Index: ../hb-0.9.0/libhb/detelecine.c===================================================================--- ../hb-0.9.0/libhb/detelecine.c (revision 1022)+++ ../hb-0.9.0/libhb/detelecine.c (working copy)@@ -975,10 +975,12 @@ } else {- goto output_frame;+ goto discard_frame; } }+ // hb_log("frame length: %i", frame->length);+ /* Check to see if frame should be dropped */ if( frame->length < 2 ) {@@ -987,7 +989,7 @@ if (!frame) {- goto output_frame;+ goto discard_frame; } if( frame->length < 2 ) {@@ -995,19 +997,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; } } }@@ -1029,11 +1031,34 @@ memcpy( pv->pic_out.data[2], frame->buffer->planes[2], pv->width[2] * pv->height[2] * sizeof(uint8_t) );+ if (frame->length != 2)+ {+ /* Interlaced material always seems to have a length of 2+ coming out of pullup, whereas ivtc'd content doesn't.+ So this is one potential way of knowing whether NTSC+ video is interlaced or telecined. */+ //pullup_release_frame ( frame );+ //goto output_ivtc_frame;+ } + pullup_release_frame( frame ); 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;++/*This lets render.c know when the fraeme length is varying. */+output_ivtc_frame: + *buf_out = pv->buf_out; + return FILTER_OK_IVTC;+ }-Index: ../hb-0.9.0/libhb/muxmp4.c===================================================================--- ../hb-0.9.0/libhb/muxmp4.c (revision 1022)+++ ../hb-0.9.0/libhb/muxmp4.c (working copy)@@ -380,7 +380,7 @@ /* 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;+ duration = ( ( buf->stop * job->arate / 90000 ) - ( buf->start * job->arate / 90000 ) ); m->sum_dur += duration; } elseIndex: ../hb-0.9.0/libhb/sync.c===================================================================--- ../hb-0.9.0/libhb/sync.c (revision 1022)+++ ../hb-0.9.0/libhb/sync.c (working copy)@@ -52,6 +52,11 @@ uint64_t st_counts[4]; uint64_t st_dates[4]; uint64_t st_first;++ /* Throttle message flags */+ int trashing_audio;+ int inserting_silence;+ int way_out_of_sync; }; /***********************************************************************@@ -85,6 +90,10 @@ pv->pts_offset_old = INT64_MIN; pv->count_frames = 0;+ pv->trashing_audio = 0;+ pv->inserting_silence = 0;+ pv->way_out_of_sync = 0;+ /* Calculate how many video frames we are expecting */ duration = 0; for( i = job->chapter_start; i <= job->chapter_end; i++ )@@ -313,8 +322,8 @@ if( next->start < cur->start - PTS_DISCONTINUITY_TOLERANCE || next->start > cur->start + PTS_DISCONTINUITY_TOLERANCE ) {- hb_log( "Sync: Video PTS discontinuity (current buffer start=%lld, next buffer start=%lld), trash Video",- cur->start, next->start );+ //hb_log( "Sync: Video PTS discontinuity (current buffer start=%lld, next buffer start=%lld), trash Video",+ // cur->start, next->start ); /* * Do we need to trash the subtitle, is it from the next->start period@@ -607,28 +616,39 @@ pts_expected = pv->pts_offset + sync->count_frames * 90000 / rate; // hb_log("Video Sequence: %lld, Audio Sequence: %lld", pv->video_sequence, buf->sequence);+ /* * Using the same logic as the Video have we crossed a VOB * boundary as detected by the expected PTS and the PTS of our * audio being out by more than the tolerance value. */- if( ( buf->start > pts_expected + PTS_DISCONTINUITY_TOLERANCE ||- buf->start < pts_expected - PTS_DISCONTINUITY_TOLERANCE ) &&- pv->pts_offset_old > INT64_MIN )+ if( buf->start > pts_expected + PTS_DISCONTINUITY_TOLERANCE ||+ buf->start < pts_expected - PTS_DISCONTINUITY_TOLERANCE ) { /* * Useful debug, but too verbose for normal use.- */+ * hb_log("Sync: Audio discontinuity (sequence: vid %lld aud %lld) (pts %lld < %lld < %lld)", pv->video_sequence, buf->sequence, pts_expected - PTS_DISCONTINUITY_TOLERANCE, buf->start, pts_expected + PTS_DISCONTINUITY_TOLERANCE );+ */ /* There has been a PTS discontinuity, and this frame might be from before the discontinuity*/- pts_expected = pv->pts_offset_old + sync->count_frames *- 90000 / rate;+ if( pv->pts_offset_old > INT64_MIN )+ {+ pts_expected = pv->pts_offset_old + sync->count_frames *+ 90000 / rate;+ } + else + {+ pv->pts_offset_old = pv->pts_offset;+ pts_expected = pv->pts_offset_old + sync->count_frames *+ 90000 / rate;+ }+ /* * Is the audio from a valid period given the previous * Video PTS. I.e. has there just been a video PTS@@ -651,7 +671,11 @@ * up diverging even more. We need to hold on to the * audio until the video catches up. */- hb_log("Sync: Audio is way out of sync, attempt to reconverge from current video PTS");+ if( !pv->way_out_of_sync )+ {+ hb_log("Sync: Audio is way out of sync, attempt to reconverge from current video PTS");+ pv->way_out_of_sync = 1;+ } /* * It wasn't from the old place, so we must be from@@ -674,9 +698,13 @@ /* Tolerance: 100 ms */ if( buf->start < pts_expected - 9000 ) {- /* Audio is behind the Video, trash it, can't use it now. */- hb_log( "Sync: Audio PTS (%lld) < Video PTS (%lld) by greater than 100ms, trashing audio to reconverge",- buf->start, pts_expected);+ if( !pv->trashing_audio )+ {+ /* Audio is behind the Video, trash it, can't use it now. */+ hb_log( "Sync: Audio PTS (%lld) < Video PTS (%lld) by greater than 100ms, trashing audio to reconverge",+ buf->start, pts_expected);+ pv->trashing_audio = 1;+ } buf = hb_fifo_get( audio->fifo_raw ); hb_buffer_close( &buf ); continue;@@ -684,9 +712,28 @@ else if( buf->start > pts_expected + 9000 ) { /* Audio is ahead of the Video, insert silence until we catch up*/- hb_log("Sync: Audio PTS (%lld) > Video PTS (%lld) by greater than 100ms insert silence until reconverged", buf->start, pts_expected);+ if( !pv->inserting_silence )+ {+ hb_log("Sync: Audio PTS (%lld) > Video PTS (%lld) by greater than 100ms insert silence until reconverged", buf->start, pts_expected);+ pv->inserting_silence = 1;+ } InsertSilence( w, i ); continue;+ } + else + {+ if( pv->trashing_audio || pv->inserting_silence )+ {+ hb_log( "Sync: Audio back in Sync at PTS %lld", buf->start );+ pv->trashing_audio = 0;+ pv->inserting_silence = 0;+ }+ if( pv->way_out_of_sync )+ {+ hb_log( "Sync: Audio no longer way out of sync at PTS %lld",+ buf->start );+ pv->way_out_of_sync = 0;+ } } if( job->acodec & HB_ACODEC_AC3 )@@ -741,6 +788,16 @@ hb_fifo_push( fifo, buf ); }+ if( hb_fifo_is_full( fifo ) &&+ pv->way_out_of_sync ) + {+ /*+ * Trash the top audio packet to avoid dead lock as we reconverge.+ */+ buf = hb_fifo_get( audio->fifo_raw );+ hb_buffer_close( &buf ); + }+ if( NeedSilence( w, audio ) ) { InsertSilence( w, i );@@ -818,8 +875,6 @@ buf->stop = buf->start + 90000 / 20; memset( buf->data, 0, buf->size );- hb_log( "sync: adding 50 ms of silence for track %x",- sync->audio->id ); hb_fifo_push( sync->audio->fifo_sync, buf ); sync->count_frames += job->arate / 20;Index: ../hb-0.9.0/libhb/render.c===================================================================--- ../hb-0.9.0/libhb/render.c (revision 1022)+++ ../hb-0.9.0/libhb/render.c (working copy)@@ -9,6 +9,14 @@ #include "ffmpeg/avcodec.h" #include "ffmpeg/swscale.h"+/* Used for keeping track of when frames are dropped by detelecine. */+int ivtc_cadence[12];+int frame_length[12];+uint32_t dropped_frames = 0;+uint32_t extended_durations = 0;++hb_buffer_t * temp = NULL;+ struct hb_work_private_s { hb_job_t * job;@@ -184,6 +192,14 @@ /* Setup render buffer */ hb_buffer_t * buf_render = hb_buffer_init( 3 * job->width * job->height / 2 ); + /* Rotate the cadence tracking. */+ int i = 0;+ for(i=11; i > 0; i--)+ {+ ivtc_cadence[i] = ivtc_cadence[i-1];+ frame_length[i] = frame_length[i-1];+ }+ /* Apply filters */ if( job->filters ) {@@ -217,6 +233,8 @@ if( result == FILTER_OK ) { buf_tmp_in = buf_tmp_out;+ ivtc_cadence[0] = 0;+ frame_length[0] = 0; } else if( result == FILTER_DELAY ) {@@ -225,13 +243,97 @@ } else if( result == FILTER_DROP ) {+ /* A drop means detelecine's latched its teeth onto+ something and has duped frames to discard. */+ ivtc_cadence[0] = 1;+ frame_length[0] = 0; hb_fifo_get( pv->subtitle_queue ); buf_tmp_in = NULL;+ dropped_frames++;+ //hb_log("RENDER: dropped frames: %i", dropped_frames);+// buf_tmp_in = buf_tmp_out; break; }+ else if( result == FILTER_OK_IVTC )+ {+ /* Frame length isnt' 2 */+ buf_tmp_in = buf_tmp_out;+ ivtc_cadence[0] = 0;+ frame_length[0] = 1;+ } }- } ++ if ( (dropped_frames) && (dropped_frames * 4) > extended_durations && (buf_tmp_in != NULL) )+ {+ // hb_log("dropped: %i >= extended / 4: %f", dropped_frames, (float)extended_durations / (float)4 );+ //in->stop = in->stop + 751;+ in->stop = in->stop + (90090000 / 120000);+ extended_durations++;+ }+ else if (in->flags & 16)+ {+ // in->stop = in->stop + 751;+ }+ /* Here's where the magic happens for VFR. The muxers sense VFR by frame durations. So here are+ a few methods for detecting whether a frame should be displayed at 23.976 or 29.87 speed. */++ /* Uncomment this section to set frame durations based+ on the lengths that come out of detelecine.c */+/* + if ( (frame_length[0] == 1) || (frame_length[1] == 1) || (frame_length[2] == 1) ) + {+ if (job->vrate_base != 1126125)+ {+ in->stop = in->stop + 751;+ }+ }+ else+ {+ if ( job->vrate_base == 1126125 )+ {+ in->stop = in->stop - 751;+ }+ }+*/++ /*This, more conservative method, watches for dropped frames in the filters above. When it+ finds one, it extends the durations of the next 4 frames to make up for the lost time. It's+ not perfect, of course. A buffering system is needed to do this accurately. We should be+ stretching the duration of 2 frames before the dropped 1m and 2 after, not 4 after.. */++// if ( (ivtc_cadence[1] == 1) || (ivtc_cadence[2] == 1) || (ivtc_cadence[3] == 1) || (ivtc_cadence[4] == 1) /*|| (ivtc_cadence[5] == 1)*/ ) +// {+ /* One of the last 4 frames was ditched by detelecine.+ That's telecined stuff, and the frames need to be + displayed with a a 23.976 duration, so extend+ their durations from ~3003 to ~3754 ticks. */+// if (job->vrate_base != 1126125)+// {+ /* Only extend ivtc frames if the FPS isn't set to 23.976 already. */+// in->stop = in->stop + 751 ;+// extended_durations++;+ //hb_log("RENDER: extended durations: %i / 4: %i", extended_durations, extended_durations / 4);+// }+// }+// else if ( in->flags & 16 ) +// {+ /* The frame is progressive. If you want to blindly assume it really is+ a 23.976 frame, extend its duration by uncommenting the line of code+ below. Otherwise, have faith in detelecine.c. */+ //in->stop = in->stop + 751 ;+// }+// else+// {+// if ( (job->vrate_base == 1126125) && !(in->flags & 16) )+// {+ /* Shorten frame durations for non-ivtc video stuff when using 23.976 */+ // in->stop = in->stop - 751;+// }++// }+ }+ /* Apply subtitles */ if( buf_tmp_in ) {@@ -268,6 +370,11 @@ buf_tmp_in = buf_render; } + /* Pass VFR NTSC IVTC frame durations on through the workflow.+ I totally wish I could slip some cryptic abbreviations into+ the last sentence. */ + buf_render->stop = in->stop;+ /* Set output to render buffer */ (*buf_out) = buf_render;@@ -297,6 +404,14 @@ void renderClose( hb_work_object_t * w ) {+ /* (90090000 / 120000) is the rational equivalent of 750.75.+ That's the number of ticks by which a 23.976 frame is + longer than a 29.97 frame. God I hate fractions.+ */+ hb_log("RENDER: dropped frames: %i (%i ticks)", dropped_frames, (dropped_frames * 3003) );+ hb_log("RENDER: extended frames: %i (%i ticks)", extended_durations, (extended_durations * (90090000 / 120000) ) );+ hb_log("RENDER: Lost time: %i ticks", (dropped_frames * 3003) - (extended_durations * (90090000 / 120000) ) );+ hb_work_private_t * pv = w->private_data; /* Cleanup subtitle queue */Index: ../hb-0.9.0/libhb/common.h===================================================================--- ../hb-0.9.0/libhb/common.h (revision 1022)+++ ../hb-0.9.0/libhb/common.h (working copy)@@ -528,6 +528,7 @@ #define FILTER_DELAY 1 #define FILTER_FAILED 2 #define FILTER_DROP 3+#define FILTER_OK_IVTC 4 struct hb_filter_object_s {