/** * 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; }
/***************************************************************************** * Helpers *****************************************************************************/ static int GetSwsCpuMask(void) { int i_sws_cpu = 0; #if defined(__i386__) || defined(__x86_64__) if( vlc_CPU_MMX() ) i_sws_cpu |= SWS_CPU_CAPS_MMX; #if (LIBSWSCALE_VERSION_INT >= ((0<<16)+(5<<8)+0)) if( vlc_CPU_MMXEXT() ) i_sws_cpu |= SWS_CPU_CAPS_MMX2; #endif if( vlc_CPU_3dNOW() ) i_sws_cpu |= SWS_CPU_CAPS_3DNOW; #elif defined(__ppc__) || defined(__ppc64__) || defined(__powerpc__) if( vlc_CPU_ALTIVEC() ) i_sws_cpu |= SWS_CPU_CAPS_ALTIVEC; #endif return i_sws_cpu; }
int RenderYadif( filter_t *p_filter, picture_t *p_dst, picture_t *p_src, int i_order, int i_field ) { VLC_UNUSED(p_src); filter_sys_t *p_sys = p_filter->p_sys; /* */ assert( i_order >= 0 && i_order <= 2 ); /* 2 = soft field repeat */ assert( i_field == 0 || i_field == 1 ); /* As the pitches must match, use ONLY pictures coming from picture_New()! */ picture_t *p_prev = p_sys->pp_history[0]; picture_t *p_cur = p_sys->pp_history[1]; picture_t *p_next = p_sys->pp_history[2]; /* Account for soft field repeat. The "parity" parameter affects the algorithm like this (from yadif.h): uint8_t *prev2= parity ? prev : cur ; uint8_t *next2= parity ? cur : next; The original parity expression that was used here is: (i_field ^ (i_order == i_field)) & 1 Truth table: i_field = 0, i_order = 0 => 1 i_field = 1, i_order = 1 => 0 i_field = 1, i_order = 0 => 1 i_field = 0, i_order = 1 => 0 => equivalent with e.g. (1 - i_order) or (i_order + 1) % 2 Thus, in a normal two-field frame, parity 1 = first field (i_order == 0) parity 0 = second field (i_order == 1) Now, with three fields, where the third is a copy of the first, i_order = 0 => parity 1 (as usual) i_order = 1 => due to the repeat, prev = cur, but also next = cur. Because in such a case there is no motion (otherwise field repeat makes no sense), we don't actually need to invoke Yadif's filter(). Thus, set "parity" to 2, and use this to bypass the filter. i_order = 2 => parity 0 (as usual) */ int yadif_parity; if( p_cur && p_cur->i_nb_fields > 2 ) yadif_parity = (i_order + 1) % 3; /* 1, *2*, 0; where 2 is a special value meaning "bypass filter". */ else yadif_parity = (i_order + 1) % 2; /* 1, 0 */ /* Filter if we have all the pictures we need */ if( p_prev && p_cur && p_next ) { /* */ void (*filter)(uint8_t *dst, uint8_t *prev, uint8_t *cur, uint8_t *next, int w, int prefs, int mrefs, int parity, int mode); #if defined(HAVE_YADIF_SSSE3) if( vlc_CPU_SSSE3() ) filter = yadif_filter_line_ssse3; else #endif #if defined(HAVE_YADIF_SSE2) if( vlc_CPU_SSE2() ) filter = yadif_filter_line_sse2; else #endif #if defined(HAVE_YADIF_MMX) if( vlc_CPU_MMX() ) filter = yadif_filter_line_mmx; else #endif filter = yadif_filter_line_c; if( p_sys->chroma->pixel_size == 2 ) filter = (void (__cdecl *)(uint8_t *,uint8_t *,uint8_t *,uint8_t *,int,int,int,int,int))yadif_filter_line_c_16bit; // sunqueen modify for( int n = 0; n < p_dst->i_planes; n++ ) { const plane_t *prevp = &p_prev->p[n]; const plane_t *curp = &p_cur->p[n]; const plane_t *nextp = &p_next->p[n]; plane_t *dstp = &p_dst->p[n]; for( int y = 1; y < dstp->i_visible_lines - 1; y++ ) { if( (y % 2) == i_field || yadif_parity == 2 ) { memcpy( &dstp->p_pixels[y * dstp->i_pitch], &curp->p_pixels[y * curp->i_pitch], dstp->i_visible_pitch ); } else { int mode; /* Spatial checks only when enough data */ mode = (y >= 2 && y < dstp->i_visible_lines - 2) ? 0 : 2; assert( prevp->i_pitch == curp->i_pitch && curp->i_pitch == nextp->i_pitch ); filter( &dstp->p_pixels[y * dstp->i_pitch], &prevp->p_pixels[y * prevp->i_pitch], &curp->p_pixels[y * curp->i_pitch], &nextp->p_pixels[y * nextp->i_pitch], dstp->i_visible_pitch, y < dstp->i_visible_lines - 2 ? curp->i_pitch : -curp->i_pitch, y - 1 ? -curp->i_pitch : curp->i_pitch, yadif_parity, mode ); } /* We duplicate the first and last lines */ if( y == 1 ) memcpy(&dstp->p_pixels[(y-1) * dstp->i_pitch], &dstp->p_pixels[ y * dstp->i_pitch], dstp->i_pitch); else if( y == dstp->i_visible_lines - 2 ) memcpy(&dstp->p_pixels[(y+1) * dstp->i_pitch], &dstp->p_pixels[ y * dstp->i_pitch], dstp->i_pitch); } } p_sys->i_frame_offset = 1; /* p_cur will be rendered at next frame, too */ return VLC_SUCCESS; } else if( !p_prev && !p_cur && p_next ) { /* NOTE: For the first frame, we use the default frame offset as set by Open() or SetFilterMethod(). It is always 0. */ /* FIXME not good as it does not use i_order/i_field */ RenderX( p_dst, p_next ); return VLC_SUCCESS; } else { p_sys->i_frame_offset = 1; /* p_cur will be rendered at next frame */ return VLC_EGENERIC; } }
/***************************************************************************** * 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; }