📄 deinterlace.c
字号:
} if( p_vout->p_sys->p_vout ) vout_CloseAndRelease( p_vout->p_sys->p_vout );}/***************************************************************************** * Destroy: destroy Deinterlace video thread output method ***************************************************************************** * Terminate an output method created by DeinterlaceCreateOutputMethod *****************************************************************************/static void Destroy( vlc_object_t *p_this ){ vout_thread_t *p_vout = (vout_thread_t *)p_this; vlc_mutex_destroy( &p_vout->p_sys->filter_lock ); free( p_vout->p_sys );}/***************************************************************************** * Render: displays previously rendered output ***************************************************************************** * This function send the currently rendered image to Deinterlace image, * waits until it is displayed and switch the two rendering buffers, preparing * next frame. *****************************************************************************/static void Render ( vout_thread_t *p_vout, picture_t *p_pic ){ vout_sys_t *p_sys = p_vout->p_sys; picture_t *pp_outpic[2]; /* FIXME are they needed ? */ p_vout->fmt_out.i_x_offset = p_vout->fmt_in.i_x_offset; p_vout->fmt_out.i_y_offset = p_vout->fmt_in.i_y_offset; p_vout->fmt_out.i_visible_width = p_vout->fmt_in.i_visible_width; p_vout->fmt_out.i_visible_height = p_vout->fmt_in.i_visible_height; /* FIXME p_sys->p_vout->* should NOT be changed FIXME */ p_sys->p_vout->fmt_in.i_x_offset = p_vout->fmt_out.i_x_offset; p_sys->p_vout->fmt_in.i_y_offset = p_vout->fmt_out.i_y_offset; p_sys->p_vout->fmt_in.i_visible_width = p_vout->fmt_out.i_visible_width; p_sys->p_vout->fmt_in.i_visible_height = p_vout->fmt_in.i_visible_height; if( p_vout->p_sys->b_half_height ) { p_sys->p_vout->fmt_in.i_y_offset /= 2; p_sys->p_vout->fmt_in.i_visible_height /= 2; } if( p_vout->i_changes & VOUT_ASPECT_CHANGE ) { p_vout->i_changes &= ~VOUT_ASPECT_CHANGE; p_vout->fmt_out.i_aspect = p_vout->fmt_in.i_aspect; p_vout->fmt_out.i_sar_num = p_vout->fmt_in.i_sar_num; p_vout->fmt_out.i_sar_den = p_vout->fmt_in.i_sar_den; video_format_t fmt = p_vout->fmt_out; if( p_vout->p_sys->b_half_height ) { fmt.i_height /= 2; fmt.i_visible_height /= 2; fmt.i_y_offset /= 2; fmt.i_sar_den *= 2; } p_sys->p_vout = vout_Request( p_vout, p_sys->p_vout, &fmt ); } if( !p_sys->p_vout ) return; pp_outpic[0] = pp_outpic[1] = NULL; vlc_mutex_lock( &p_vout->p_sys->filter_lock ); /* Get a new picture */ while( ( pp_outpic[0] = vout_CreatePicture( p_vout->p_sys->p_vout, 0, 0, 0 ) ) == NULL ) { if( !vlc_object_alive( p_vout ) || p_vout->b_error ) { vlc_mutex_unlock( &p_vout->p_sys->filter_lock ); return; } msleep( VOUT_OUTMEM_SLEEP ); } vout_DatePicture( p_vout->p_sys->p_vout, pp_outpic[0], p_pic->date ); /* If we are using double rate, get an additional new picture */ if( p_vout->p_sys->b_double_rate ) { while( ( pp_outpic[1] = vout_CreatePicture( p_vout->p_sys->p_vout, 0, 0, 0 ) ) == NULL ) { if( !vlc_object_alive( p_vout ) || p_vout->b_error ) { vout_DestroyPicture( p_vout->p_sys->p_vout, pp_outpic[0] ); vlc_mutex_unlock( &p_vout->p_sys->filter_lock ); return; } msleep( VOUT_OUTMEM_SLEEP ); } /* 20ms is a bit arbitrary, but it's only for the first image we get */ if( !p_vout->p_sys->last_date ) { vout_DatePicture( p_vout->p_sys->p_vout, pp_outpic[1], p_pic->date + 20000 ); } else { vout_DatePicture( p_vout->p_sys->p_vout, pp_outpic[1], (3 * p_pic->date - p_vout->p_sys->last_date) / 2 ); } p_vout->p_sys->last_date = p_pic->date; } switch( p_vout->p_sys->i_mode ) { case DEINTERLACE_DISCARD: RenderDiscard( p_vout, pp_outpic[0], p_pic, 0 ); vout_DisplayPicture( p_vout->p_sys->p_vout, pp_outpic[0] ); break; case DEINTERLACE_BOB: RenderBob( p_vout, pp_outpic[0], p_pic, p_pic->b_top_field_first ? 0 : 1 ); vout_DisplayPicture( p_vout->p_sys->p_vout, pp_outpic[0] ); RenderBob( p_vout, pp_outpic[1], p_pic, p_pic->b_top_field_first ? 1 : 0 ); vout_DisplayPicture( p_vout->p_sys->p_vout, pp_outpic[1] ); break; case DEINTERLACE_LINEAR: RenderLinear( p_vout, pp_outpic[0], p_pic, p_pic->b_top_field_first ? 0 : 1 ); vout_DisplayPicture( p_vout->p_sys->p_vout, pp_outpic[0] ); RenderLinear( p_vout, pp_outpic[1], p_pic, p_pic->b_top_field_first ? 1 : 0 ); vout_DisplayPicture( p_vout->p_sys->p_vout, pp_outpic[1] ); break; case DEINTERLACE_MEAN: RenderMean( p_vout, pp_outpic[0], p_pic ); vout_DisplayPicture( p_vout->p_sys->p_vout, pp_outpic[0] ); break; case DEINTERLACE_BLEND: RenderBlend( p_vout, pp_outpic[0], p_pic ); vout_DisplayPicture( p_vout->p_sys->p_vout, pp_outpic[0] ); break; case DEINTERLACE_X: RenderX( pp_outpic[0], p_pic ); vout_DisplayPicture( p_vout->p_sys->p_vout, pp_outpic[0] ); break; } vlc_mutex_unlock( &p_vout->p_sys->filter_lock );}/***************************************************************************** * RenderDiscard: only keep TOP or BOTTOM field, discard the other. *****************************************************************************/static void RenderDiscard( vout_thread_t *p_vout, picture_t *p_outpic, picture_t *p_pic, int i_field ){ int i_plane; /* Copy image and skip lines */ for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ ) { uint8_t *p_in, *p_out_end, *p_out; int i_increment; p_in = p_pic->p[i_plane].p_pixels + i_field * p_pic->p[i_plane].i_pitch; p_out = p_outpic->p[i_plane].p_pixels; p_out_end = p_out + p_outpic->p[i_plane].i_pitch * p_outpic->p[i_plane].i_visible_lines; switch( p_vout->render.i_chroma ) { case VLC_FOURCC('I','4','2','0'): case VLC_FOURCC('I','Y','U','V'): case VLC_FOURCC('Y','V','1','2'): for( ; p_out < p_out_end ; ) { vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch ); p_out += p_outpic->p[i_plane].i_pitch; p_in += 2 * p_pic->p[i_plane].i_pitch; } break; case VLC_FOURCC('I','4','2','2'): i_increment = 2 * p_pic->p[i_plane].i_pitch; if( i_plane == Y_PLANE ) { for( ; p_out < p_out_end ; ) { vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch ); p_out += p_outpic->p[i_plane].i_pitch; vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch ); p_out += p_outpic->p[i_plane].i_pitch; p_in += i_increment; } } else { for( ; p_out < p_out_end ; ) { vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch ); p_out += p_outpic->p[i_plane].i_pitch; p_in += i_increment; } } break; default: break; } }}/***************************************************************************** * RenderBob: renders a BOB picture - simple copy *****************************************************************************/static void RenderBob( vout_thread_t *p_vout, picture_t *p_outpic, picture_t *p_pic, int i_field ){ int i_plane; /* Copy image and skip lines */ for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ ) { uint8_t *p_in, *p_out_end, *p_out; p_in = p_pic->p[i_plane].p_pixels; p_out = p_outpic->p[i_plane].p_pixels; p_out_end = p_out + p_outpic->p[i_plane].i_pitch * p_outpic->p[i_plane].i_visible_lines; switch( p_vout->render.i_chroma ) { case VLC_FOURCC('I','4','2','0'): case VLC_FOURCC('I','Y','U','V'): case VLC_FOURCC('Y','V','1','2'): /* For BOTTOM field we need to add the first line */ if( i_field == 1 ) { vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch ); p_in += p_pic->p[i_plane].i_pitch; p_out += p_outpic->p[i_plane].i_pitch; } p_out_end -= 2 * p_outpic->p[i_plane].i_pitch; for( ; p_out < p_out_end ; ) { vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch ); p_out += p_outpic->p[i_plane].i_pitch; vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch ); p_in += 2 * p_pic->p[i_plane].i_pitch; p_out += p_outpic->p[i_plane].i_pitch; } vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch ); /* For TOP field we need to add the last line */ if( i_field == 0 ) { p_in += p_pic->p[i_plane].i_pitch; p_out += p_outpic->p[i_plane].i_pitch; vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch ); } break; case VLC_FOURCC('I','4','2','2'): /* For BOTTOM field we need to add the first line */ if( i_field == 1 ) { vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch ); p_in += p_pic->p[i_plane].i_pitch; p_out += p_outpic->p[i_plane].i_pitch; } p_out_end -= 2 * p_outpic->p[i_plane].i_pitch; if( i_plane == Y_PLANE ) { for( ; p_out < p_out_end ; ) { vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch ); p_out += p_outpic->p[i_plane].i_pitch; vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch ); p_in += 2 * p_pic->p[i_plane].i_pitch; p_out += p_outpic->p[i_plane].i_pitch; } } else { for( ; p_out < p_out_end ; ) { vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch ); p_out += p_outpic->p[i_plane].i_pitch; p_in += 2 * p_pic->p[i_plane].i_pitch; } } vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch ); /* For TOP field we need to add the last line */ if( i_field == 0 ) { p_in += p_pic->p[i_plane].i_pitch; p_out += p_outpic->p[i_plane].i_pitch; vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch ); } break; } }}#define Merge p_vout->p_sys->pf_merge#define EndMerge if(p_vout->p_sys->pf_end_merge) p_vout->p_sys->pf_end_merge/***************************************************************************** * RenderLinear: BOB with linear interpolation *****************************************************************************/static void RenderLinear( vout_thread_t *p_vout, picture_t *p_outpic, picture_t *p_pic, int i_field ){ int i_plane; /* Copy image and skip lines */ for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ ) { uint8_t *p_in, *p_out_end, *p_out; p_in = p_pic->p[i_plane].p_pixels; p_out = p_outpic->p[i_plane].p_pixels; p_out_end = p_out + p_outpic->p[i_plane].i_pitch * p_outpic->p[i_plane].i_visible_lines; /* For BOTTOM field we need to add the first line */ if( i_field == 1 ) { vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch ); p_in += p_pic->p[i_plane].i_pitch; p_out += p_outpic->p[i_plane].i_pitch; } p_out_end -= 2 * p_outpic->p[i_plane].i_pitch; for( ; p_out < p_out_end ; ) { vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch ); p_out += p_outpic->p[i_plane].i_pitch; Merge( p_out, p_in, p_in + 2 * p_pic->p[i_plane].i_pitch, p_pic->p[i_plane].i_pitch ); p_in += 2 * p_pic->p[i_plane].i_pitch; p_out += p_outpic->p[i_plane].i_pitch; } vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch ); /* For TOP field we need to add the last line */ if( i_field == 0 ) { p_in += p_pic->p[i_plane].i_pitch; p_out += p_outpic->p[i_plane].i_pitch; vlc_memcpy( p_out, p_in, p_pic->p[i_plane].i_pitch ); } } EndMerge();}static void RenderMean( vout_thread_t *p_vout, picture_t *p_outpic, picture_t *p_pic ){ int i_plane; /* Copy image and skip lines */ for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ ) { uint8_t *p_in, *p_out_end, *p_out; p_in = p_pic->p[i_plane].p_pixels; p_out = p_outpic->p[i_plane].p_pixels; p_out_end = p_out + p_outpic->p[i_plane].i_pitch * p_outpic->p[i_plane].i_visible_lines; /* All lines: mean value */ for( ; p_out < p_out_end ; ) { Merge( p_out, p_in, p_in + p_pic->p[i_plane].i_pitch, p_pic->p[i_plane].i_pitch ); p_out += p_outpic->p[i_plane].i_pitch; p_in += 2 * p_pic->p[i_plane].i_pitch; } } EndMerge();}static void RenderBlend( vout_thread_t *p_vout, picture_t *p_outpic, picture_t *p_pic ){ int i_plane; /* Copy image and skip lines */ for( i_plane = 0 ; i_plane < p_pic->i_planes ; i_plane++ ) { uint8_t *p_in, *p_out_end, *p_out; p_in = p_pic->p[i_plane].p_pixels; p_out = p_outpic->p[i_plane].p_pixels; p_out_end = p_out + p_outpic->p[i_plane].i_pitch
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -