From d60a8f85d7016af8a412acfc8e220445a3c3436d Mon Sep 17 00:00:00 2001
From: Michael Niedermayer <michaelni@gmx.at>
Date: Wed, 17 Dec 2003 19:53:05 +0000
Subject: [PATCH] vbv_delay

Originally committed as revision 2623 to svn://svn.ffmpeg.org/ffmpeg/trunk
---
 libavcodec/mpeg12.c      |  8 +++++---
 libavcodec/mpegvideo.c   | 18 +++++++++++++++++-
 libavcodec/mpegvideo.h   |  1 +
 libavcodec/ratecontrol.c | 27 ++++++++++++++++++++-------
 4 files changed, 43 insertions(+), 11 deletions(-)

diff --git a/libavcodec/mpeg12.c b/libavcodec/mpeg12.c
index 2d50ff9b73b..8a240da2766 100644
--- a/libavcodec/mpeg12.c
+++ b/libavcodec/mpeg12.c
@@ -408,7 +408,9 @@ void mpeg1_encode_picture_header(MpegEncContext *s, int picture_number)
     s->fake_picture_number++;
     
     put_bits(&s->pb, 3, s->pict_type);
-    put_bits(&s->pb, 16, 0xffff); /* non constant bit rate */
+
+    s->vbv_delay_ptr= s->pb.buf + get_bit_count(&s->pb)/8;
+    put_bits(&s->pb, 16, 0xFFFF); /* vbv_delay */
     
     // RAL: Forward f_code also needed for B frames
     if (s->pict_type == P_TYPE || s->pict_type == B_TYPE) {
@@ -1758,7 +1760,7 @@ static int mpeg1_decode_picture(AVCodecContext *avctx,
 {
     Mpeg1Context *s1 = avctx->priv_data;
     MpegEncContext *s = &s1->mpeg_enc_ctx;
-    int ref, f_code;
+    int ref, f_code, vbv_delay;
 
     init_get_bits(&s->gb, buf, buf_size*8);
 
@@ -1766,7 +1768,7 @@ static int mpeg1_decode_picture(AVCodecContext *avctx,
     s->pict_type = get_bits(&s->gb, 3);
     dprintf("pict_type=%d number=%d\n", s->pict_type, s->picture_number);
 
-    skip_bits(&s->gb, 16);
+    vbv_delay= get_bits(&s->gb, 16);
     if (s->pict_type == P_TYPE || s->pict_type == B_TYPE) {
         s->full_pel[0] = get_bits1(&s->gb);
         f_code = get_bits(&s->gb, 3);
diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index 61976d7d166..18a3a67fdea 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -1865,7 +1865,23 @@ int MPV_encode_picture(AVCodecContext *avctx,
         flush_put_bits(&s->pb);
         s->frame_bits  = (pbBufPtr(&s->pb) - s->pb.buf) * 8;
     }
-    
+
+    /* update mpeg1/2 vbv_delay for CBR */    
+    if(s->avctx->rc_max_rate && s->avctx->rc_min_rate == s->avctx->rc_max_rate){
+        int vbv_delay;
+
+        assert(s->repeat_first_field==0 && s->avctx->repeat_pic==0);
+        
+        vbv_delay= lrint(90000 * s->rc_context.buffer_index / s->avctx->rc_max_rate);
+        assert(vbv_delay < 0xFFFF);
+
+        s->vbv_delay_ptr[0] &= 0xF8;
+        s->vbv_delay_ptr[0] |= vbv_delay>>13;
+        s->vbv_delay_ptr[1]  = vbv_delay>>5;
+        s->vbv_delay_ptr[2] &= 0x07;
+        s->vbv_delay_ptr[2] |= vbv_delay<<3;
+    }
+
     s->total_bits += s->frame_bits;
     avctx->frame_bits  = s->frame_bits;
     
diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index c3e39f58c72..4fe388ec407 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -605,6 +605,7 @@ typedef struct MpegEncContext {
     int gop_picture_number;  ///< index of the first picture of a GOP based on fake_pic_num & mpeg1 specific 
     int last_mv_dir;         ///< last mv_dir, used for b frame encoding 
     int broken_link;         ///< no_output_of_prior_pics_flag
+    uint8_t *vbv_delay_ptr;  ///< pointer to vbv_delay in the bitstream 
     
     /* MPEG2 specific - I wish I had not to support this mess. */
     int progressive_sequence;
diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c
index 791acd8f0fc..6247315b1df 100644
--- a/libavcodec/ratecontrol.c
+++ b/libavcodec/ratecontrol.c
@@ -198,11 +198,11 @@ static inline double bits2qp(RateControlEntry *rce, double bits){
 int ff_vbv_update(MpegEncContext *s, int frame_size){
     RateControlContext *rcc= &s->rc_context;
     const double fps= (double)s->avctx->frame_rate / (double)s->avctx->frame_rate_base;
-    const double buffer_size= s->avctx->rc_buffer_size;
+    const int buffer_size= s->avctx->rc_buffer_size;
     const double min_rate= s->avctx->rc_min_rate/fps;
     const double max_rate= s->avctx->rc_max_rate/fps;
-
-//printf("%f %f %d %f %f\n", buffer_size, rcc->buffer_index, frame_size, min_rate, max_rate);
+    
+//printf("%d %f %d %f %f\n", buffer_size, rcc->buffer_index, frame_size, min_rate, max_rate);
     if(buffer_size){
         int left;
 
@@ -215,8 +215,8 @@ int ff_vbv_update(MpegEncContext *s, int frame_size){
         left= buffer_size - rcc->buffer_index - 1;
         rcc->buffer_index += clip(left, min_rate, max_rate);
 
-        if(rcc->buffer_index > s->avctx->rc_buffer_size){
-            int stuffing= ceil((rcc->buffer_index - s->avctx->rc_buffer_size)/8);
+        if(rcc->buffer_index > buffer_size){
+            int stuffing= ceil((rcc->buffer_index - buffer_size)/8);
             
             if(stuffing < 4 && s->codec_id == CODEC_ID_MPEG4)
                 stuffing=4;
@@ -413,6 +413,7 @@ static double modify_qscale(MpegEncContext *s, RateControlEntry *rce, double q,
     /* buffer overflow/underflow protection */
     if(buffer_size){
         double expected_size= rcc->buffer_index;
+        double q_limit;
 
         if(min_rate){
             double d= 2*(buffer_size - expected_size)/buffer_size;
@@ -420,7 +421,13 @@ static double modify_qscale(MpegEncContext *s, RateControlEntry *rce, double q,
             else if(d<0.0001) d=0.0001;
             q*= pow(d, 1.0/s->avctx->rc_buffer_aggressivity);
 
-            q= FFMIN(q, bits2qp(rce, FFMAX((min_rate - buffer_size + rcc->buffer_index)*3, 1)));
+            q_limit= bits2qp(rce, FFMAX((min_rate - buffer_size + rcc->buffer_index)*3, 1));
+            if(q > q_limit){
+                if(s->avctx->debug&FF_DEBUG_RC){
+                    av_log(s->avctx, AV_LOG_DEBUG, "limiting QP %f -> %f\n", q, q_limit);
+                }
+                q= q_limit;
+            }
         }
 
         if(max_rate){
@@ -429,7 +436,13 @@ static double modify_qscale(MpegEncContext *s, RateControlEntry *rce, double q,
             else if(d<0.0001) d=0.0001;
             q/= pow(d, 1.0/s->avctx->rc_buffer_aggressivity);
 
-            q= FFMAX(q, bits2qp(rce, FFMAX(rcc->buffer_index/3, 1)));
+            q_limit= bits2qp(rce, FFMAX(rcc->buffer_index/3, 1));
+            if(q < q_limit){
+                if(s->avctx->debug&FF_DEBUG_RC){
+                    av_log(s->avctx, AV_LOG_DEBUG, "limiting QP %f -> %f\n", q, q_limit);
+                }
+                q= q_limit;
+            }
         }
     }
 //printf("q:%f max:%f min:%f size:%f index:%d bits:%f agr:%f\n", q,max_rate, min_rate, buffer_size, rcc->buffer_index, bits, s->avctx->rc_buffer_aggressivity);
-- 
GitLab