From: Ilkka Ollakka Date: Sat, 29 Nov 2014 21:47:19 +0000 (+0200) Subject: transcode: refactor fps conversion out from video transcode X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=62a5a151673cdc8fc1300d93789006cdbcdf8873;p=vlc transcode: refactor fps conversion out from video transcode Use fps video filter for framerate conversion. Also do framerate conversion after deinterlacer so we don't screw deinterlacing with frame dropping. --- diff --git a/modules/stream_out/transcode/transcode.h b/modules/stream_out/transcode/transcode.h index 66daca0520..0dc0589b87 100644 --- a/modules/stream_out/transcode/transcode.h +++ b/modules/stream_out/transcode/transcode.h @@ -107,8 +107,7 @@ struct sout_stream_id_sys_t /* Sync */ date_t next_input_pts; /**< Incoming calculated PTS */ date_t next_output_pts; /**< output calculated PTS */ - int i_input_frame_interval; - int i_output_frame_interval; + }; /* OSD */ diff --git a/modules/stream_out/transcode/video.c b/modules/stream_out/transcode/video.c index d0ad9d5e57..79f9a81706 100644 --- a/modules/stream_out/transcode/video.c +++ b/modules/stream_out/transcode/video.c @@ -288,6 +288,16 @@ static void transcode_video_filter_init( sout_stream_t *p_stream, p_fmt_out = filter_chain_GetFmtOut( id->p_f_chain ); } + if( p_stream->p_sys->b_master_sync ) + { + filter_chain_AppendFilter( id->p_f_chain, + "fps", + NULL, + p_fmt_out, + &id->p_encoder->fmt_in ); + + p_fmt_out = filter_chain_GetFmtOut( id->p_f_chain ); + } /* Check that we have visible_width/height*/ if( !p_fmt_out->video.i_visible_height ) @@ -513,21 +523,6 @@ static void transcode_video_encoder_init( sout_stream_t *p_stream, id->p_encoder->fmt_in.video.i_frame_rate, id->p_encoder->fmt_in.video.i_frame_rate_base ); - id->i_input_frame_interval = id->p_decoder->fmt_out.video.i_frame_rate_base * CLOCK_FREQ / id->p_decoder->fmt_out.video.i_frame_rate; - msg_Info( p_stream, "input interval %d (base %d)", - id->i_input_frame_interval, id->p_decoder->fmt_out.video.i_frame_rate_base ); - - id->i_output_frame_interval = id->p_encoder->fmt_in.video.i_frame_rate_base * CLOCK_FREQ / id->p_encoder->fmt_in.video.i_frame_rate; - msg_Info( p_stream, "output interval %d (base %d)", - id->i_output_frame_interval, id->p_encoder->fmt_in.video.i_frame_rate_base ); - - date_Init( &id->next_input_pts, - id->p_decoder->fmt_out.video.i_frame_rate, - 1 ); - - date_Init( &id->next_output_pts, - id->p_encoder->fmt_in.video.i_frame_rate, - 1 ); /* Check whether a particular aspect ratio was requested */ if( id->p_encoder->fmt_out.video.i_sar_num <= 0 || @@ -633,51 +628,10 @@ void transcode_video_close( sout_stream_t *p_stream, filter_chain_Delete( id->p_uf_chain ); } -static picture_t* check_picture_drop( sout_stream_id_sys_t *id, picture_t *input_pic) { - /* If input pts lower than next_output_pts - output_frame_interval Then the - * future input frame should fit better and we can drop this one - * - * We check this here as we don't need to run user defined video filter at - * all for pictures we are going to drop anyway - * - * Duplication need is checked in OutputFrame */ - - if( ( input_pic->date ) < - ( date_Get( &id->next_output_pts ) - (mtime_t)id->i_output_frame_interval ) ) - { -#if 0 - msg_Dbg( p_stream, "dropping frame (%"PRId64" + %"PRId64" vs %"PRId64")", - p_pic->date, id->i_input_frame_interval, date_Get(&id->next_output_pts) ); -#endif - picture_Release( input_pic ); - return NULL; - } - return input_pic; -} - static void OutputFrame( sout_stream_t *p_stream, picture_t *p_pic, sout_stream_id_sys_t *id, block_t **out ) { sout_stream_sys_t *p_sys = p_stream->p_sys; picture_t *p_pic2 = NULL; - const mtime_t original_date = p_pic->date; - bool b_need_duplicate=false; - /* If input pts is lower than next_output_pts - output_frame_interval - * Then the future input frame should fit better and we can drop this one - * - * We check it here also because we can have case that video filters outputs multiple - * pictures but we don't need to use them all, for example yadif2x and outputting to some - * different fps value - */ - if( ( original_date ) < - ( date_Get( &id->next_output_pts ) - (mtime_t)id->i_output_frame_interval ) ) - { -#if 0 - msg_Dbg( p_stream, "dropping frame (%"PRId64" + %"PRId64" vs %"PRId64")", - p_pic->date, id->i_input_frame_interval, date_Get(&id->next_output_pts) ); -#endif - picture_Release( p_pic ); - return; - } /* * Encoding @@ -720,11 +674,6 @@ static void OutputFrame( sout_stream_t *p_stream, picture_t *p_pic, sout_stream_ } } - /* set output pts*/ - p_pic->date = date_Get( &id->next_output_pts ); - /*This pts is handled, increase clock to next one*/ - date_Increment( &id->next_output_pts, id->p_encoder->fmt_in.video.i_frame_rate_base ); - if( p_sys->i_threads == 0 ) { block_t *p_block; @@ -733,56 +682,14 @@ static void OutputFrame( sout_stream_t *p_stream, picture_t *p_pic, sout_stream_ block_ChainAppend( out, p_block ); } - /* we need to duplicate while next_output_pts + output_frame_interval < input_pts (next input pts)*/ - b_need_duplicate = ( date_Get( &id->next_output_pts ) + id->i_output_frame_interval ) < - ( original_date ); - if( p_sys->i_threads ) { - if( p_sys->b_master_sync ) - { - p_pic2 = video_new_buffer_encoder( id->p_encoder ); - if( likely( p_pic2 != NULL ) ) - picture_Copy( p_pic2, p_pic ); - } vlc_mutex_lock( &p_sys->lock_out ); picture_fifo_Push( p_sys->pp_pics, p_pic ); vlc_cond_signal( &p_sys->cond ); vlc_mutex_unlock( &p_sys->lock_out ); } - while( (p_sys->b_master_sync && b_need_duplicate )) - { - if( p_sys->i_threads >= 1 ) - { - picture_t *p_tmp = NULL; - /* We can't modify the picture, we need to duplicate it */ - p_tmp = video_new_buffer_encoder( id->p_encoder ); - if( likely( p_tmp != NULL ) ) - { - picture_Copy( p_tmp, p_pic2 ); - p_tmp->date = date_Get( &id->next_output_pts ); - vlc_mutex_lock( &p_sys->lock_out ); - picture_fifo_Push( p_sys->pp_pics, p_tmp ); - vlc_cond_signal( &p_sys->cond ); - vlc_mutex_unlock( &p_sys->lock_out ); - } - } - else - { - block_t *p_block; - p_pic->date = date_Get( &id->next_output_pts ); - p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic); - block_ChainAppend( out, p_block ); - } -#if 0 - msg_Dbg( p_stream, "duplicated frame"); -#endif - date_Increment( &id->next_output_pts, id->p_encoder->fmt_in.video.i_frame_rate_base ); - b_need_duplicate = ( date_Get( &id->next_output_pts ) + id->i_output_frame_interval ) < - ( original_date ); - } - if( p_sys->i_threads && p_pic2 ) picture_Release( p_pic2 ); else if ( p_sys->i_threads == 0 ) @@ -879,23 +786,6 @@ int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id, id->b_transcode = false; return VLC_EGENERIC; } - date_Set( &id->next_output_pts, p_pic->date ); - date_Set( &id->next_input_pts, p_pic->date ); - } - - /* Check input drift regardless, if it's more than 100ms from our approximation, we most likely have lost pictures - * and are in danger to become out of sync, so better reset timestamps then */ - if( likely( p_pic->date != VLC_TS_INVALID ) ) - { - mtime_t input_drift = p_pic->date - date_Get( &id->next_input_pts ); - if( unlikely( (input_drift > (CLOCK_FREQ/10)) || - (input_drift < -(CLOCK_FREQ/10)) - ) ) - { - msg_Warn( p_stream, "Reseting video sync" ); - date_Set( &id->next_output_pts, p_pic->date ); - date_Set( &id->next_input_pts, p_pic->date ); - } } /* Run the filter and output chains; first with the picture, @@ -911,12 +801,6 @@ int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id, if( !p_filtered_pic ) break; - /*drop check. We do it here because we want to feed all frames to deinterlacer */ - if( p_sys->b_master_sync ) - p_filtered_pic = check_picture_drop( id, p_filtered_pic ); - if( !p_filtered_pic ) - break; - for ( ;; ) { picture_t *p_user_filtered_pic = p_filtered_pic; @@ -933,7 +817,6 @@ int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id, p_pic = NULL; } - date_Increment( &id->next_input_pts, id->p_decoder->fmt_out.video.i_frame_rate_base ); } if( p_sys->i_threads >= 1 ) @@ -976,8 +859,8 @@ bool transcode_video_add( sout_stream_t *p_stream, es_format_t *p_fmt, if( p_sys->fps_num ) { - id->p_encoder->fmt_out.video.i_frame_rate = (p_sys->fps_num ); - id->p_encoder->fmt_out.video.i_frame_rate_base = (p_sys->fps_den ? p_sys->fps_den : 1); + id->p_encoder->fmt_in.video.i_frame_rate = id->p_encoder->fmt_out.video.i_frame_rate = (p_sys->fps_num ); + id->p_encoder->fmt_in.video.i_frame_rate_base = id->p_encoder->fmt_out.video.i_frame_rate_base = (p_sys->fps_den ? p_sys->fps_den : 1); } return true;