/** * Maps CPU capabilities computed by VLC to libav DSP mask. */ unsigned GetVlcDspMask( void ) { unsigned mask = 0; #if defined (__i386__) || defined (__x86_64__) if( !vlc_CPU_MMX() ) mask |= AV_CPU_FLAG_MMX; if( !vlc_CPU_MMXEXT() ) mask |= AV_CPU_FLAG_MMX2; if( !vlc_CPU_3dNOW() ) mask |= AV_CPU_FLAG_3DNOW; if( !vlc_CPU_SSE() ) mask |= AV_CPU_FLAG_SSE; if( !vlc_CPU_SSE2() ) mask |= AV_CPU_FLAG_SSE2; # ifdef AV_CPU_FLAG_SSE3 if( !vlc_CPU_SSE3() ) mask |= AV_CPU_FLAG_SSE3; # endif # ifdef AV_CPU_FLAG_SSSE3 if( !vlc_CPU_SSSE3() ) mask |= AV_CPU_FLAG_SSSE3; # endif # ifdef AV_CPU_FLAG_SSE4 if( !vlc_CPU_SSE4_1() ) mask |= AV_CPU_FLAG_SSE4; # endif # ifdef AV_CPU_FLAG_SSE42 if( !vlc_CPU_SSE4_2() ) mask |= AV_CPU_FLAG_SSE42; # endif # ifdef AV_CPU_FLAG_AVX if( !vlc_CPU_AVX() ) mask |= AV_CPU_FLAG_AVX; # endif # ifdef AV_CPU_FLAG_XOP if( !vlc_CPU_XOP() ) mask |= AV_CPU_FLAG_XOP; # endif # ifdef AV_CPU_FLAG_FMA4 if( !vlc_CPU_FMA4() ) mask |= AV_CPU_FLAG_FMA4; # endif #endif #if defined (__ppc__) || defined (__ppc64__) || defined (__powerpc__) if( !vlc_CPU_ALTIVEC() ) mask |= AV_CPU_FLAG_ALTIVEC; #endif #if defined ( __arm__) #if LIBAVUTIL_VERSION_INT >= ((51<<16)+(29<<8)+0) if( !vlc_CPU_ARM_NEON() ) mask |= AV_CPU_FLAG_NEON; #endif #endif return mask; }
/***************************************************************************** * OpenFilter: *****************************************************************************/ static int OpenFilter( vlc_object_t *p_this ) { filter_t *p_filter = (filter_t *)p_this; if (!vlc_CPU_ARM_NEON()) return VLC_EGENERIC; audio_format_t fmt_in = p_filter->fmt_in.audio; audio_format_t fmt_out = p_filter->fmt_out.audio; fmt_in.i_format = p_filter->fmt_in.i_codec; fmt_out.i_format = p_filter->fmt_out.i_codec; if( fmt_in.i_format != VLC_CODEC_FL32 || fmt_in.i_format != fmt_out.i_format || fmt_in.i_rate != fmt_out.i_rate ) { return VLC_EGENERIC; } if( fmt_in.i_physical_channels == fmt_out.i_physical_channels && fmt_in.i_original_channels == fmt_out.i_original_channels ) { return VLC_EGENERIC; } const bool b_input_7 = (fmt_in.i_physical_channels & ~AOUT_CHAN_LFE) == AOUT_CHANS_7_0; const bool b_input_5 = ( (fmt_in.i_physical_channels & AOUT_CHANS_5_0) == AOUT_CHANS_5_0 || (fmt_in.i_physical_channels & AOUT_CHANS_5_0_MIDDLE) == AOUT_CHANS_5_0_MIDDLE ); const bool b_input_4 = (fmt_in.i_physical_channels & ~AOUT_CHAN_LFE) == AOUT_CHANS_4_CENTER_REAR; const bool b_input_3 = (fmt_in.i_physical_channels & ~AOUT_CHAN_LFE) == AOUT_CHANS_3_0; const bool b_output_1 = fmt_out.i_physical_channels == AOUT_CHAN_CENTER; const bool b_output_2 = fmt_out.i_physical_channels == AOUT_CHANS_2_0; const bool b_output_4 = fmt_out.i_physical_channels == AOUT_CHANS_4_0; /* Only conversion to Mono, Stereo and 4.0 right now */ /* Only from 7/7.1/5/5.1/3/3.1/2.0 * XXX 5.X rear and middle are handled the same way */ TRY_FILTER(7,2) TRY_FILTER(5,2) TRY_FILTER(4,2) TRY_FILTER(3,2) TRY_FILTER(7,1) TRY_FILTER(5,1) TRY_FILTER(7,4) TRY_FILTER(5,4) return VLC_EGENERIC; }
static int Open (vlc_object_t *obj) { filter_t *filter = (filter_t *)obj; if (!vlc_CPU_ARM_NEON()) return VLC_EGENERIC; if (((filter->fmt_in.video.i_width | filter->fmt_in.video.i_height) & 1) || (filter->fmt_in.video.i_width != filter->fmt_out.video.i_width) || (filter->fmt_in.video.i_height != filter->fmt_out.video.i_height)) return VLC_EGENERIC; switch (filter->fmt_out.video.i_chroma) { case VLC_CODEC_RGB16: switch (filter->fmt_in.video.i_chroma) { case VLC_CODEC_I420: filter->pf_video_filter = I420_RV16_Filter; break; default: return VLC_EGENERIC; } break; case VLC_CODEC_RGB32: if( filter->fmt_out.video.i_rmask != 0x000000ff || filter->fmt_out.video.i_gmask != 0x0000ff00 || filter->fmt_out.video.i_bmask != 0x00ff0000 ) return VLC_EGENERIC; switch (filter->fmt_in.video.i_chroma) { case VLC_CODEC_I420: filter->pf_video_filter = I420_RGBA_Filter; break; case VLC_CODEC_YV12: filter->pf_video_filter = YV12_RGBA_Filter; break; case VLC_CODEC_NV21: filter->pf_video_filter = NV21_RGBA_Filter; break; case VLC_CODEC_NV12: filter->pf_video_filter = NV12_RGBA_Filter; break; default: return VLC_EGENERIC; } break; default: return VLC_EGENERIC; } //precompute some values for the C version /*const int coefY = (int)(1.164 * 32768 + 0.5); const int coefRV = (int)(1.793 * 32768 + 0.5); const int coefGU = (int)(0.213 * 32768 + 0.5); const int coefGV = (int)(0.533 * 32768 + 0.5); const int coefBU = (int)(2.113 * 32768 + 0.5); for (int i=0; i<256; ++i) { CoefY[i] = coefY * (i-16) + 16384; CoefRV[i] = coefRV*(i-128); CoefGU[i] = -coefGU*(i-128); CoefGV[i] = -coefGV*(i-128); CoefBU[i] = coefBU*(i-128); }*/ msg_Dbg(filter, "%4.4s(%dx%d) to %4.4s(%dx%d)", (char*)&filter->fmt_in.video.i_chroma, filter->fmt_in.video.i_width, filter->fmt_in.video.i_height, (char*)&filter->fmt_out.video.i_chroma, filter->fmt_out.video.i_width, filter->fmt_out.video.i_height); return VLC_SUCCESS; }
static int Open (vlc_object_t *obj) { filter_t *filter = (filter_t *)obj; if (!vlc_CPU_ARM_NEON()) return VLC_EGENERIC; if ((filter->fmt_in.video.i_width != filter->fmt_out.video.i_width) || (filter->fmt_in.video.i_height != filter->fmt_out.video.i_height)) return VLC_EGENERIC; switch (filter->fmt_in.video.i_chroma) { /* Planar to packed */ case VLC_CODEC_I420: switch (filter->fmt_out.video.i_chroma) { case VLC_CODEC_YUYV: filter->pf_video_filter = I420_YUYV_Filter; break; case VLC_CODEC_UYVY: filter->pf_video_filter = I420_UYVY_Filter; break; case VLC_CODEC_YVYU: filter->pf_video_filter = I420_YVYU_Filter; break; case VLC_CODEC_VYUY: filter->pf_video_filter = I420_VYUY_Filter; break; default: return VLC_EGENERIC; } break; case VLC_CODEC_YV12: switch (filter->fmt_out.video.i_chroma) { case VLC_CODEC_YUYV: filter->pf_video_filter = I420_YVYU_Filter; break; case VLC_CODEC_UYVY: filter->pf_video_filter = I420_VYUY_Filter; break; case VLC_CODEC_YVYU: filter->pf_video_filter = I420_YUYV_Filter; break; case VLC_CODEC_VYUY: filter->pf_video_filter = I420_UYVY_Filter; break; default: return VLC_EGENERIC; } break; case VLC_CODEC_I422: switch (filter->fmt_out.video.i_chroma) { case VLC_CODEC_YUYV: filter->pf_video_filter = I422_YUYV_Filter; break; case VLC_CODEC_UYVY: filter->pf_video_filter = I422_UYVY_Filter; break; case VLC_CODEC_YVYU: filter->pf_video_filter = I422_YVYU_Filter; break; case VLC_CODEC_VYUY: filter->pf_video_filter = I422_VYUY_Filter; break; default: return VLC_EGENERIC; } break; /* Packed to planar */ case VLC_CODEC_YUYV: switch (filter->fmt_out.video.i_chroma) { case VLC_CODEC_I422: filter->pf_video_filter = YUYV_I422_Filter; break; default: return VLC_EGENERIC; } case VLC_CODEC_UYVY: switch (filter->fmt_out.video.i_chroma) { case VLC_CODEC_I422: filter->pf_video_filter = UYVY_I422_Filter; break; default: return VLC_EGENERIC; } case VLC_CODEC_YVYU: switch (filter->fmt_out.video.i_chroma) { case VLC_CODEC_I422: filter->pf_video_filter = YVYU_I422_Filter; break; default: return VLC_EGENERIC; } case VLC_CODEC_VYUY: switch (filter->fmt_out.video.i_chroma) { case VLC_CODEC_I422: filter->pf_video_filter = VYUY_I422_Filter; break; default: return VLC_EGENERIC; } default: return VLC_EGENERIC; } return VLC_SUCCESS; }
/***************************************************************************** * OpenDecoder: probe the decoder and return score *****************************************************************************/ static int OpenDecoder( vlc_object_t *p_this ) { decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; uint32_t i_accel = 0; if( p_dec->fmt_in.i_codec != VLC_CODEC_MPGV ) return VLC_EGENERIC; /* Select onl recognized original format (standard mpeg video) */ switch( p_dec->fmt_in.i_original_fourcc ) { case VLC_FOURCC('m','p','g','1'): case VLC_FOURCC('m','p','g','2'): case VLC_FOURCC('m','p','g','v'): case VLC_FOURCC('P','I','M','1'): case VLC_FOURCC('h','d','v','2'): break; default: if( p_dec->fmt_in.i_original_fourcc ) return VLC_EGENERIC; break; } /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = calloc( 1, sizeof(*p_sys)) ) == NULL ) return VLC_ENOMEM; /* Initialize the thread properties */ p_sys->p_mpeg2dec = NULL; p_sys->p_synchro = NULL; p_sys->p_info = NULL; p_sys->i_current_pts = 0; p_sys->i_previous_pts = 0; p_sys->i_current_dts = 0; p_sys->i_previous_dts = 0; p_sys->i_sar_num = 0; p_sys->i_sar_den = 0; p_sys->b_garbage_pic = false; p_sys->b_slice_i = false; p_sys->b_second_field = false; p_sys->b_skip = false; p_sys->b_preroll = false; DpbInit( p_dec ); p_sys->i_cc_pts = 0; p_sys->i_cc_dts = 0; p_sys->i_cc_flags = 0; #if MPEG2_RELEASE >= MPEG2_VERSION (0, 5, 0) p_dec->pf_get_cc = GetCc; cc_Init( &p_sys->cc ); #endif p_sys->p_gop_user_data = NULL; p_sys->i_gop_user_data = 0; #if defined( __i386__ ) || defined( __x86_64__ ) if( vlc_CPU_MMX() ) i_accel |= MPEG2_ACCEL_X86_MMX; if( vlc_CPU_3dNOW() ) i_accel |= MPEG2_ACCEL_X86_3DNOW; if( vlc_CPU_MMXEXT() ) i_accel |= MPEG2_ACCEL_X86_MMXEXT; #elif defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc64__ ) if( vlc_CPU_ALTIVEC() ) i_accel |= MPEG2_ACCEL_PPC_ALTIVEC; #elif defined(__arm__) # ifdef MPEG2_ACCEL_ARM i_accel |= MPEG2_ACCEL_ARM; # endif # ifdef MPEG2_ACCEL_ARM_NEON if( vlc_CPU_ARM_NEON() ) i_accel |= MPEG2_ACCEL_ARM_NEON; # endif /* TODO: sparc */ #else /* If we do not know this CPU, trust libmpeg2's feature detection */ i_accel = MPEG2_ACCEL_DETECT; #endif /* Set CPU acceleration features */ mpeg2_accel( i_accel ); /* Initialize decoder */ p_sys->p_mpeg2dec = mpeg2_init(); if( p_sys->p_mpeg2dec == NULL) { msg_Err( p_dec, "mpeg2_init() failed" ); free( p_sys ); return VLC_EGENERIC; } p_sys->p_info = mpeg2_info( p_sys->p_mpeg2dec ); p_dec->pf_decode_video = DecodeBlock; p_dec->fmt_out.i_cat = VIDEO_ES; p_dec->fmt_out.i_codec = 0; return VLC_SUCCESS; }
int Open( vlc_object_t *p_this ) { filter_t *p_filter = (filter_t*)p_this; filter_sys_t *p_sys; const vlc_fourcc_t fourcc = p_filter->fmt_in.video.i_chroma; const vlc_chroma_description_t *chroma = vlc_fourcc_GetChromaDescription( fourcc ); if( !vlc_fourcc_IsYUV( fourcc ) || !chroma || chroma->plane_count != 3 || chroma->pixel_size > 2 ) { msg_Err( p_filter, "Unsupported chroma (%4.4s)", (char*)&fourcc ); return VLC_EGENERIC; } /* */ p_sys = p_filter->p_sys = malloc( sizeof( *p_sys ) ); if( !p_sys ) return VLC_ENOMEM; p_sys->chroma = chroma; p_sys->i_mode = DEINTERLACE_BLEND; p_sys->b_double_rate = false; p_sys->b_half_height = true; p_sys->b_use_frame_history = false; for( int i = 0; i < METADATA_SIZE; i++ ) { p_sys->meta.pi_date[i] = VLC_TS_INVALID; p_sys->meta.pi_nb_fields[i] = 2; p_sys->meta.pb_top_field_first[i] = true; } p_sys->i_frame_offset = 0; /* start with default value (first-ever frame cannot have offset) */ for( int i = 0; i < HISTORY_SIZE; i++ ) p_sys->pp_history[i] = NULL; IVTCClearState( p_filter ); #if defined(CAN_COMPILE_C_ALTIVEC) if( chroma->pixel_size == 1 && vlc_CPU_ALTIVEC() ) p_sys->pf_merge = MergeAltivec; else #endif #if defined(CAN_COMPILE_SSE2) if( vlc_CPU_SSE2() ) { p_sys->pf_merge = chroma->pixel_size == 1 ? Merge8BitSSE2 : Merge16BitSSE2; p_sys->pf_end_merge = EndMMX; } else #endif #if defined(CAN_COMPILE_MMXEXT) if( chroma->pixel_size == 1 && vlc_CPU_MMXEXT() ) { p_sys->pf_merge = MergeMMXEXT; p_sys->pf_end_merge = EndMMX; } else #endif #if defined(CAN_COMPILE_3DNOW) if( chroma->pixel_size == 1 && vlc_CPU_3dNOW() ) { p_sys->pf_merge = Merge3DNow; p_sys->pf_end_merge = End3DNow; } else #endif #if defined(CAN_COMPILE_ARM) if( vlc_CPU_ARM_NEON() ) p_sys->pf_merge = (chroma->pixel_size == 1) ? merge8_arm_neon : merge16_arm_neon; else if( vlc_CPU_ARMv6() ) p_sys->pf_merge = (chroma->pixel_size == 1) ? merge8_armv6 : merge16_armv6; else #endif { p_sys->pf_merge = chroma->pixel_size == 1 ? Merge8BitGeneric : Merge16BitGeneric; #if defined(__i386__) || defined(__x86_64__) p_sys->pf_end_merge = NULL; #endif } /* */ config_ChainParse( p_filter, FILTER_CFG_PREFIX, ppsz_filter_options, p_filter->p_cfg ); char *psz_mode = var_GetNonEmptyString( p_filter, FILTER_CFG_PREFIX "mode" ); SetFilterMethod( p_filter, psz_mode ); free( psz_mode ); if( p_sys->i_mode == DEINTERLACE_PHOSPHOR ) { int i_c420 = var_GetInteger( p_filter, FILTER_CFG_PREFIX "phosphor-chroma" ); if( i_c420 != PC_LATEST && i_c420 != PC_ALTLINE && i_c420 != PC_BLEND && i_c420 != PC_UPCONVERT ) { msg_Dbg( p_filter, "Phosphor 4:2:0 input chroma mode not set"\ "or out of range (valid: 1, 2, 3 or 4), "\ "using default" ); i_c420 = PC_ALTLINE; } msg_Dbg( p_filter, "using Phosphor 4:2:0 input chroma mode %d", i_c420 ); /* This maps directly to the phosphor_chroma_t enum. */ p_sys->phosphor.i_chroma_for_420 = i_c420; int i_dimmer = var_GetInteger( p_filter, FILTER_CFG_PREFIX "phosphor-dimmer" ); if( i_dimmer < 1 || i_dimmer > 4 ) { msg_Dbg( p_filter, "Phosphor dimmer strength not set "\ "or out of range (valid: 1, 2, 3 or 4), "\ "using default" ); i_dimmer = 2; /* low */ } msg_Dbg( p_filter, "using Phosphor dimmer strength %d", i_dimmer ); /* The internal value ranges from 0 to 3. */ p_sys->phosphor.i_dimmer_strength = i_dimmer - 1; } else { p_sys->phosphor.i_chroma_for_420 = PC_ALTLINE; p_sys->phosphor.i_dimmer_strength = 1; } /* */ video_format_t fmt; GetOutputFormat( p_filter, &fmt, &p_filter->fmt_in.video ); if( !p_filter->b_allow_fmt_out_change && ( fmt.i_chroma != p_filter->fmt_in.video.i_chroma || fmt.i_height != p_filter->fmt_in.video.i_height ) ) { Close( VLC_OBJECT(p_filter) ); return VLC_EGENERIC; } p_filter->fmt_out.video = fmt; p_filter->fmt_out.i_codec = fmt.i_chroma; p_filter->pf_video_filter = Deinterlace; p_filter->pf_video_flush = Flush; p_filter->pf_video_mouse = Mouse; msg_Dbg( p_filter, "deinterlacing" ); return VLC_SUCCESS; }