OSDN Git Service

- fix an error in the SCR calculation that would cause an extra frame to be dropped...
authorvan <van@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Mon, 30 Jun 2008 05:01:01 +0000 (05:01 +0000)
committervan <van@b64f7644-9d1e-0410-96f1-a4d463321fa5>
Mon, 30 Jun 2008 05:01:01 +0000 (05:01 +0000)
 - fix a rounding error in the encx264 init_delay computation that would underestimate the delay for progressive content and cause spurious "init_delay too small" messages.
 - clean up the sync.c "video time didn't advance" logic and try to make the error mgs more useful for debugging frame duration problems.

git-svn-id: svn://localhost/HandBrake/trunk@1543 b64f7644-9d1e-0410-96f1-a4d463321fa5

libhb/demuxmpeg.c
libhb/encx264.c
libhb/internal.h
libhb/reader.c
libhb/sync.c

index 0538679..051f2f6 100644 (file)
@@ -62,7 +62,7 @@ int hb_demux_ps( hb_buffer_t * buf_ps, hb_list_t * list_es, hb_psdemux_t* state
         if ( scr_delta > (90*700) || scr_delta < 0 )
         {
             ++state->scr_changes;
-            state->scr_offset += scr_delta - 1;
+            state->scr_offset += scr_delta - state->frame_duration;
         }
         state->last_scr = scr;
     }
index da8c7f9..57a2fe2 100644 (file)
@@ -317,9 +317,11 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job )
 
         /* 23.976-length frames are 3753.75 ticks long on average but the DVD
            creates that average rate by repeating 59.95 fields so the max
-           frame size is actually 4504.5 (3 field times) */
+           frame size is actually 4504.5 (3 field times). The field durations
+           are computed based on quantized times (see below) so we need an extra
+           two ticks to account for the rounding. */
         if (pv->init_delay == 3753)
-            pv->init_delay = 4505;
+            pv->init_delay = 4507;
 
         /* frame rates are not exact in the DVD 90KHz PTS clock (they are
            exact in the DVD 27MHz system clock but we never see that) so the
index 95545ac..15b016b 100644 (file)
@@ -108,6 +108,7 @@ typedef struct {
     int64_t last_scr;       /* unadjusted SCR from most recent pack */
     int64_t scr_offset;     /* discontinuity correction adjustment */
     int     scr_changes;    /* number of SCR discontinuities */
+    int     frame_duration; /* frame duration (in 90KHz ticks) */
 } hb_psdemux_t;
 
 int hb_demux_ps( hb_buffer_t * ps_buf, hb_list_t * es_list, hb_psdemux_t * );
index 9ad2867..9ce2a80 100644 (file)
@@ -43,6 +43,21 @@ hb_thread_t * hb_reader_init( hb_job_t * job )
     r->die   = job->die;
     r->sequence = 0;
 
+    /*
+     * when the scr changes we need to base the timing offset change on the
+     * end of the current video frame otherwise we'll map the first frame
+     * following the change over the current frame & it will be discarded.
+     * Since the PTS only gives the start of the frame we need the average
+     * frame duration to get its end. See the comments in the init_delay
+     * setup in libhb/encx264.c to understand the following code.
+     */
+    r->demux.frame_duration = 90000. * (double)job->vrate_base / (double)job->vrate;
+    if ( r->demux.frame_duration == 3753 )
+    {
+        r->demux.frame_duration = 4506;
+    }
+    r->demux.frame_duration += 3;
+
     return hb_thread_init( "reader", ReaderFunc, r,
                            HB_NORMAL_PRIORITY );
 }
@@ -158,7 +173,7 @@ static void ReaderFunc( void * _r )
 #define p state.param.working
 
             state.state = HB_STATE_WORKING;
-            p.progress = (float)chapter / (float)r->job->chapter_end;
+            p.progress = (double)chapter / (double)r->job->chapter_end;
             if( p.progress > 1.0 )
             {
                 p.progress = 1.0;
index 0b0852b..58812a7 100644 (file)
@@ -346,7 +346,7 @@ static int SyncVideo( hb_work_object_t * w )
          * can deal with overlaps of up to a frame time but anything larger
          * we handle by dropping frames here.
          */
-        if ( (int64_t)( next->start - pv->next_pts ) <= 0 )
+        if ( (int64_t)( next->start - cur->start ) <= 0 )
         {
             if ( pv->first_drop == 0 )
             {
@@ -365,9 +365,9 @@ static int SyncVideo( hb_work_object_t * w )
         if ( pv->first_drop )
         {
             hb_log( "sync: video time didn't advance - dropped %d frames "
-                    "(delta %d ms, current %lld, next %lld)",
-                    pv->drop_count, (int)( pv->next_pts - pv->first_drop ) / 90,
-                    pv->next_pts, pv->first_drop );
+                    "(delta %d ms, current %lld, next %lld, dur %d)",
+                    pv->drop_count, (int)( cur->start - pv->first_drop ) / 90,
+                    cur->start, next->start, (int)( next->start - cur->start ) );
             pv->first_drop = 0;
             pv->drop_count = 0;
         }
@@ -583,8 +583,8 @@ static int SyncVideo( hb_work_object_t * w )
              */
             buf_tmp = cur;
             pv->cur = cur = hb_fifo_get( job->fifo_raw );
-            pv->next_pts = next->start;
-            duration = next->start - buf_tmp->start;
+            pv->next_pts = cur->start;
+            duration = cur->start - buf_tmp->start;
             if ( duration <= 0 )
             {
                 hb_log( "sync: invalid video duration %lld, start %lld, next %lld",