Index: libhb/render.c =================================================================== --- libhb/render.c (revision 1047) +++ libhb/render.c (working copy) @@ -19,6 +19,8 @@ AVPicture pic_tmp_out; hb_buffer_t * buf_scale; hb_fifo_t * subtitle_queue; + hb_fifo_t * delay_queue; + int ivtc_frames; }; int renderInit( hb_work_object_t *, hb_job_t * ); @@ -153,10 +155,14 @@ hb_job_t * job = pv->job; hb_title_t * title = job->title; hb_buffer_t * in = *buf_in, * buf_tmp_in = *buf_in; + hb_buffer_t * ivtc_buffer = NULL; if(!in->data) { - /* If the input buffer is end of stream, send out an empty one to the next stage as well. */ + /* If the input buffer is end of stream, send out an empty one + * to the next stage as well. Note that this will result in us + * losing the current contents of the delay queue. + */ *buf_out = hb_buffer_init(0); return HB_WORK_OK; } @@ -227,6 +233,10 @@ { hb_fifo_get( pv->subtitle_queue ); buf_tmp_in = NULL; + if( job->vfr ) + { + pv->ivtc_frames = 3; + } break; } } @@ -292,6 +302,64 @@ hb_buffer_copy_settings( buf_render, buf_tmp_in ); } + if( pv->ivtc_frames == 3 ) + { + /* + * We have just detected a dropped frame and variable frame rate + * is enabled. We need to rewrite the times on the last two + * buffers, and also the next two to arrive. + */ + + ivtc_buffer = hb_fifo_see2( pv->delay_queue ); + + if( ivtc_buffer ) + { + /* + * This is the buffer from 2 frames ago, rewrite the duration on it. + */ + ivtc_buffer->stop = ivtc_buffer->stop + (90090000 / 120000); + } + + ivtc_buffer = hb_fifo_see( pv->delay_queue ); + + if( ivtc_buffer ) + { + /* + * This is the buffer from 1 frame ago, rewrite the duration on it. + */ + ivtc_buffer->stop = ivtc_buffer->stop + (90090000 / 120000); + } + + /* + * Process the next 2 frames to arrive as well. + */ + pv->ivtc_frames = 2; + } + + if( *buf_out ) + { + if( pv->ivtc_frames ) + { + /* + * This is an ivtc frame, rewrite the duration on it. + */ + ivtc_buffer = *buf_out; + ivtc_buffer->stop = ivtc_buffer->stop + (90090000 / 120000); + pv->ivtc_frames--; + } + hb_fifo_push( pv->delay_queue, *buf_out ); + *buf_out = NULL; + } + + /* + * Keep the last three frames in our queue, this ensures that we have the last + * two always in there should we need to rewrite the durations on them. + */ + if( hb_fifo_size( pv->delay_queue ) >= 3 ) + { + *buf_out = hb_fifo_get( pv->delay_queue ); + } + return HB_WORK_OK; } @@ -304,7 +372,12 @@ { hb_fifo_close( &pv->subtitle_queue ); } - + + if( pv->delay_queue ) + { + hb_fifo_close( &pv->delay_queue ); + } + /* Cleanup filters */ /* TODO: Move to work.c? */ if( pv->job->filters ) @@ -351,7 +424,9 @@ } /* Setup FIFO queue for subtitle cache */ - pv->subtitle_queue = hb_fifo_init( 8 ); + pv->subtitle_queue = hb_fifo_init( 8 ); + pv->delay_queue = hb_fifo_init( 8 ); + pv->ivtc_frames = 0; /* Setup filters */ /* TODO: Move to work.c? */ Index: libhb/common.h =================================================================== --- libhb/common.h (revision 1047) +++ libhb/common.h (working copy) @@ -172,6 +172,7 @@ int crf; char *x264opts; int areBframes; + int vfr; /* Audio tracks: audios: Indexes in hb_title_t's audios list, starting from 0.