Index: libhb/render.c===================================================================--- libhb/render.c (revision 1472)+++ libhb/render.c (working copy)@@ -207,6 +207,7 @@ hb_title_t * title = job->title; hb_buffer_t * in = *buf_in, * buf_tmp_in = *buf_in; hb_buffer_t * ivtc_buffer = NULL;+ hb_buffer_t * buf_render = NULL; if(!in->data) {@@ -246,9 +247,6 @@ in->new_chap = 0; }- /* Setup render buffer */- hb_buffer_t * buf_render = hb_buffer_init( 3 * job->width * job->height / 2 );- /* Apply filters */ if( job->filters ) {@@ -339,6 +337,117 @@ pv->last_stop[0] = pv->last_start[0] + (in->stop - in->start); }+ /*+ * Process the buffers in a delayed fashion if doing VFR+ */+ if ( job->vfr ) + {+ if ( buf_tmp_in )+ {+ hb_buffer_t *duplicate;+ /*+ * Duplicate frame.+ */+ duplicate = hb_buffer_init( buf_tmp_in->size );+ hb_buffer_copy_settings( duplicate, buf_tmp_in );+ memcpy( duplicate->data, buf_tmp_in->data, buf_tmp_in->size );+ duplicate->sequence = buf_tmp_in->sequence;+ hb_fifo_push( pv->delay_queue, duplicate );+ buf_tmp_in = 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 )+ {+ /*+ * pop off the oldest and replace our buffer with it+ */+ buf_tmp_in = hb_fifo_get( pv->delay_queue );+ }++ if( buf_tmp_in )+ {+ /* The current frame exists. That means it hasn't been dropped by a filter.+ Make it accessible as ivtc_buffer so we can edit its duration if needed. */+ ivtc_buffer = buf_tmp_in;++ if( pv->lost_time[3] > 0 )+ {+ /*+ * A frame's been dropped earlier by VFR detelecine.+ * Gotta make up the lost time. This will also+ * slow down the video.+ * The dropped frame's has to be accounted for, so+ * divvy it up amongst the 4 frames left behind.+ * This is what the delay_queue is for;+ * telecined sequences start 2 frames before+ * the dropped frame, so to slow down the right+ * ones you need a 2 frame delay between+ * reading input and writing output.+ */++ /* We want to extend the outputted frame's duration by the value+ stored in the 4th slot of the lost_time array. Because we need+ to adjust all the values in the array so they're contiguous,+ extend the duration inside the array first, before applying+ it to the current frame buffer. */+ pv->last_stop[3] += pv->lost_time[3];++ /* Log how much time has been added back in to the video. */+ pv->total_gained_time += pv->lost_time[3];++ /* We've pulled the 4th value from the lost_time array+ and added it to the last_stop array's 4th slot. Now, rotate the+ lost_time array so the 4th slot now holds the 3rd's value, and+ so on down the line, and set the 0 index to a value of 0. */+ int i;+ for( i=2; i >= 0; i--)+ {+ pv->lost_time[i+1] = pv->lost_time[i];+ }+ pv->lost_time[0] = 0;++ /* Log how many frames have had their durations extended. */+ pv->extended_frames++;+ }++ /* We can't use the given time stamps. Previous frames+ might already have been extended, throwing off the+ raw values fed to render.c. Instead, their+ stop and start times are stored in arrays.+ The 4th cached frame will be the to use.+ If it needed its duration extended to make up+ lost time, it will have happened above. */+ ivtc_buffer->start = pv->last_start[3];+ ivtc_buffer->stop = pv->last_stop[3];++ /* Set the 3rd cached frame to start when this one stops,+ and so on down the line. If any of them need to be+ extended as well to make up lost time, it'll be handled+ on the next loop through the renderer. */+ int i;+ for (i = 2; i >= 0; i--)+ {+ int temp_duration = pv->last_stop[i] - pv->last_start[i];+ pv->last_start[i] = pv->last_stop[i+1];+ pv->last_stop[i] = pv->last_start[i] + temp_duration;+ }++ /* If we have a pending chapter mark and this frame is at+ or after the time of the mark, mark this frame & clear+ our pending mark. */+ if( pv->chapter_time && pv->chapter_time <= ivtc_buffer->start )+ {+ ivtc_buffer->new_chap = pv->chapter_val;+ pv->chapter_time = 0;+ }++ }+ } + /* Apply subtitles */ if( buf_tmp_in ) {@@ -349,6 +458,13 @@ } }+ /* + * Setup render buffer into which we will copy the original input frame+ * resizing and cropping as appropriate. This is the buffer that we will+ * output.+ */+ buf_render = hb_buffer_init( 3 * job->width * job->height / 2 );+ /* Apply crop/scale if specified */ if( buf_tmp_in && pv->context ) {@@ -371,16 +487,26 @@ pv->pic_tmp_out.data, pv->pic_tmp_out.linesize); hb_buffer_copy_settings( buf_render, buf_tmp_in );++ if( job->vfr )+ {+ /*+ * When doing VFR the buffer is a duplicate, so don't leak it.+ */+ hb_buffer_close( &buf_tmp_in );+ } buf_tmp_in = buf_render; } /* Set output to render buffer */- (*buf_out) = buf_render;+ *buf_out = buf_render; if( buf_tmp_in == NULL ) {- /* Teardown and cleanup buffers if we are emitting NULL */+ /* + * Teardown and cleanup buffers if we are emitting NULL.+ */ if( buf_in && *buf_in ) { hb_buffer_close( buf_in );@@ -391,110 +517,22 @@ hb_buffer_close( buf_out ); *buf_out = NULL; }- }- else if( buf_tmp_in != buf_render )+ } else if( buf_tmp_in != buf_render ) {- /* Copy temporary results and settings into render buffer */+ /*+ * Didn't do any resizing or rescaling, so Copy temporary+ * results and settings into unused render buffer+ */ memcpy( buf_render->data, buf_tmp_in->data, buf_render->size ); hb_buffer_copy_settings( buf_render, buf_tmp_in );- }-- if (*buf_out && job->vfr)- {- 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( job->vfr )- {- if( hb_fifo_size( pv->delay_queue ) >= 3 )++ if( job->vfr ) {- *buf_out = hb_fifo_get( pv->delay_queue );- }- }-- if( *buf_out && job->vfr)- {- /* The current frame exists. That means it hasn't been dropped by a filter.- Make it accessible as ivtc_buffer so we can edit its duration if needed. */- ivtc_buffer = *buf_out;-- if( pv->lost_time[3] > 0 )- { /*- * A frame's been dropped earlier by VFR detelecine.- * Gotta make up the lost time. This will also- * slow down the video.- * The dropped frame's has to be accounted for, so- * divvy it up amongst the 4 frames left behind.- * This is what the delay_queue is for;- * telecined sequences start 2 frames before- * the dropped frame, so to slow down the right- * ones you need a 2 frame delay between- * reading input and writing output.+ * When doing VFR this is a duplicate and needs freeing */-- /* We want to extend the outputted frame's duration by the value- stored in the 4th slot of the lost_time array. Because we need- to adjust all the values in the array so they're contiguous,- extend the duration inside the array first, before applying- it to the current frame buffer. */- pv->last_stop[3] += pv->lost_time[3];-- /* Log how much time has been added back in to the video. */- pv->total_gained_time += pv->lost_time[3];-- /* We've pulled the 4th value from the lost_time array- and added it to the last_stop array's 4th slot. Now, rotate the- lost_time array so the 4th slot now holds the 3rd's value, and- so on down the line, and set the 0 index to a value of 0. */- int i;- for( i=2; i >= 0; i--)- {- pv->lost_time[i+1] = pv->lost_time[i];- }- pv->lost_time[0] = 0;-- /* Log how many frames have had their durations extended. */- pv->extended_frames++;+ hb_buffer_close( &buf_tmp_in ); }-- /* We can't use the given time stamps. Previous frames- might already have been extended, throwing off the- raw values fed to render.c. Instead, their- stop and start times are stored in arrays.- The 4th cached frame will be the to use.- If it needed its duration extended to make up- lost time, it will have happened above. */- ivtc_buffer->start = pv->last_start[3];- ivtc_buffer->stop = pv->last_stop[3];-- /* Set the 3rd cached frame to start when this one stops,- and so on down the line. If any of them need to be- extended as well to make up lost time, it'll be handled- on the next loop through the renderer. */- int i;- for (i = 2; i >= 0; i--)- {- int temp_duration = pv->last_stop[i] - pv->last_start[i];- pv->last_start[i] = pv->last_stop[i+1];- pv->last_stop[i] = pv->last_start[i] + temp_duration;- }-- /* If we have a pending chapter mark and this frame is at- or after the time of the mark, mark this frame & clear- our pending mark. */- if( pv->chapter_time && pv->chapter_time <= ivtc_buffer->start )- {- ivtc_buffer->new_chap = pv->chapter_val;- pv->chapter_time = 0;- }- } return HB_WORK_OK;