X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_filter%2Fdeinterlace.c;h=5fb23deca6d13ff424ed693fa71e066acf0ebc46;hb=bc09c365ab435fda0185e60a423f69d6dfa348c8;hp=70d9b2ce4500ea35f2fd99728cc76fe08d3884ee;hpb=62c53d4ac373ce7032d3dacbb008eff913cc53a6;p=vlc diff --git a/modules/video_filter/deinterlace.c b/modules/video_filter/deinterlace.c index 70d9b2ce45..5fb23deca6 100644 --- a/modules/video_filter/deinterlace.c +++ b/modules/video_filter/deinterlace.c @@ -98,7 +98,7 @@ static void RenderMean ( filter_t *, picture_t *, picture_t * ); static void RenderBlend ( filter_t *, picture_t *, picture_t * ); static void RenderLinear ( filter_t *, picture_t *, picture_t *, int ); static void RenderX ( picture_t *, picture_t * ); -static void RenderYadif ( filter_t *, picture_t *, picture_t *, int, int ); +static int RenderYadif ( filter_t *, picture_t *, picture_t *, int, int ); static void MergeGeneric ( void *, const void *, const void *, size_t ); #if defined(CAN_COMPILE_C_ALTIVEC) @@ -137,6 +137,8 @@ struct filter_sys_t void (*pf_merge) ( void *, const void *, const void *, size_t ); void (*pf_end_merge) ( void ); + mtime_t i_last_date; + /* Yadif */ picture_t *pp_history[HISTORY_SIZE]; }; @@ -829,7 +831,8 @@ static void MergeNEON (void *restrict out, const void *in1, "vst1.u8 {q10-q11}, [%[out],:128]!\n" : [out] "+r" (outp), [in1] "+r" (in1p), [in2] "+r" (in2p) : - : "q0", "q1", "q2", "memory"); + : "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", + "q8", "q9", "q10", "q11", "memory"); else while (outp < end) asm volatile ( @@ -845,7 +848,8 @@ static void MergeNEON (void *restrict out, const void *in1, "vst1.u8 {q10-q11}, [%[out],:128]!\n" : [out] "+r" (outp), [in1] "+r" (in1p), [in2] "+r" (in2p) : - : "q0", "q1", "q2", "memory"); + : "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", + "q8", "q9", "q10", "q11", "memory"); n &= 15; if (n) MergeGeneric (outp, in1p, in2p, n); @@ -1432,7 +1436,7 @@ typedef intptr_t x86_reg; /* yadif.h comes from vf_yadif.c of mplayer project */ #include "yadif.h" -static void RenderYadif( filter_t *p_filter, picture_t *p_dst, picture_t *p_src, int i_order, int i_field ) +static int RenderYadif( filter_t *p_filter, picture_t *p_dst, picture_t *p_src, int i_order, int i_field ) { filter_sys_t *p_sys = p_filter->p_sys; @@ -1515,12 +1519,17 @@ static void RenderYadif( filter_t *p_filter, picture_t *p_dst, picture_t *p_src, /* */ p_dst->date = (p_next->date - p_cur->date) * i_order / 2 + p_cur->date; + return VLC_SUCCESS; + } + else if( !p_prev && !p_cur && p_next ) + { + /* FIXME not good as it does not use i_order/i_field */ + RenderX( p_dst, p_next ); + return VLC_SUCCESS; } else { - /* Fallback to something simple - * XXX it is wrong when we have 2 pictures, we should not output a picture */ - RenderX( p_dst, p_src ); + return VLC_EGENERIC; } } @@ -1530,77 +1539,111 @@ static void RenderYadif( filter_t *p_filter, picture_t *p_dst, picture_t *p_src, static picture_t *Deinterlace( filter_t *p_filter, picture_t *p_pic ) { filter_sys_t *p_sys = p_filter->p_sys; - picture_t *p_pic_dst; + picture_t *p_dst[2]; /* Request output picture */ - p_pic_dst = filter_NewPicture( p_filter ); - if( p_pic_dst == NULL ) + p_dst[0] = filter_NewPicture( p_filter ); + if( p_dst[0] == NULL ) { picture_Release( p_pic ); return NULL; } + picture_CopyProperties( p_dst[0], p_pic ); + + if( p_sys->b_double_rate ) + { + p_dst[0]->p_next = + p_dst[1] = filter_NewPicture( p_filter ); + if( p_dst[1] ) + { + picture_CopyProperties( p_dst[1], p_pic ); + /* XXX it's not really good especially for the first picture, but + * I don't think that delaying by one frame is worth it */ + if( p_sys->i_last_date > VLC_TS_INVALID && p_pic->date > VLC_TS_INVALID ) + p_dst[1]->date = p_pic->date + (p_pic->date - p_sys->i_last_date) / 2; + } + p_sys->i_last_date = p_pic->date; + } + else + { + p_dst[1] = NULL; + } switch( p_sys->i_mode ) { case DEINTERLACE_DISCARD: - RenderDiscard( p_filter, p_pic_dst, p_pic, 0 ); + RenderDiscard( p_filter, p_dst[0], p_pic, 0 ); break; case DEINTERLACE_BOB: -#if 0 - RenderBob( p_filter, pp_outpic[0], p_pic, !p_pic->b_top_field_first ); - RenderBob( p_filter, pp_outpic[1], p_pic, p_pic->b_top_field_first ); - break; -#endif + RenderBob( p_filter, p_dst[0], p_pic, !p_pic->b_top_field_first ); + if( p_dst[1] ) + RenderBob( p_filter, p_dst[1], p_pic, p_pic->b_top_field_first ); + break;; case DEINTERLACE_LINEAR: -#if 0 - RenderLinear( p_filter, pp_outpic[0], p_pic, !p_pic->b_top_field_first ); - RenderLinear( p_filter, pp_outpic[1], p_pic, p_pic->b_top_field_first ); -#endif - msg_Err( p_filter, "doubling the frame rate is not supported yet" ); - picture_Release( p_pic_dst ); - picture_Release( p_pic ); - return NULL; + RenderLinear( p_filter, p_dst[0], p_pic, !p_pic->b_top_field_first ); + if( p_dst[1] ) + RenderLinear( p_filter, p_dst[1], p_pic, p_pic->b_top_field_first ); + break; case DEINTERLACE_MEAN: - RenderMean( p_filter, p_pic_dst, p_pic ); + RenderMean( p_filter, p_dst[0], p_pic ); break; case DEINTERLACE_BLEND: - RenderBlend( p_filter, p_pic_dst, p_pic ); + RenderBlend( p_filter, p_dst[0], p_pic ); break; case DEINTERLACE_X: - RenderX( p_pic_dst, p_pic ); + RenderX( p_dst[0], p_pic ); break; case DEINTERLACE_YADIF: - msg_Err( p_filter, "delaying frames is not supported yet" ); - //RenderYadif( p_vout, pp_outpic[0], p_pic, 0, 0 ); - picture_Release( p_pic_dst ); - picture_Release( p_pic ); - return NULL; + if( RenderYadif( p_filter, p_dst[0], p_pic, 0, 0 ) ) + goto drop; + break; case DEINTERLACE_YADIF2X: - msg_Err( p_filter, "doubling the frame rate is not supported yet" ); - //RenderYadif( p_vout, pp_outpic[0], p_pic, 0, !p_pic->b_top_field_first ); - //RenderYadif( p_vout, pp_outpic[1], p_pic, 1, p_pic->b_top_field_first ); - picture_Release( p_pic_dst ); - picture_Release( p_pic ); - return NULL; + if( RenderYadif( p_filter, p_dst[0], p_pic, 0, !p_pic->b_top_field_first ) ) + goto drop; + if( p_dst[1] ) + RenderYadif( p_filter, p_dst[1], p_pic, 1, p_pic->b_top_field_first ); + break; } - picture_CopyProperties( p_pic_dst, p_pic ); - p_pic_dst->b_progressive = true; + p_dst[0]->b_progressive = true; + if( p_dst[1] ) + p_dst[1]->b_progressive = true; picture_Release( p_pic ); - return p_pic_dst; + return p_dst[0]; + +drop: + picture_Release( p_dst[0] ); + if( p_dst[1] ) + picture_Release( p_dst[1] ); + picture_Release( p_pic ); + return NULL; +} + +static void Flush( filter_t *p_filter ) +{ + filter_sys_t *p_sys = p_filter->p_sys; + + p_sys->i_last_date = VLC_TS_INVALID; + for( int i = 0; i < HISTORY_SIZE; i++ ) + { + if( p_sys->pp_history[i] ) + picture_Release( p_sys->pp_history[i] ); + p_sys->pp_history[i] = NULL; + } } static int Mouse( filter_t *p_filter, vlc_mouse_t *p_mouse, const vlc_mouse_t *p_old, const vlc_mouse_t *p_new ) { + VLC_UNUSED(p_old); *p_mouse = *p_new; if( p_filter->p_sys->b_half_height ) p_mouse->i_y *= 2; @@ -1627,6 +1670,9 @@ static int Open( vlc_object_t *p_this ) p_sys->i_mode = DEINTERLACE_BLEND; p_sys->b_double_rate = false; p_sys->b_half_height = true; + p_sys->i_last_date = VLC_TS_INVALID; + for( int i = 0; i < HISTORY_SIZE; i++ ) + p_sys->pp_history[i] = NULL; #if defined(CAN_COMPILE_C_ALTIVEC) if( vlc_CPU() & CPU_CAPABILITY_ALTIVEC ) @@ -1694,6 +1740,7 @@ static int Open( vlc_object_t *p_this ) 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" ); @@ -1708,6 +1755,7 @@ static void Close( vlc_object_t *p_this ) { filter_t *p_filter = (filter_t*)p_this; + Flush( p_filter ); free( p_filter->p_sys ); }