]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/ratecontrol.c
tinfoil patch: accept no widths that are no multiples of 4
[ffmpeg] / libavcodec / ratecontrol.c
index d86c5aed792cb703cd156b1eb6910d4cd19f3231..0fc9caa3174fba37f34595c248016f0f2f5dca7a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Rate control for video encoders
  *
- * Copyright (c) 2002-2003 Michael Niedermayer <michaelni@gmx.at>
+ * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -38,8 +38,8 @@ static int init_pass2(MpegEncContext *s);
 static double get_qscale(MpegEncContext *s, RateControlEntry *rce, double rate_factor, int frame_num);
 
 void ff_write_pass1_stats(MpegEncContext *s){
-    sprintf(s->avctx->stats_out, "in:%d out:%d type:%d q:%d itex:%d ptex:%d mv:%d misc:%d fcode:%d bcode:%d mc-var:%d var:%d icount:%d;\n",
-            s->picture_number, s->input_picture_number - s->max_b_frames, s->pict_type, 
+    snprintf(s->avctx->stats_out, 256, "in:%d out:%d type:%d q:%d itex:%d ptex:%d mv:%d misc:%d fcode:%d bcode:%d mc-var:%d var:%d icount:%d;\n",
+            s->current_picture_ptr->display_picture_number, s->current_picture_ptr->coded_picture_number, s->pict_type, 
             s->current_picture.quality, s->i_tex_bits, s->p_tex_bits, s->mv_bits, s->misc_bits, 
             s->f_code, s->b_code, s->current_picture.mc_mb_var_sum, s->current_picture.mb_var_sum, s->i_count);
 }
@@ -74,10 +74,12 @@ int ff_rate_control_init(MpegEncContext *s)
             p= strchr(p+1, ';');
         }
         i+= s->max_b_frames;
+        if(i<=0 || i>=INT_MAX / sizeof(RateControlEntry))
+            return -1;
         rcc->entry = (RateControlEntry*)av_mallocz(i*sizeof(RateControlEntry));
         rcc->num_entries= i;
         
-        /* init all to skiped p frames (with b frames we might have a not encoded frame at the end FIXME) */
+        /* init all to skipped p frames (with b frames we might have a not encoded frame at the end FIXME) */
         for(i=0; i<rcc->num_entries; i++){
             RateControlEntry *rce= &rcc->entry[i];
             rce->pict_type= rce->new_pict_type=P_TYPE;
@@ -164,7 +166,7 @@ int ff_rate_control_init(MpegEncContext *s)
                 bits= rce.i_tex_bits + rce.p_tex_bits;
 
                 q= get_qscale(s, &rce, rcc->pass1_wanted_bits/rcc->pass1_rc_eq_output_sum, i);
-                rcc->pass1_wanted_bits+= s->bit_rate/(s->avctx->frame_rate / (double)s->avctx->frame_rate_base);
+                rcc->pass1_wanted_bits+= s->bit_rate/(1/av_q2d(s->avctx->time_base)); //FIXME missbehaves a little for variable fps
             }
         }
 
@@ -195,14 +197,14 @@ static inline double bits2qp(RateControlEntry *rce, double bits){
     return rce->qscale * (double)(rce->i_tex_bits + rce->p_tex_bits+1)/ bits;
 }
     
-static void update_rc_buffer(MpegEncContext *s, int frame_size){
+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 double fps= 1/av_q2d(s->avctx->time_base);
+    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,11 +217,20 @@ static void update_rc_buffer(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){
-            av_log(s->avctx, AV_LOG_ERROR, "rc buffer overflow\n");
-            rcc->buffer_index= s->avctx->rc_buffer_size;
+        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;
+            rcc->buffer_index -= 8*stuffing;
+            
+            if(s->avctx->debug & FF_DEBUG_RC)
+                av_log(s->avctx, AV_LOG_DEBUG, "stuffing %d bytes\n", stuffing);
+
+            return stuffing;
         }
     }
+    return 0;
 }
 
 /**
@@ -227,6 +238,7 @@ static void update_rc_buffer(MpegEncContext *s, int frame_size){
  */
 static double get_qscale(MpegEncContext *s, RateControlEntry *rce, double rate_factor, int frame_num){
     RateControlContext *rcc= &s->rc_context;
+    AVCodecContext *a= s->avctx;
     double q, bits;
     const int pict_type= rce->new_pict_type;
     const double mb_num= s->mb_num;  
@@ -247,7 +259,7 @@ static double get_qscale(MpegEncContext *s, RateControlEntry *rce, double rate_f
         rce->pict_type == P_TYPE,
         rce->pict_type == B_TYPE,
         rcc->qscale_sum[pict_type] / (double)rcc->frame_count[pict_type],
-        s->qcompress,
+        a->qcompress,
 /*        rcc->last_qscale_for[I_TYPE],
         rcc->last_qscale_for[P_TYPE],
         rcc->last_qscale_for[B_TYPE],
@@ -388,7 +400,7 @@ static double modify_qscale(MpegEncContext *s, RateControlEntry *rce, double q,
     double bits;
     const int pict_type= rce->new_pict_type;
     const double buffer_size= s->avctx->rc_buffer_size;
-    const double fps= (double)s->avctx->frame_rate / (double)s->avctx->frame_rate_base;
+    const double fps= 1/av_q2d(s->avctx->time_base);
     const double min_rate= s->avctx->rc_min_rate / fps;
     const double max_rate= s->avctx->rc_max_rate / fps;
     
@@ -403,6 +415,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;
@@ -410,7 +423,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){
@@ -419,7 +438,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);
@@ -476,13 +501,16 @@ static void adaptive_quantization(MpegEncContext *s, double q){
     const float temp_cplx_masking= s->avctx->temporal_cplx_masking;
     const float spatial_cplx_masking = s->avctx->spatial_cplx_masking;
     const float p_masking = s->avctx->p_masking;
+    const float border_masking = s->avctx->border_masking;
     float bits_sum= 0.0;
     float cplx_sum= 0.0;
     float cplx_tab[s->mb_num];
     float bits_tab[s->mb_num];
-    const int qmin= s->avctx->lmin;
-    const int qmax= s->avctx->lmax;
+    const int qmin= s->avctx->mb_lmin;
+    const int qmax= s->avctx->mb_lmax;
     Picture * const pic= &s->current_picture;
+    const int mb_width = s->mb_width;
+    const int mb_height = s->mb_height;
     
     for(i=0; i<s->mb_num; i++){
         const int mb_xy= s->mb_index2xy[i];
@@ -490,6 +518,10 @@ static void adaptive_quantization(MpegEncContext *s, double q){
         float spat_cplx= sqrt(pic->mb_var[mb_xy]);
         const int lumi= pic->mb_mean[mb_xy];
         float bits, cplx, factor;
+        int mb_x = mb_xy % s->mb_stride;
+        int mb_y = mb_xy / s->mb_stride;
+        int mb_distance;
+        float mb_factor = 0.0;
 #if 0        
         if(spat_cplx < q/3) spat_cplx= q/3; //FIXME finetune
         if(temp_cplx < q/3) temp_cplx= q/3; //FIXME finetune
@@ -497,7 +529,7 @@ static void adaptive_quantization(MpegEncContext *s, double q){
         if(spat_cplx < 4) spat_cplx= 4; //FIXME finetune
         if(temp_cplx < 4) temp_cplx= 4; //FIXME finetune
 
-        if((s->mb_type[mb_xy]&MB_TYPE_INTRA)){//FIXME hq mode 
+        if((s->mb_type[mb_xy]&CANDIDATE_MB_TYPE_INTRA)){//FIXME hq mode 
             cplx= spat_cplx;
             factor= 1.0 + p_masking;
         }else{
@@ -510,6 +542,23 @@ static void adaptive_quantization(MpegEncContext *s, double q){
             factor*= (1.0 - (lumi-128)*(lumi-128)*lumi_masking);
         else
             factor*= (1.0 - (lumi-128)*(lumi-128)*dark_masking);
+
+        if(mb_x < mb_width/5){
+            mb_distance = mb_width/5 - mb_x;
+            mb_factor = (float)mb_distance / (float)(mb_width/5);
+        }else if(mb_x > 4*mb_width/5){
+            mb_distance = mb_x - 4*mb_width/5;
+            mb_factor = (float)mb_distance / (float)(mb_width/5);
+        }
+        if(mb_y < mb_height/5){
+            mb_distance = mb_height/5 - mb_y;
+            mb_factor = FFMAX(mb_factor, (float)mb_distance / (float)(mb_height/5));
+        }else if(mb_y > 4*mb_height/5){
+            mb_distance = mb_y - 4*mb_height/5;
+            mb_factor = FFMAX(mb_factor, (float)mb_distance / (float)(mb_height/5));
+        }
+
+        factor*= 1.0 - border_masking*mb_factor;
         
         if(factor<0.00001) factor= 0.00001;
         
@@ -522,9 +571,10 @@ static void adaptive_quantization(MpegEncContext *s, double q){
 
     /* handle qmin/qmax cliping */
     if(s->flags&CODEC_FLAG_NORMALIZE_AQP){
+        float factor= bits_sum/cplx_sum;
         for(i=0; i<s->mb_num; i++){
             float newq= q*cplx_tab[i]/bits_tab[i];
-            newq*= bits_sum/cplx_sum;
+            newq*= factor;
 
             if     (newq > qmax){
                 bits_sum -= bits_tab[i];
@@ -535,6 +585,8 @@ static void adaptive_quantization(MpegEncContext *s, double q){
                 cplx_sum -= cplx_tab[i]*q/qmin;
             }
         }
+        if(bits_sum < 0.001) bits_sum= 0.001;
+        if(cplx_sum < 0.001) cplx_sum= 0.001;
     }
    
     for(i=0; i<s->mb_num; i++){
@@ -568,6 +620,7 @@ float ff_rate_estimate_qscale(MpegEncContext *s)
     int picture_number= s->picture_number;
     int64_t wanted_bits;
     RateControlContext *rcc= &s->rc_context;
+    AVCodecContext *a= s->avctx;
     RateControlEntry local_rce, *rce;
     double bits;
     double rate_factor;
@@ -578,7 +631,7 @@ float ff_rate_estimate_qscale(MpegEncContext *s)
 
     get_qminmax(&qmin, &qmax, s, pict_type);
 
-    fps= (double)s->avctx->frame_rate / (double)s->avctx->frame_rate_base;
+    fps= 1/av_q2d(s->avctx->time_base);
 //printf("input_pic_num:%d pic_num:%d frame_rate:%d\n", s->input_picture_number, s->picture_number, s->frame_rate);
         /* update predictors */
     if(picture_number>2){
@@ -597,7 +650,7 @@ float ff_rate_estimate_qscale(MpegEncContext *s)
     }
 
     diff= s->total_bits - wanted_bits;
-    br_compensation= (s->bit_rate_tolerance - diff)/s->bit_rate_tolerance;
+    br_compensation= (a->bit_rate_tolerance - diff)/a->bit_rate_tolerance;
     if(br_compensation<=0.0) br_compensation=0.001;
 
     var= pict_type == I_TYPE ? pic->mb_var_sum : pic->mc_mb_var_sum;
@@ -619,9 +672,6 @@ float ff_rate_estimate_qscale(MpegEncContext *s)
         rce->b_code   = s->b_code;
         rce->misc_bits= 1;
 
-        if(picture_number>0)
-            update_rc_buffer(s, s->frame_bits);
-
         bits= predict_size(&rcc->pred[pict_type], rce->qscale, sqrt(var));
         if(pict_type== I_TYPE){
             rce->i_count   = s->mb_num;
@@ -652,8 +702,8 @@ float ff_rate_estimate_qscale(MpegEncContext *s)
         assert(q>0.0);
 
         if(pict_type==P_TYPE || s->intra_only){ //FIXME type dependant blur like in 2-pass
-            rcc->short_term_qsum*=s->qblur;
-            rcc->short_term_qcount*=s->qblur;
+            rcc->short_term_qsum*=a->qblur;
+            rcc->short_term_qcount*=a->qblur;
 
             rcc->short_term_qsum+= q;
             rcc->short_term_qcount++;
@@ -705,8 +755,9 @@ float ff_rate_estimate_qscale(MpegEncContext *s)
 static int init_pass2(MpegEncContext *s)
 {
     RateControlContext *rcc= &s->rc_context;
+    AVCodecContext *a= s->avctx;
     int i;
-    double fps= (double)s->avctx->frame_rate / (double)s->avctx->frame_rate_base;
+    double fps= 1/av_q2d(s->avctx->time_base);
     double complexity[5]={0,0,0,0,0};   // aproximate bits at quant=1
     double avg_quantizer[5];
     uint64_t const_bits[5]={0,0,0,0,0}; // quantizer idependant bits
@@ -716,7 +767,7 @@ static int init_pass2(MpegEncContext *s)
     double rate_factor=0;
     double step;
     //int last_i_frame=-10000000;
-    const int filter_size= (int)(s->qblur*4) | 1;  
+    const int filter_size= (int)(a->qblur*4) | 1;  
     double expected_bits;
     double *qscale, *blured_qscale;
 
@@ -797,7 +848,7 @@ static int init_pass2(MpegEncContext *s)
             for(j=0; j<filter_size; j++){
                 int index= i+j-filter_size/2;
                 double d= index-i;
-                double coeff= s->qblur==0 ? 1.0 : exp(-d*d/(s->qblur * s->qblur));
+                double coeff= a->qblur==0 ? 1.0 : exp(-d*d/(a->qblur * a->qblur));
             
                 if(index < 0 || index >= rcc->num_entries) continue;
                 if(pict_type != rcc->entry[index].new_pict_type) continue;
@@ -814,7 +865,7 @@ static int init_pass2(MpegEncContext *s)
             rce->new_qscale= modify_qscale(s, rce, blured_qscale[i], i);
             bits= qp2bits(rce, rce->new_qscale) + rce->mv_bits + rce->misc_bits;
 //printf("%d %f\n", rce->new_bits, blured_qscale[i]);
-            update_rc_buffer(s, bits);
+            bits += 8*ff_vbv_update(s, bits);
 
             rce->expected_bits= expected_bits;
             expected_bits += bits;