📄 deinterlace.c
字号:
{ const uint8_t *s = &src[y*i_src]; for( x = 0; x < i_width; x++ ) { fr += ssd(s[ x] - s[1*i_src+x]); ff += ssd(s[ x] - s[2*i_src+x]); } if( ff < fr && fr > i_width / 2 ) fc++; } return fc < 2 ? VLC_FALSE : VLC_TRUE;}static inline void XDeintNxNFrame( uint8_t *dst, int i_dst, uint8_t *src, int i_src, int i_width, int i_height ){ int y, x; /* Progressive */ for( y = 0; y < i_height; y += 2 ) { memcpy( dst, src, i_width ); dst += i_dst; if( y < i_height - 2 ) { for( x = 0; x < i_width; x++ ) dst[x] = (src[x] + 2*src[1*i_src+x] + src[2*i_src+x] + 2 ) >> 2; } else { /* Blend last line */ for( x = 0; x < i_width; x++ ) dst[x] = (src[x] + src[1*i_src+x] ) >> 1; } dst += 1*i_dst; src += 2*i_src; }}static inline void XDeintNxNField( uint8_t *dst, int i_dst, uint8_t *src, int i_src, int i_width, int i_height ){ int y, x; /* Interlaced */ for( y = 0; y < i_height; y += 2 ) { memcpy( dst, src, i_width ); dst += i_dst; if( y < i_height - 2 ) { for( x = 0; x < i_width; x++ ) dst[x] = (src[x] + src[2*i_src+x] ) >> 1; } else { /* Blend last line */ for( x = 0; x < i_width; x++ ) dst[x] = (src[x] + src[i_src+x]) >> 1; } dst += 1*i_dst; src += 2*i_src; }}static inline void XDeintNxN( uint8_t *dst, int i_dst, uint8_t *src, int i_src, int i_width, int i_height ){ if( XDeintNxNDetect( src, i_src, i_width, i_height ) ) XDeintNxNField( dst, i_dst, src, i_src, i_width, i_height ); else XDeintNxNFrame( dst, i_dst, src, i_src, i_width, i_height );}static inline int median( int a, int b, int c ){ int min = a, max =a; if( b < min ) min = b; else max = b; if( c < min ) min = c; else if( c > max ) max = c; return a + b + c - min - max;}/* XDeintBand8x8: */static inline void XDeintBand8x8C( uint8_t *dst, int i_dst, uint8_t *src, int i_src, const int i_mbx, int i_modx ){ int x; for( x = 0; x < i_mbx; x++ ) { int s; if( ( s = XDeint8x8DetectC( src, i_src ) ) ) { if( x == 0 || x == i_mbx - 1 ) XDeint8x8FieldEC( dst, i_dst, src, i_src ); else XDeint8x8FieldC( dst, i_dst, src, i_src ); } else { XDeint8x8MergeC( dst, i_dst, &src[0*i_src], 2*i_src, &src[1*i_src], 2*i_src ); } dst += 8; src += 8; } if( i_modx ) XDeintNxN( dst, i_dst, src, i_src, i_modx, 8 );}#ifdef CAN_COMPILE_MMXEXTstatic inline void XDeintBand8x8MMXEXT( uint8_t *dst, int i_dst, uint8_t *src, int i_src, const int i_mbx, int i_modx ){ int x; /* Reset current line */ for( x = 0; x < i_mbx; x++ ) { int s; if( ( s = XDeint8x8DetectMMXEXT( src, i_src ) ) ) { if( x == 0 || x == i_mbx - 1 ) XDeint8x8FieldEMMXEXT( dst, i_dst, src, i_src ); else XDeint8x8FieldMMXEXT( dst, i_dst, src, i_src ); } else { XDeint8x8MergeMMXEXT( dst, i_dst, &src[0*i_src], 2*i_src, &src[1*i_src], 2*i_src ); } dst += 8; src += 8; } if( i_modx ) XDeintNxN( dst, i_dst, src, i_src, i_modx, 8 );}#endifstatic void RenderX( vout_thread_t *p_vout, picture_t *p_outpic, picture_t *p_pic ){ vout_sys_t *p_sys = p_vout->p_sys; int i_plane; /* Copy image and skip lines */ for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ ) { const int i_mby = ( p_outpic->p[i_plane].i_visible_lines + 7 )/8 - 1; const int i_mbx = p_outpic->p[i_plane].i_visible_pitch/8; const int i_mody = p_outpic->p[i_plane].i_visible_lines - 8*i_mby; const int i_modx = p_outpic->p[i_plane].i_visible_pitch - 8*i_mbx; const int i_dst = p_outpic->p[i_plane].i_pitch; const int i_src = p_pic->p[i_plane].i_pitch; int y, x; for( y = 0; y < i_mby; y++ ) { uint8_t *dst = &p_outpic->p[i_plane].p_pixels[8*y*i_dst]; uint8_t *src = &p_pic->p[i_plane].p_pixels[8*y*i_src];#ifdef CAN_COMPILE_MMXEXT if( p_vout->p_libvlc->i_cpu & CPU_CAPABILITY_MMXEXT ) XDeintBand8x8MMXEXT( dst, i_dst, src, i_src, i_mbx, i_modx ); else#endif XDeintBand8x8C( dst, i_dst, src, i_src, i_mbx, i_modx ); } /* Last line (C only)*/ if( i_mody ) { uint8_t *dst = &p_outpic->p[i_plane].p_pixels[8*y*i_dst]; uint8_t *src = &p_pic->p[i_plane].p_pixels[8*y*i_src]; for( x = 0; x < i_mbx; x++ ) { XDeintNxN( dst, i_dst, src, i_src, 8, i_mody ); dst += 8; src += 8; } if( i_modx ) XDeintNxN( dst, i_dst, src, i_src, i_modx, i_mody ); } }#ifdef CAN_COMPILE_MMXEXT if( p_vout->p_libvlc->i_cpu & CPU_CAPABILITY_MMXEXT ) emms();#endif}/***************************************************************************** * SendEvents: forward mouse and keyboard events to the parent p_vout *****************************************************************************/static int SendEvents( vlc_object_t *p_this, char const *psz_var, vlc_value_t oldval, vlc_value_t newval, void *_p_vout ){ vout_thread_t *p_vout = (vout_thread_t *)_p_vout; vlc_value_t sentval = newval; if( !strcmp( psz_var, "mouse-y" ) ) { switch( p_vout->p_sys->i_mode ) { case DEINTERLACE_MEAN: case DEINTERLACE_DISCARD: sentval.i_int *= 2; break; } } var_Set( p_vout, psz_var, sentval ); return VLC_SUCCESS;}/***************************************************************************** * FilterCallback: called when changing the deinterlace method on the fly. *****************************************************************************/static int FilterCallback( vlc_object_t *p_this, char const *psz_cmd, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ vout_thread_t * p_vout = (vout_thread_t *)p_this; int i_old_mode = p_vout->p_sys->i_mode; msg_Dbg( p_vout, "using %s deinterlace mode", newval.psz_string ); vlc_mutex_lock( &p_vout->p_sys->filter_lock ); SetFilterMethod( p_vout, newval.psz_string ); switch( p_vout->render.i_chroma ) { case VLC_FOURCC('I','4','2','2'): vlc_mutex_unlock( &p_vout->p_sys->filter_lock ); return VLC_SUCCESS; break; case VLC_FOURCC('I','4','2','0'): case VLC_FOURCC('I','Y','U','V'): case VLC_FOURCC('Y','V','1','2'): switch( p_vout->p_sys->i_mode ) { case DEINTERLACE_MEAN: case DEINTERLACE_DISCARD: if( ( i_old_mode == DEINTERLACE_MEAN ) || ( i_old_mode == DEINTERLACE_DISCARD ) ) { vlc_mutex_unlock( &p_vout->p_sys->filter_lock ); return VLC_SUCCESS; } break; case DEINTERLACE_BOB: case DEINTERLACE_BLEND: case DEINTERLACE_LINEAR: if( ( i_old_mode == DEINTERLACE_BOB ) || ( i_old_mode == DEINTERLACE_BLEND ) || ( i_old_mode == DEINTERLACE_LINEAR ) ) { vlc_mutex_unlock( &p_vout->p_sys->filter_lock ); return VLC_SUCCESS; } break; } break; default: break; } /* We need to kill the old vout */ DEL_CALLBACKS( p_vout->p_sys->p_vout, SendEvents ); vlc_object_detach( p_vout->p_sys->p_vout ); vout_Destroy( p_vout->p_sys->p_vout ); /* Try to open a new video output */ p_vout->p_sys->p_vout = SpawnRealVout( p_vout ); if( p_vout->p_sys->p_vout == NULL ) { /* Everything failed */ msg_Err( p_vout, "cannot open vout, aborting" ); vlc_mutex_unlock( &p_vout->p_sys->filter_lock ); return VLC_EGENERIC; } ADD_CALLBACKS( p_vout->p_sys->p_vout, SendEvents ); vlc_mutex_unlock( &p_vout->p_sys->filter_lock ); return VLC_SUCCESS;}/***************************************************************************** * SendEventsToChild: forward events to the child/children vout *****************************************************************************/static int SendEventsToChild( vlc_object_t *p_this, char const *psz_var, vlc_value_t oldval, vlc_value_t newval, void *p_data ){ vout_thread_t *p_vout = (vout_thread_t *)p_this; var_Set( p_vout->p_sys->p_vout, psz_var, newval ); return VLC_SUCCESS;}/***************************************************************************** * video filter2 functions *****************************************************************************/static picture_t *Deinterlace( filter_t *p_filter, picture_t *p_pic ){ vout_thread_t *p_vout = (vout_thread_t *)p_filter->p_sys; picture_t *p_pic_dst; /* Request output picture */ p_pic_dst = p_filter->pf_vout_buffer_new( p_filter ); if( p_pic_dst == NULL ) { msg_Warn( p_filter, "can't get output picture" ); return NULL; } switch( p_vout->p_sys->i_mode ) { case DEINTERLACE_DISCARD:#if 0 RenderDiscard( p_vout, p_pic_dst, p_pic, 0 );#endif msg_Err( p_vout, "discarding lines is not supported yet" ); p_pic_dst->pf_release( p_pic_dst ); return p_pic; break; case DEINTERLACE_BOB:#if 0 RenderBob( p_vout, pp_outpic[0], p_pic, 0 ); RenderBob( p_vout, pp_outpic[1], p_pic, 1 ); break;#endif case DEINTERLACE_LINEAR:#if 0 RenderLinear( p_vout, pp_outpic[0], p_pic, 0 ); RenderLinear( p_vout, pp_outpic[1], p_pic, 1 );#endif msg_Err( p_vout, "doubling the frame rate is not supported yet" ); p_pic_dst->pf_release( p_pic_dst ); return p_pic; break; case DEINTERLACE_MEAN: RenderMean( p_vout, p_pic_dst, p_pic ); break; case DEINTERLACE_BLEND: RenderBlend( p_vout, p_pic_dst, p_pic ); break; case DEINTERLACE_X: RenderX( p_vout, p_pic_dst, p_pic ); break; } p_pic_dst->date = p_pic->date; p_pic_dst->b_force = p_pic->b_force; p_pic_dst->i_nb_fields = p_pic->i_nb_fields; p_pic_dst->b_progressive = VLC_TRUE; p_pic_dst->b_top_field_first = p_pic->b_top_field_first; p_pic->pf_release( p_pic ); return p_pic_dst;}/***************************************************************************** * OpenFilter: *****************************************************************************/static int OpenFilter( vlc_object_t *p_this ){ filter_t *p_filter = (filter_t*)p_this; vout_thread_t *p_vout; vlc_value_t val; if( ( p_filter->fmt_in.video.i_chroma != VLC_FOURCC('I','4','2','0') && p_filter->fmt_in.video.i_chroma != VLC_FOURCC('I','Y','U','V') && p_filter->fmt_in.video.i_chroma != VLC_FOURCC('Y','V','1','2') ) || p_filter->fmt_in.video.i_chroma != p_filter->fmt_out.video.i_chroma ) { return VLC_EGENERIC; } /* Impossible to use VLC_OBJECT_VOUT here because it w
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -