Fix HRD with intra-refresh
authorKieran Kunhya <kieran@kunhya.com>
Fri, 12 Nov 2010 21:53:28 +0000 (21:53 +0000)
committerJason Garrett-Glaser <darkshikari@gmail.com>
Sun, 14 Nov 2010 06:12:46 +0000 (22:12 -0800)
x264 was incorrectly calculating cpb_removal_delay with respect to the first keyframe.
It should have been calculating cpb_removal_delay with respect to the last keyframe.

common/common.h
encoder/encoder.c
encoder/ratecontrol.c
encoder/set.c

index cff6453..7d57119 100644 (file)
@@ -433,6 +433,8 @@ struct x264_t
     int             i_coded_fields_lookahead; /* Use separate counters for lookahead */
     int             i_cpb_delay_lookahead;
 
+    int             i_cpb_delay_pir_offset;
+
     int             b_queued_intra_refresh;
     int64_t         i_last_idr_pts;
 
index 12aa1fb..2a6b0df 100644 (file)
@@ -2666,6 +2666,9 @@ int     x264_encoder_encode( x264_t *h,
         overhead += h->out.nal[h->out.i_nal-1].i_payload + NALU_OVERHEAD - (h->param.b_annexb && h->out.i_nal-1);
     }
 
+    if( h->fenc->b_keyframe && h->param.b_intra_refresh )
+        h->i_cpb_delay_pir_offset = h->fenc->i_cpb_delay;
+
     /* Init the rate control */
     /* FIXME: Include slice header bit cost. */
     x264_ratecontrol_start( h, h->fenc->i_qpplus1, overhead*8 );
index ba116b8..34879b7 100644 (file)
@@ -1615,7 +1615,7 @@ int x264_ratecontrol_end( x264_t *h, int bits, int *filler )
         }
         else
         {
-            h->fenc->hrd_timing.cpb_removal_time = rc->nrt_first_access_unit + (double)h->fenc->i_cpb_delay *
+            h->fenc->hrd_timing.cpb_removal_time = rc->nrt_first_access_unit + (double)(h->fenc->i_cpb_delay - h->i_cpb_delay_pir_offset) *
                                                    h->sps->vui.i_num_units_in_tick / h->sps->vui.i_time_scale;
 
             double cpb_earliest_arrival_time = h->fenc->hrd_timing.cpb_removal_time - (double)rc->initial_cpb_removal_delay / 90000;
index 149d23a..4b0fa51 100644 (file)
@@ -618,7 +618,7 @@ void x264_sei_pic_timing_write( x264_t *h, bs_t *s )
 
     if( sps->vui.b_nal_hrd_parameters_present || sps->vui.b_vcl_hrd_parameters_present )
     {
-        bs_write( &q, sps->vui.hrd.i_cpb_removal_delay_length, h->fenc->i_cpb_delay );
+        bs_write( &q, sps->vui.hrd.i_cpb_removal_delay_length, h->fenc->i_cpb_delay - h->i_cpb_delay_pir_offset );
         bs_write( &q, sps->vui.hrd.i_dpb_output_delay_length, h->fenc->i_dpb_output_delay );
     }