rendered paste bodyIndex: test/test.c===================================================================--- test/test.c (revision 1034)+++ test/test.c (working copy)@@ -67,6 +67,7 @@ static int turbo_opts_enabled = 0; static char * turbo_opts = "ref=1:subme=1:me=dia:analyse=none:trellis=0:no-fast-pskip=0:8x8dct=0"; static int largeFileSize = 0;+static int vfr = 0; /* Exit cleanly on Ctrl-C */ static volatile int die = 0;@@ -633,6 +634,9 @@ job->maxWidth = maxWidth; if (maxHeight) job->maxHeight = maxHeight;+ + if (vfr)+ job->vfr = 1; if( subtitle_force ) {@@ -928,14 +932,15 @@ "\n" - "### Advanced H264 Options----------------------------------------------------\n\n"+ "### Advanced Options---------------------------------------------------------\n\n" " -x, --x264opts <string> Specify advanced x264 options in the\n" " same style as mencoder:\n" " option1=value1:option2=value2\n" " -T, --turbo When using 2-pass use the turbo options\n" " on the first pass to improve speed\n" " (only works with x264, affects PSNR by about 0.05dB,\n"- " and increases first pass speed two to four times)\n");+ " and increases first pass speed two to four times)\n"+ " -V, --vfr Perform variable framerate detelecine\n"); } /****************************************************************************@@ -991,7 +996,7 @@ { "crf", no_argument, NULL, 'Q' }, { "x264opts", required_argument, NULL, 'x' }, { "turbo", no_argument, NULL, 'T' },- + { "vfr", no_argument, NULL, 'V' }, { "maxHeight", required_argument, NULL, 'Y' }, { "maxWidth", required_argument, NULL, 'X' }, @@ -1002,7 +1007,7 @@ int c; c = getopt_long( argc, argv,- "hvuC:f:4i:o:t:Lc:ma:6:s:UFN:e:E:2d789gpP::w:l:n:b:q:S:B:r:R:Qx:TY:X:",+ "hvuC:f:4i:o:t:Lc:ma:6:s:UFN:e:E:2d789gpP::w:l:n:b:q:S:B:r:R:Qx:TY:X:V", long_options, &option_index ); if( c < 0 ) {@@ -1315,6 +1320,9 @@ case 'X': maxWidth = atoi (optarg ); break;+ case 'V':+ vfr = 1;+ break; default: fprintf( stderr, "unknown option (%s)\n", argv[optind] );Index: libhb/detelecine.c===================================================================--- libhb/detelecine.c (revision 1034)+++ libhb/detelecine.c (working copy)@@ -975,7 +975,7 @@ } else {- goto output_frame;+ goto discard_frame; } } @@ -987,7 +987,7 @@ if (!frame) {- goto output_frame;+ goto discard_frame; } if( frame->length < 2 ) {@@ -995,19 +995,19 @@ if( !(buf_in->flags & PIC_FLAG_REPEAT_FIRST_FIELD) ) {- goto output_frame;+ goto discard_frame; } frame = pullup_get_frame( ctx ); if( !frame ) {- goto output_frame;+ goto discard_frame; } if( frame->length < 2 ) { pullup_release_frame( frame );- goto output_frame;+ goto discard_frame; } } }@@ -1034,6 +1034,15 @@ output_frame: *buf_out = pv->buf_out; return FILTER_OK;++/* This and all discard_frame calls shown above are+ the result of me restoring the functionality in+ pullup that huevos_rancheros disabled because+ HB couldn't handle it. */+discard_frame: + *buf_out = pv->buf_out;+ return FILTER_DROP;+ } Index: libhb/muxmp4.c===================================================================--- libhb/muxmp4.c (revision 1034)+++ libhb/muxmp4.c (working copy)@@ -393,7 +393,14 @@ /* Because we use the audio samplerate as the timescale, we have to use potentially variable durations so the video doesn't go out of sync */- duration = ( buf->stop * job->arate / 90000 ) - m->sum_dur;+ if ( job->vfr )+ {+ duration = ( ( buf->stop * job->arate / 90000 ) - ( buf->start * job->arate / 90000 ) );+ }+ else+ {+ duration = ( buf->stop * job->arate / 90000 ) - m->sum_dur;+ } m->sum_dur += duration; } elseIndex: libhb/render.c===================================================================--- libhb/render.c (revision 1047)+++ libhb/render.c (working copy)@@ -19,6 +19,10 @@ AVPicture pic_tmp_out; hb_buffer_t * buf_scale; hb_fifo_t * subtitle_queue;+ hb_fifo_t * delay_queue;+ int frames_to_extend;+ int dropped_frames;+ int extended_frames; }; int renderInit( hb_work_object_t *, hb_job_t * );@@ -153,10 +157,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 +235,11 @@ { hb_fifo_get( pv->subtitle_queue ); buf_tmp_in = NULL;+ if( job->vfr )+ {+ pv->frames_to_extend += 4;+ pv->dropped_frames++;+ } break; } }@@ -291,7 +304,50 @@ memcpy( buf_render->data, buf_tmp_in->data, buf_render->size ); hb_buffer_copy_settings( buf_render, buf_tmp_in ); }+ + if (*buf_out)+ {+ 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 );+ } ++ if( *buf_out )+ {+ if( pv->frames_to_extend )+ {+ /*+ * A frame's been dropped by VFR detelecine.+ * Gotta make up the lost time. This will also+ * slow down the video to 23.976fps.+ * The dropped frame ran for 3003 ticks, sp+ * divvy it up amongst the 4 frames left behind.+ * This is what the deleay_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.+ */+ ivtc_buffer = *buf_out;+ + if (pv->frames_to_extend % 4)+ ivtc_buffer->stop += 751;+ else+ ivtc_buffer->stop += 750;+ + pv->frames_to_extend--;+ pv->extended_frames++;+ }+ }+ return HB_WORK_OK; } @@ -299,12 +355,21 @@ { hb_work_private_t * pv = w->private_data; + hb_log("render: dropped frames: %i (%i ticks)", pv->dropped_frames, (pv->dropped_frames * 3003) );+ hb_log("render: extended frames: %i (%i ticks)", pv->extended_frames, ( ( pv->extended_frames / 4 ) * 3003 ) );+ hb_log("render: Lost time: %i frames (%i ticks)", (pv->dropped_frames * 4) - (pv->extended_frames), (pv->dropped_frames * 3003) - ( ( pv->extended_frames / 4 ) * 3003 ) );+ /* Cleanup subtitle queue */ if( pv->subtitle_queue ) { 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 )@@ -352,6 +417,10 @@ /* Setup FIFO queue for subtitle cache */ pv->subtitle_queue = hb_fifo_init( 8 ); + pv->delay_queue = hb_fifo_init( 8 );+ pv->frames_to_extend = 0;+ pv->dropped_frames = 0;+ pv->extended_frames = 0; /* Setup filters */ /* TODO: Move to work.c? */Index: libhb/work.c===================================================================--- libhb/work.c (revision 1034)+++ libhb/work.c (working copy)@@ -160,6 +160,27 @@ job->crop[0], job->crop[1], job->crop[2], job->crop[3] ); hb_log( " + grayscale %s", job->grayscale ? "on" : "off" ); + if ( job->vfr )+ {+ job->vrate_base = 900900;++ int detelecine_present = 0; + if ( job->filters )+ {+ for( i = 0; i < hb_list_count( job->filters ); i++ )+ {+ hb_filter_object_t * filter = hb_list_item( job->filters, i );+ if (filter->id == FILTER_DETELECINE)+ detelecine_present = 1;+ } + }+ + if (!detelecine_present)+ hb_list_add( job->filters, &hb_filter_detelecine );+ + hb_log("work: VFR mode -- Switching FPS to 29.97 and detelecining.");+ }+ if( job->filters ) { hb_log(" + filters");Index: libhb/common.h===================================================================--- libhb/common.h (revision 1034)+++ libhb/common.h (working copy)@@ -172,7 +172,8 @@ int crf; char *x264opts; int areBframes;- + int vfr;+ /* Audio tracks: audios: Indexes in hb_title_t's audios list, starting from 0. -1 indicates the end of the list