]> granicus.if.org Git - handbrake/commitdiff
fix 2 pass cfr x264 crash
authorjstebbins <jstebbins.hb@gmail.com>
Sun, 13 Mar 2011 21:51:14 +0000 (21:51 +0000)
committerjstebbins <jstebbins.hb@gmail.com>
Sun, 13 Mar 2011 21:51:14 +0000 (21:51 +0000)
An error in interjob->vrate calculation lead to specifying a different
timebase for the 1st and 2nd pass which x264 does not allow.  This
improves the interjob->vrate calculation accuracy and also guarantees
the timebase is the same on both passes regardless of the calculations
accuracy.

git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@3848 b64f7644-9d1e-0410-96f1-a4d463321fa5

libhb/encx264.c
libhb/hb.h
libhb/render.c
libhb/sync.c
libhb/work.c

index 67ea45b1ab01e90915b34b75810905524551971c..ed76a1f7023d060559df18cd36616c90be18f060 100644 (file)
@@ -98,7 +98,7 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job )
     param.i_threads    = ( hb_get_cpu_count() * 3 / 2 );
     param.i_width      = job->width;
     param.i_height     = job->height;
-    if( job->pass == 2 )
+    if( job->pass == 2 && job->cfr != 1 )
     {
         hb_interjob_t * interjob = hb_interjob_get( job->h );
         param.i_fps_num = interjob->vrate;
index 56566f3302ddb5a081a4497c964259e685e14801..5729088cff22be6fb839952ad9f176c31d0a0053 100644 (file)
@@ -80,8 +80,8 @@ typedef struct hb_interjob_s
 {
     int last_job;          /* job->sequence_id & 0xFFFFFF */
     int frame_count;       /* number of frames counted by sync */
+    int out_frame_count;   /* number of frames counted by render */
     uint64_t total_time;   /* real length in 90khz (i.e. / 90000 */
-    int render_dropped;    /* frames droped by telecine */
     int vrate;             /* actual measured output vrate from 1st pass */
     int vrate_base;        /* actual measured output vrate_base from 1st pass */
 
index 0af7148c15e8fc6d57ccb1ac739ccf7aca390770..0b040fc232fce7ff37fc2b29a987d3e78bd2520e 100644 (file)
@@ -29,7 +29,7 @@ struct hb_work_private_s
     int                  chapter_val;
     int                  count_frames;      // frames output so far
     double               frame_rate;        // 90KHz ticks per frame (for CFR/PFR)
-    double               out_last_stop;     // where last frame ended (for CFR/PFR)
+    uint64_t             out_last_stop;     // where last frame ended (for CFR/PFR)
     int                  drops;             // frames dropped (for CFR/PFR)
     int                  dups;              // frames duped (for CFR/PFR)
 };
@@ -266,6 +266,14 @@ static void adjust_frame_rate( hb_work_private_t *pv, hb_buffer_t **buf_out )
 
     while ( out && out->size > 0 )
     {
+        if ( pv->job->cfr == 0 )
+        {
+            ++pv->count_frames;
+            pv->out_last_stop = out->stop;
+            out = out->next;
+            continue;
+        }
+
         // this frame has to start where the last one stopped.
         out->start = pv->out_last_stop;
 
@@ -375,10 +383,7 @@ int renderWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
         {
             tail->next = in;
             *buf_out = head;
-            if ( job->cfr )
-            {
-                adjust_frame_rate( pv, buf_out );
-            }
+            adjust_frame_rate( pv, buf_out );
         } else {
             *buf_out = in;
         }     
@@ -692,7 +697,7 @@ int renderWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
 
     }
 
-    if ( buf_out && *buf_out && job->cfr )
+    if ( buf_out && *buf_out )
     {
         adjust_frame_rate( pv, buf_out );
     }
@@ -712,7 +717,8 @@ void renderClose( hb_work_object_t * w )
     hb_interjob_t * interjob = hb_interjob_get( w->private_data->job->h );
     
     /* Preserve dropped frame count for more accurate framerates in 2nd passes. */
-    interjob->render_dropped = pv->dropped_frames;
+    interjob->out_frame_count = pv->count_frames;
+    interjob->total_time = pv->out_last_stop;
 
     hb_log("render: lost time: %"PRId64" (%i frames)", pv->total_lost_time, pv->dropped_frames);
     hb_log("render: gained time: %"PRId64" (%i frames) (%"PRId64" not accounted for)", pv->total_gained_time, pv->extended_frames, pv->total_lost_time - pv->total_gained_time);
index 9a532a94b84cbfa71834a142a288c13f501fc43b..c5071222d6b8317d926443169a29c9d2ce9c1f93 100644 (file)
@@ -218,7 +218,6 @@ void syncVideoClose( hb_work_object_t * w )
         hb_interjob_t * interjob = hb_interjob_get( job->h );
         interjob->frame_count = pv->common->count_frames;
         interjob->last_job = job->sequence_id;
-        interjob->total_time = sync->next_start;
     }
 
     if (sync->drops || sync->dups )
@@ -404,6 +403,7 @@ int syncVideoWork( hb_work_object_t * w, hb_buffer_t ** buf_in,
         pv->common->first_pts[0] = INT64_MAX - 1;
         cur->start = sync->next_start;
         cur->stop = cur->start + 90000. / ((double)job->vrate / (double)job->vrate_base);
+        sync->next_start += cur->stop - cur->start;;
 
         /* Make sure last frame is reflected in frame count */
         pv->common->count_frames++;
index 39d926d3c7bd730acc59f2a0e197b6bf56eeed18..c8caff7b87773138e83e405de0174cc2ab1fcd79 100644 (file)
@@ -376,17 +376,13 @@ void hb_display_job_info( hb_job_t * job )
 /* Corrects framerates when actual duration and frame count numbers are known. */
 void correct_framerate( hb_job_t * job )
 {
-    int real_frames;
-
     hb_interjob_t * interjob = hb_interjob_get( job->h );
 
     if( ( job->sequence_id & 0xFFFFFF ) != ( interjob->last_job & 0xFFFFFF) )
         return; // Interjob information is for a different encode.
 
     // compute actual output vrate from first pass
-    real_frames = interjob->frame_count - interjob->render_dropped;
-
-    interjob->vrate = job->vrate_base * ( (double)real_frames * 90000 / interjob->total_time );
+    interjob->vrate = job->vrate_base * ( (double)interjob->out_frame_count * 90000 / interjob->total_time );
     interjob->vrate_base = job->vrate_base;
 }