[SCM] libav/experimental: fixed ratecontrol & b-frames 2pass ratecontrol fixed hq with 2pass inceased build num (a few more vars for the rc stuff) hopefully no new bugs

siretart at users.alioth.debian.org siretart at users.alioth.debian.org
Sun Jun 30 15:31:28 UTC 2013


The following commit has been merged in the experimental branch:
commit 8b4c7dbc5507425b0c342948dabf01d714af7068
Author: Michael Niedermayer <michaelni at gmx.at>
Date:   Sun Apr 21 21:18:17 2002 +0000

    fixed ratecontrol & b-frames
    2pass ratecontrol
    fixed hq with 2pass
    inceased build num (a few more vars for the rc stuff)
    hopefully no new bugs
    
    Originally committed as revision 408 to svn://svn.ffmpeg.org/ffmpeg/trunk

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 00d10b7..6afa159 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -6,7 +6,8 @@ LDFLAGS= -g
 OBJS= common.o utils.o mpegvideo.o h263.o jrevdct.o jfdctfst.o \
       mpegaudio.o ac3enc.o mjpeg.o resample.o dsputil.o \
       motion_est.o imgconvert.o imgresample.o msmpeg4.o \
-      mpeg12.o h263dec.o rv10.o mpegaudiodec.o pcm.o simple_idct.o
+      mpeg12.o h263dec.o rv10.o mpegaudiodec.o pcm.o simple_idct.o \
+      ratecontrol.o
 ASM_OBJS=
 
 # currently using libac3 for ac3 decoding
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index d4f1302..10ebcae 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -5,8 +5,8 @@
 
 #define LIBAVCODEC_VERSION_INT 0x000406
 #define LIBAVCODEC_VERSION     "0.4.6"
-#define LIBAVCODEC_BUILD       4600
-#define LIBAVCODEC_BUILD_STR   "4600"
+#define LIBAVCODEC_BUILD       4601
+#define LIBAVCODEC_BUILD_STR   "4601"
 
 enum CodecID {
     CODEC_ID_NONE, 
@@ -90,7 +90,9 @@ static const int Motion_Est_QTab[] = { 1, 4, 3, 6, 5, 2 };
 #define CODEC_FLAG_TYPE   0x0040 /* fixed I/P frame type, from avctx->key_frame */
 /* parent program gurantees that the input for b-frame containing streams is not written to 
    for at least s->max_b_frames+1 frames, if this is not set than the input will be copied */
-#define CODEC_FLAG_INPUT_PRESERVED 0x0100 
+#define CODEC_FLAG_INPUT_PRESERVED 0x0100
+#define CODEC_FLAG_PASS1 0x0200  /* use internal 2pass ratecontrol in first  pass mode */
+#define CODEC_FLAG_PASS2 0x0400  /* use internal 2pass ratecontrol in second pass mode */
 
 /* codec capabilities */
 
@@ -139,13 +141,18 @@ typedef struct AVCodecContext {
     int key_frame;    /* true if the previous compressed frame was 
                          a key frame (intra, or seekable) */
     int quality;      /* quality of the previous encoded frame 
-                         (between 1 (good) and 31 (bad)) */
+                         (between 1 (good) and 31 (bad)) 
+                         this is allso used to set the quality in vbr mode
+                         and the per frame quality in CODEC_FLAG_TYPE (second pass mode) */
     float qcompress;  /* amount of qscale change between easy & hard scenes (0.0-1.0)*/
     float qblur;      /* amount of qscale smoothing over time (0.0-1.0) */
     int qmin;         /* min qscale */
     int qmax;         /* max qscale */
     int max_qdiff;    /* max qscale difference between frames */
     int max_b_frames; /* maximum b frames, the output will be delayed by max_b_frames+1 relative to the input */
+    float b_quant_factor;/* qscale factor between ips and b frames */
+    int rc_strategy;
+    int b_frame_strategy;
 
     struct AVCodec *codec;
     void *priv_data;
diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index d1c7e16..112d684 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -31,8 +31,6 @@
 #endif
 
 static void encode_picture(MpegEncContext *s, int picture_number);
-static void rate_control_init(MpegEncContext *s);
-static int rate_estimate_qscale(MpegEncContext *s);
 static void dct_unquantize_mpeg1_c(MpegEncContext *s, 
                                    DCTELEM *block, int n, int qscale);
 static void dct_unquantize_mpeg2_c(MpegEncContext *s,
@@ -377,10 +375,13 @@ int MPV_encode_init(AVCodecContext *avctx)
     s->max_qdiff= avctx->max_qdiff;
     s->qcompress= avctx->qcompress;
     s->qblur= avctx->qblur;
+    s->b_quant_factor= avctx->b_quant_factor;
     s->avctx = avctx;
     s->aspect_ratio_info= avctx->aspect_ratio_info;
     s->flags= avctx->flags;
     s->max_b_frames= avctx->max_b_frames;
+    s->rc_strategy= avctx->rc_strategy;
+    s->b_frame_strategy= avctx->b_frame_strategy;
     
     if (s->gop_size <= 1) {
         s->intra_only = 1;
@@ -510,8 +511,8 @@ int MPV_encode_init(AVCodecContext *avctx)
         s->non_intra_matrix[i] = default_non_intra_matrix[i];
     }
 
-    /* rate control init */
-    rate_control_init(s);
+    if(ff_rate_control_init(s) < 0)
+        return -1;
 
     s->picture_number = 0;
     s->picture_in_gop_number = 0;
@@ -530,6 +531,9 @@ int MPV_encode_end(AVCodecContext *avctx)
 #ifdef STATS
     print_stats();
 #endif
+
+    ff_rate_control_uninit(s);
+
     MPV_common_end(s);
     if (s->out_format == FMT_MJPEG)
         mjpeg_close(s);
@@ -577,7 +581,6 @@ void MPV_frame_start(MpegEncContext *s)
             s->current_picture[i] = s->aux_picture[i];
         }
     } else {
-        s->last_non_b_pict_type= s->pict_type;
         for(i=0;i<3;i++) {
             /* swap next and last */
             tmp = s->last_picture[i];
@@ -605,6 +608,12 @@ void MPV_frame_end(MpegEncContext *s)
       }
     }
     emms_c();
+    
+    if(s->pict_type!=B_TYPE){
+        s->last_non_b_pict_type= s->pict_type;
+        s->last_non_b_qscale= s->qscale;
+        s->last_non_b_mc_mb_var= s->mc_mb_var;
+    }
 }
 
 /* reorder input for encoding */
@@ -695,25 +704,34 @@ int MPV_encode_picture(AVCodecContext *avctx,
 
     init_put_bits(&s->pb, buf, buf_size, NULL, NULL);
 
-    s->force_input_type= (avctx->flags&CODEC_FLAG_TYPE) ?
-	(avctx->key_frame ? I_TYPE : P_TYPE) : 0;
-    if (!s->intra_only) {
-        /* first picture of GOP is intra */
-        if (s->input_picture_in_gop_number % s->gop_size==0 || s->force_input_type==I_TYPE){
-            s->input_picture_in_gop_number=0;
-            s->input_pict_type = I_TYPE;
-        }else if(s->max_b_frames==0){
-            s->input_pict_type = P_TYPE;
-        }else{
-            if(s->b_frames_since_non_b < s->max_b_frames) //FIXME more IQ
-                s->input_pict_type = B_TYPE;
-            else
+    if(avctx->flags&CODEC_FLAG_TYPE){
+        s->input_pict_type=
+        s->force_input_type= avctx->key_frame ? I_TYPE : P_TYPE;
+    }else if(s->flags&CODEC_FLAG_PASS2){
+        s->input_pict_type=
+        s->force_input_type= s->rc_context.entry[s->input_picture_number].new_pict_type;
+    }else{
+        s->force_input_type=0;
+        if (!s->intra_only) {
+            /* first picture of GOP is intra */
+            if (s->input_picture_in_gop_number % s->gop_size==0){
+                s->input_pict_type = I_TYPE;
+            }else if(s->max_b_frames==0){
                 s->input_pict_type = P_TYPE;
+            }else{
+                if(s->b_frames_since_non_b < s->max_b_frames) //FIXME more IQ
+                    s->input_pict_type = B_TYPE;
+                else
+                    s->input_pict_type = P_TYPE;
+            }
+        } else {
+            s->input_pict_type = I_TYPE;
         }
-    } else {
-        s->input_pict_type = I_TYPE;
     }
 
+    if(s->input_pict_type==I_TYPE)
+        s->input_picture_in_gop_number=0;
+    
     reorder_input(s, pict);
     
     /* output? */
@@ -745,14 +763,19 @@ int MPV_encode_picture(AVCodecContext *avctx,
             mjpeg_picture_trailer(s);
 
         avctx->quality = s->qscale;
+        
+        if(s->flags&CODEC_FLAG_PASS1)
+            ff_write_pass1_stats(s);
     }
 
     s->input_picture_number++;
     s->input_picture_in_gop_number++;
 
     flush_put_bits(&s->pb);
-    s->last_frame_bits= s->frame_bits;
     s->frame_bits  = (pbBufPtr(&s->pb) - s->pb.buf) * 8;
+    if(s->pict_type==B_TYPE) s->pb_frame_bits+= s->frame_bits;
+    else                     s->pb_frame_bits= s->frame_bits;
+
     s->total_bits += s->frame_bits;
     avctx->frame_bits  = s->frame_bits;
 //printf("fcode: %d, type: %d, head: %d, mv: %d, misc: %d, frame: %d, itex: %d, ptex: %d\n", 
@@ -1425,7 +1448,7 @@ static void copy_context_before_encode(MpegEncContext *d, MpegEncContext *s, int
     d->p_count= s->p_count;
     d->skip_count= s->skip_count;
     d->misc_bits= s->misc_bits;
-    d->last_bits= s->last_bits;
+    d->last_bits= 0;
 
     d->mb_skiped= s->mb_skiped;
 }
@@ -1449,7 +1472,6 @@ static void copy_context_after_encode(MpegEncContext *d, MpegEncContext *s, int
     d->p_count= s->p_count;
     d->skip_count= s->skip_count;
     d->misc_bits= s->misc_bits;
-    d->last_bits= s->last_bits;
 
     d->mb_intra= s->mb_intra;
     d->mb_skiped= s->mb_skiped;
@@ -1479,7 +1501,6 @@ static void encode_picture(MpegEncContext *s, int picture_number)
     s->block_wrap[4]=
     s->block_wrap[5]= s->mb_width + 2;
     
-    s->last_mc_mb_var = s->mc_mb_var;
     /* Reset the average MB variance */
     s->avg_mb_var = 0;
     s->mc_mb_var = 0;
@@ -1524,12 +1545,13 @@ static void encode_picture(MpegEncContext *s, int picture_number)
         memset(s->mb_type      , MB_TYPE_INTRA, sizeof(UINT8)*s->mb_width*s->mb_height);
     }
 
-    if(s->avg_mb_var < s->mc_mb_var && s->pict_type != B_TYPE && (!s->force_type) && s->max_b_frames==0){ //FIXME subtract MV bits
-        // FIXME b-frames & scene change detection
-        s->input_pict_type= I_TYPE;
+    if(s->avg_mb_var < s->mc_mb_var && s->pict_type == P_TYPE){ //FIXME subtract MV bits
         s->pict_type= I_TYPE;
-        s->input_picture_in_gop_number=0;
         memset(s->mb_type   , MB_TYPE_INTRA, sizeof(UINT8)*s->mb_width*s->mb_height);
+        if(s->max_b_frames==0){
+            s->input_pict_type= I_TYPE;
+            s->input_picture_in_gop_number=0;
+        }
 //printf("Scene change detected, encoding as I Frame\n");
     }
     
@@ -1550,8 +1572,11 @@ static void encode_picture(MpegEncContext *s, int picture_number)
 
 //    printf("%d %d\n", s->avg_mb_var, s->mc_mb_var);
 
-    if (!s->fixed_qscale) 
-        s->qscale = rate_estimate_qscale(s);
+    if(s->flags&CODEC_FLAG_PASS2)
+        s->qscale = ff_rate_estimate_qscale_pass2(s);
+    else if (!s->fixed_qscale) 
+        s->qscale = ff_rate_estimate_qscale(s);
+
 
     /* precompute matrix */
     if (s->out_format == FMT_MJPEG) {
@@ -1667,6 +1692,7 @@ static void encode_picture(MpegEncContext *s, int picture_number)
                     s->mv[0][0][1] = s->p_mv_table[xy][1];
                     init_put_bits(&s->pb, bit_buf[1], 3000, NULL, NULL);
                     s->block= s->blocks[next_block];
+                    s->last_bits= 0; //done in copy_context_before_encode but we skip that here
 
                     encode_mb(s, s->mv[0][0][0], s->mv[0][0][1]);
                     d= get_bit_count(&s->pb);
@@ -1810,6 +1836,7 @@ static void encode_picture(MpegEncContext *s, int picture_number)
                 copy_context_after_encode(s, &best_s, -1);
                 copy_bits(&pb, bit_buf[best], dmin);
                 s->pb= pb;
+                s->last_bits= get_bit_count(&s->pb);
             } else {
                 int motion_x, motion_y;
                 s->mv_type=MV_TYPE_16X16;
@@ -2190,132 +2217,6 @@ static void dct_unquantize_h263_c(MpegEncContext *s,
     }
 }
 
-/* rate control */
-
-static void rate_control_init(MpegEncContext *s)
-{
-    emms_c();
-
-    //initial values, they dont really matter as they will be totally different within a few frames
-    s->i_pred.coeff= s->p_pred.coeff= 7.0;
-    s->i_pred.count= s->p_pred.count= 1.0;
-    
-    s->i_pred.decay= s->p_pred.decay= 0.4;
-    
-    // use more bits at the beginning, otherwise high motion at the begin will look like shit
-    s->qsum=100;
-    s->qcount=100;
-
-    s->short_term_qsum=0.001;
-    s->short_term_qcount=0.001;
-}
-
-static double predict(Predictor *p, double q, double var)
-{
-    return p->coeff*var / (q*p->count);
-}
-
-static void update_predictor(Predictor *p, double q, double var, double size)
-{
-    double new_coeff= size*q / (var + 1);
-    if(var<1000) return;
-/*{
-int pred= predict(p, q, var);
-int error= abs(pred-size);
-static double sum=0;
-static int count=0;
-if(count>5) sum+=error;
-count++;
-if(256*256*256*64%count==0){
-    printf("%d %f %f\n", count, sum/count, p->coeff);
-}
-}*/
-    p->count*= p->decay;
-    p->coeff*= p->decay;
-    p->count++;
-    p->coeff+= new_coeff;
-}
-
-static int rate_estimate_qscale(MpegEncContext *s)
-{
-    int qmin= s->qmin;
-    int qmax= s->qmax;
-    int rate_q=5;
-    float q;
-    int qscale;
-    float br_compensation;
-    double diff;
-    double short_term_q;
-    double long_term_q;
-    int last_qscale= s->qscale;
-    double fps;
-    INT64 wanted_bits;
-    emms_c();
-
-    fps= (double)s->frame_rate / FRAME_RATE_BASE;
-    wanted_bits= s->bit_rate*(double)s->picture_number/fps;
-
-    
-    if(s->picture_number>2){
-        /* update predictors */
-        if(s->last_pict_type == I_TYPE){
-        //FIXME
-        }else{ //P Frame
-//printf("%d %d %d %f\n", s->qscale, s->last_mc_mb_var, s->frame_bits, s->p_pred.coeff);
-            update_predictor(&s->p_pred, s->qscale, s->last_mc_mb_var, s->frame_bits);
-        }
-    }
-
-    if(s->pict_type == I_TYPE){
-        //FIXME
-        rate_q= s->qsum/s->qcount;
-    }else{ //P Frame
-        int i;
-        int diff, best_diff=1000000000;
-        for(i=1; i<=31; i++){
-            diff= predict(&s->p_pred, i, s->mc_mb_var) - (double)s->bit_rate/fps;
-            if(diff<0) diff= -diff;
-            if(diff<best_diff){
-                best_diff= diff;
-                rate_q= i;
-            }
-        }
-    }
-
-    s->short_term_qsum*=s->qblur;
-    s->short_term_qcount*=s->qblur;
-
-    s->short_term_qsum+= rate_q;
-    s->short_term_qcount++;
-    short_term_q= s->short_term_qsum/s->short_term_qcount;
-    
-    long_term_q= s->qsum/s->qcount*(s->total_bits+1)/(wanted_bits+1); //+1 to avoid nan & 0
-
-//    q= (long_term_q - short_term_q)*s->qcompress + short_term_q;
-    q= 1/((1/long_term_q - 1/short_term_q)*s->qcompress + 1/short_term_q);
-
-    diff= s->total_bits - wanted_bits;
-    br_compensation= (s->bit_rate_tolerance - diff)/s->bit_rate_tolerance;
-    if(br_compensation<=0.0) br_compensation=0.001;
-    q/=br_compensation;
-
-    qscale= (int)(q + 0.5);
-    if     (qscale<qmin) qscale=qmin;
-    else if(qscale>qmax) qscale=qmax;
-    
-    if     (qscale<last_qscale-s->max_qdiff) qscale=last_qscale-s->max_qdiff;
-    else if(qscale>last_qscale+s->max_qdiff) qscale=last_qscale+s->max_qdiff;
-
-    s->qsum+= qscale;
-    s->qcount++;
-
-    s->last_pict_type= s->pict_type;
-//printf("q:%d diff:%d comp:%f rate_q:%d st_q:%f fvar:%d last_size:%d\n", qscale, (int)diff, br_compensation, 
-//       rate_q, short_term_q, s->mc_mb_var, s->frame_bits);
-//printf("%d %d\n", s->bit_rate, (int)fps);
-    return qscale;
-}
-
 AVCodec mpeg1video_encoder = {
     "mpeg1video",
     CODEC_TYPE_VIDEO,
diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index 24943e5..b0aebe8 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -44,6 +44,24 @@ typedef struct Predictor{
     double decay;
 } Predictor;
 
+typedef struct RateControlEntry{
+    int pict_type;
+    int qscale;
+    int mv_bits;
+    int i_tex_bits;
+    int p_tex_bits;
+    int misc_bits;
+    uint64_t expected_bits;
+    int new_pict_type;
+    float new_qscale;
+}RateControlEntry;
+
+typedef struct RateControlContext{
+    FILE *stats_file;
+    int num_entries;
+    RateControlEntry *entry;
+}RateControlContext;
+
 typedef struct ReorderBuffer{
     UINT8 *picture[3];
     int pict_type;
@@ -78,6 +96,9 @@ typedef struct MpegEncContext {
     int flags;        /* AVCodecContext.flags (HQ, MV4, ...) */
     int force_input_type;/* 0= no force, otherwise I_TYPE, P_TYPE, ... */
     int max_b_frames; /* max number of b-frames for encoding */
+    float b_quant_factor;/* qscale factor between ips and b frames */
+    int rc_strategy;
+    int b_frame_strategy;
     /* the following fields are managed internally by the encoder */
 
     /* bit output */
@@ -121,9 +142,9 @@ typedef struct MpegEncContext {
     int input_pict_type;        /* pict_type prior to reordering of frames */
     int force_type;             /* 0= no force, otherwise I_TYPE, P_TYPE, ... */
     int qscale;                 /* QP */
+    int last_non_b_qscale;	/* QP of last non b frame used for b frame qscale*/
     int pict_type;              /* I_TYPE, P_TYPE, B_TYPE, ... */
-    int last_non_b_pict_type;   /* used for mpeg4 gmc b-frames */
-    int last_pict_type;         /* used for bit rate stuff (needs that to update the right predictor) */
+    int last_non_b_pict_type;   /* used for mpeg4 gmc b-frames & ratecontrol */
     int frame_rate_index;
     /* motion compensation */
     int unrestricted_mv;
@@ -195,7 +216,7 @@ typedef struct MpegEncContext {
     int q_intra_matrix[64];
     int q_non_intra_matrix[64];
     /* identical to the above but for MMX & these are not permutated */
-    UINT16 __align8 q_intra_matrix16[64] ;
+    UINT16 __align8 q_intra_matrix16[64];
     UINT16 __align8 q_non_intra_matrix16[64];
     int block_last_index[6];  /* last non zero coefficient in block */
 
@@ -204,18 +225,19 @@ typedef struct MpegEncContext {
     /* bit rate control */
     int I_frame_bits; //FIXME used in mpeg12 ...
     int avg_mb_var;        /* average MB variance for current frame */
-    int mc_mb_var;     /* motion compensated MB variance for current frame */
-    int last_mc_mb_var;     /* motion compensated MB variance for last frame */
+    int mc_mb_var;         /* motion compensated MB variance for current frame */
+    int last_non_b_mc_mb_var;/* motion compensated MB variance for last non b frame */
     INT64 wanted_bits;
     INT64 total_bits;
-    int frame_bits;      /* bits used for the current frame */
-    int last_frame_bits; /* bits used for the last frame */
+    int frame_bits;        /* bits used for the current frame */
+    int pb_frame_bits;     /* bits of the last b...bp group */
     Predictor i_pred;
     Predictor p_pred;
     double qsum;         /* sum of qscales */
     double qcount;       /* count of qscales */
     double short_term_qsum;   /* sum of recent qscales */
     double short_term_qcount; /* count of recent qscales */
+    RateControlContext rc_context;
 
     /* statistics, used for 2-pass encoding */
     int mv_bits;
@@ -459,3 +481,14 @@ void mjpeg_encode_mb(MpegEncContext *s,
                      DCTELEM block[6][64]);
 void mjpeg_picture_header(MpegEncContext *s);
 void mjpeg_picture_trailer(MpegEncContext *s);
+
+/* rate control */
+int ff_rate_control_init(MpegEncContext *s);
+int ff_rate_estimate_qscale(MpegEncContext *s);
+int ff_rate_estimate_qscale_pass2(MpegEncContext *s);
+void ff_write_pass1_stats(MpegEncContext *s);
+void ff_rate_control_uninit(MpegEncContext *s);
+
+
+
+
diff --git a/libavcodec/ratecontrol.c b/libavcodec/ratecontrol.c
new file mode 100644
index 0000000..3abddb4
--- /dev/null
+++ b/libavcodec/ratecontrol.c
@@ -0,0 +1,405 @@
+/*
+    Copyright (C) 2002 Michael Niedermayer <michaelni at gmx.at>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "common.h" //needed for mpegvideo.h to compile
+#include "dsputil.h" //needed for mpegvideo.h to compile
+#include "avcodec.h"
+#include "mpegvideo.h"
+
+#define STATS_FILE "lavc_stats.txt"
+
+static int init_pass2(MpegEncContext *s);
+
+void ff_write_pass1_stats(MpegEncContext *s){
+    RateControlContext *rcc= &s->rc_context;
+//    fprintf(c->stats_file, "type:%d q:%d icount:%d pcount:%d scount:%d itex:%d ptex%d mv:%d misc:%d fcode:%d bcode:%d\")
+    fprintf(rcc->stats_file, "in:%d out:%d type:%d q:%d itex:%d ptex:%d mv:%d misc:%d fcode:%d bcode:%d\n",
+            s->picture_number, s->input_picture_number - s->max_b_frames, s->pict_type, 
+            s->qscale, s->i_tex_bits, s->p_tex_bits, s->mv_bits, s->misc_bits, s->f_code, s->b_code);
+}
+
+int ff_rate_control_init(MpegEncContext *s)
+{
+    RateControlContext *rcc= &s->rc_context;
+    emms_c();
+
+    if(s->flags&CODEC_FLAG_PASS1){
+        rcc->stats_file= fopen(STATS_FILE, "w");
+        if(!rcc->stats_file){
+            fprintf(stderr, "failed to open " STATS_FILE "\n");
+            return -1;
+        }
+    } else if(s->flags&CODEC_FLAG_PASS2){
+        int size;
+        int i;
+
+        rcc->stats_file= fopen(STATS_FILE, "r");
+        if(!rcc->stats_file){
+            fprintf(stderr, "failed to open " STATS_FILE "\n");
+            return -1;
+        }
+
+        /* find number of pics without reading the file twice :) */
+        fseek(rcc->stats_file, 0, SEEK_END);
+        size= ftell(rcc->stats_file);
+        fseek(rcc->stats_file, 0, SEEK_SET);
+
+        size/= 64; // we need at least 64 byte to store a line ...
+        rcc->entry = (RateControlEntry*)av_mallocz(size*sizeof(RateControlEntry));
+
+        for(i=0; !feof(rcc->stats_file); i++){
+            RateControlEntry *rce;
+            int picture_number;
+            int e;
+            
+            e= fscanf(rcc->stats_file, "in:%d ", &picture_number);
+            rce= &rcc->entry[picture_number];
+            e+=fscanf(rcc->stats_file, "out:%*d type:%d q:%d itex:%d ptex:%d mv:%d misc:%d fcode:%*d bcode:%*d\n",
+                   &rce->pict_type, &rce->qscale, &rce->i_tex_bits, &rce->p_tex_bits, &rce->mv_bits, &rce->misc_bits);
+            if(e!=7){
+                fprintf(stderr, STATS_FILE " is damaged\n");
+                return -1;
+            }
+        }
+        rcc->num_entries= i;
+        
+        if(init_pass2(s) < 0) return -1;
+    }
+     
+    /* no 2pass stuff, just normal 1-pass */
+    //initial values, they dont really matter as they will be totally different within a few frames
+    s->i_pred.coeff= s->p_pred.coeff= 7.0;
+    s->i_pred.count= s->p_pred.count= 1.0;
+    
+    s->i_pred.decay= s->p_pred.decay= 0.4;
+    
+    // use more bits at the beginning, otherwise high motion at the begin will look like shit
+    s->qsum=100 * s->qmin;
+    s->qcount=100;
+
+    s->short_term_qsum=0.001;
+    s->short_term_qcount=0.001;
+
+    return 0;
+}
+
+void ff_rate_control_uninit(MpegEncContext *s)
+{
+    RateControlContext *rcc= &s->rc_context;
+    emms_c();
+
+    if(rcc->stats_file) fclose(rcc->stats_file);
+    if(rcc->entry) free(rcc->entry);
+    rcc->stats_file= NULL;
+    rcc->entry= NULL;
+}
+
+//----------------------------------
+// 1 Pass Code
+
+static double predict(Predictor *p, double q, double var)
+{
+     return p->coeff*var / (q*p->count);
+}
+
+static void update_predictor(Predictor *p, double q, double var, double size)
+{
+    double new_coeff= size*q / (var + 1);
+    if(var<1000) return;
+
+    p->count*= p->decay;
+    p->coeff*= p->decay;
+    p->count++;
+    p->coeff+= new_coeff;
+}
+
+int ff_rate_estimate_qscale(MpegEncContext *s)
+{
+    int qmin= s->qmin;
+    int qmax= s->qmax;
+    int rate_q=5;
+    float q;
+    int qscale;
+    float br_compensation;
+    double diff;
+    double short_term_q;
+    double long_term_q;
+    double fps;
+    int picture_number= s->input_picture_number - s->max_b_frames;
+    int64_t wanted_bits;
+    emms_c();
+
+    fps= (double)s->frame_rate / FRAME_RATE_BASE;
+    wanted_bits= (uint64_t)(s->bit_rate*(double)picture_number/fps);
+//    printf("%d %d %d\n", picture_number, (int)wanted_bits, (int)s->total_bits);
+    
+    if(s->pict_type==B_TYPE){
+        qmin= (int)(qmin*s->b_quant_factor+0.5);
+        qmax= (int)(qmax*s->b_quant_factor+0.5);
+    }
+    if(qmin<2) qmin=2;
+    if(qmax>31) qmax=31;
+    if(qmax<=qmin) qmax= qmin;
+
+        /* update predictors */
+    if(picture_number>2){
+        if(s->pict_type!=B_TYPE && s->last_non_b_pict_type == P_TYPE){
+//printf("%d %d %d %f\n", s->qscale, s->last_mc_mb_var, s->frame_bits, s->p_pred.coeff);
+            update_predictor(&s->p_pred, s->last_non_b_qscale, s->last_non_b_mc_mb_var, s->pb_frame_bits);
+        }
+    }
+
+    if(s->pict_type == I_TYPE){
+        short_term_q= s->short_term_qsum/s->short_term_qcount;
+    
+        long_term_q= s->qsum/s->qcount*(s->total_bits+1)/(wanted_bits+1); //+1 to avoid nan & 0
+
+        q= 1/((1/long_term_q - 1/short_term_q)*s->qcompress + 1/short_term_q);
+    }else if(s->pict_type==B_TYPE){
+        q= (int)(s->last_non_b_qscale*s->b_quant_factor+0.5);
+    }else{ //P Frame
+        int i;
+        int diff, best_diff=1000000000;
+        for(i=1; i<=31; i++){
+            diff= predict(&s->p_pred, i, s->mc_mb_var) - (double)s->bit_rate/fps;
+            if(diff<0) diff= -diff;
+            if(diff<best_diff){
+                best_diff= diff;
+                rate_q= i;
+            }
+        }
+        s->short_term_qsum*=s->qblur;
+        s->short_term_qcount*=s->qblur;
+
+        s->short_term_qsum+= rate_q;
+        s->short_term_qcount++;
+        short_term_q= s->short_term_qsum/s->short_term_qcount;
+    
+        long_term_q= s->qsum/s->qcount*(s->total_bits+1)/(wanted_bits+1); //+1 to avoid nan & 0
+
+//    q= (long_term_q - short_term_q)*s->qcompress + short_term_q;
+        q= 1/((1/long_term_q - 1/short_term_q)*s->qcompress + 1/short_term_q);
+    }
+
+    diff= s->total_bits - wanted_bits;
+    br_compensation= (s->bit_rate_tolerance - diff)/s->bit_rate_tolerance;
+    if(br_compensation<=0.0) br_compensation=0.001;
+    q/=br_compensation;
+//printf("%f %f %f\n", q, br_compensation, short_term_q);
+    qscale= (int)(q + 0.5);
+    if     (qscale<qmin) qscale=qmin;
+    else if(qscale>qmax) qscale=qmax;
+    
+    if(s->pict_type!=B_TYPE){
+        s->qsum+= qscale;
+        s->qcount++;
+        if     (qscale<s->last_non_b_qscale-s->max_qdiff) qscale=s->last_non_b_qscale-s->max_qdiff;
+        else if(qscale>s->last_non_b_qscale+s->max_qdiff) qscale=s->last_non_b_qscale+s->max_qdiff;
+    }
+//printf("q:%d diff:%d comp:%f rate_q:%d st_q:%f fvar:%d last_size:%d\n", qscale, (int)diff, br_compensation, 
+//       rate_q, short_term_q, s->mc_mb_var, s->frame_bits);
+//printf("%d %d\n", s->bit_rate, (int)fps);
+    return qscale;
+}
+
+//----------------------------------------------
+// 2-Pass code
+
+static int init_pass2(MpegEncContext *s)
+{
+    RateControlContext *rcc= &s->rc_context;
+    int i;
+    double fps= (double)s->frame_rate / FRAME_RATE_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
+    uint64_t available_bits[5];
+    uint64_t all_const_bits;
+    uint64_t all_available_bits= (uint64_t)(s->bit_rate*(double)rcc->num_entries/fps);
+    int num_frames[5]={0,0,0,0,0};
+    double rate_factor=0;
+    double step;
+    int last_i_frame=-10000000;
+
+    /* find complexity & const_bits & decide the pict_types */
+    for(i=0; i<rcc->num_entries; i++){
+        RateControlEntry *rce= &rcc->entry[i];
+        
+        if(s->b_frame_strategy==0 || s->max_b_frames==0){
+            rce->new_pict_type= rce->pict_type;
+        }else{
+            int j;
+            int next_non_b_type=P_TYPE;
+
+            switch(rce->pict_type){
+            case I_TYPE:
+                if(i-last_i_frame>s->gop_size/2){ //FIXME this is not optimal
+                    rce->new_pict_type= I_TYPE;
+                    last_i_frame= i;
+                }else{
+                    rce->new_pict_type= P_TYPE; // will be caught by the scene detection anyway
+                }
+                break;
+            case P_TYPE:
+                rce->new_pict_type= P_TYPE;
+                break;
+            case B_TYPE:
+                for(j=i+1; j<i+s->max_b_frames+2 && j<rcc->num_entries; j++){
+                    if(rcc->entry[j].pict_type != B_TYPE){
+                        next_non_b_type= rcc->entry[j].pict_type;
+                        break;
+                    }
+                }
+                if(next_non_b_type==I_TYPE)
+                    rce->new_pict_type= P_TYPE;
+                else
+                    rce->new_pict_type= B_TYPE;
+                break;
+            }
+        }
+
+        complexity[rce->new_pict_type]+= (rce->i_tex_bits+ rce->p_tex_bits)*(double)rce->qscale;
+        const_bits[rce->new_pict_type]+= rce->mv_bits + rce->misc_bits;
+        num_frames[rce->new_pict_type]++;
+    }
+    all_const_bits= const_bits[I_TYPE] + const_bits[P_TYPE] + const_bits[B_TYPE];
+    
+    if(all_available_bits < all_const_bits){
+        fprintf(stderr, "requested bitrate is to low\n");
+        return -1;
+    }
+
+//    avg_complexity= complexity/rcc->num_entries;
+    avg_quantizer[P_TYPE]= 
+    avg_quantizer[I_TYPE]=   (complexity[I_TYPE]+complexity[P_TYPE] + complexity[B_TYPE]/s->b_quant_factor) 
+                           / (all_available_bits - all_const_bits);
+    avg_quantizer[B_TYPE]= avg_quantizer[P_TYPE]*s->b_quant_factor;
+//printf("avg quantizer: %f %f\n", avg_quantizer[P_TYPE], avg_quantizer[B_TYPE]);
+
+    for(i=0; i<5; i++){
+        available_bits[i]= const_bits[i] + complexity[i]/avg_quantizer[i];
+    }
+//printf("%lld %lld %lld %lld\n", available_bits[I_TYPE], available_bits[P_TYPE], available_bits[B_TYPE], all_available_bits);
+    
+    for(step=256*256; step>0.0000001; step*=0.5){
+        uint64_t expected_bits=0;
+        rate_factor+= step;
+        /* find qscale */
+        for(i=0; i<rcc->num_entries; i++){
+            RateControlEntry *rce= &rcc->entry[i];
+            double short_term_q, q, bits_left;
+            const int pict_type= rce->new_pict_type;
+            int qmin= s->qmin;
+            int qmax= s->qmax;
+
+            if(pict_type==B_TYPE){
+                qmin= (int)(qmin*s->b_quant_factor+0.5);
+                qmax= (int)(qmax*s->b_quant_factor+0.5);
+            }
+            if(qmin<2) qmin=2;
+            if(qmax>31) qmax=31;
+            if(qmax<=qmin) qmax= qmin;
+            
+            switch(s->rc_strategy){
+            case 0:
+                bits_left= available_bits[pict_type]/num_frames[pict_type]*rate_factor - rce->misc_bits - rce->mv_bits;
+                if(bits_left<1.0) bits_left=1.0;
+                short_term_q= rce->qscale*(rce->i_tex_bits + rce->p_tex_bits)/bits_left;
+                break;
+            case 1:
+                bits_left= (available_bits[pict_type] - const_bits[pict_type])/num_frames[pict_type]*rate_factor;
+                if(bits_left<1.0) bits_left=1.0;
+                short_term_q= rce->qscale*(rce->i_tex_bits + rce->p_tex_bits)/bits_left;
+                break;
+            case 2:
+                bits_left= available_bits[pict_type]/num_frames[pict_type]*rate_factor;
+                if(bits_left<1.0) bits_left=1.0;
+                short_term_q= rce->qscale*(rce->i_tex_bits + rce->p_tex_bits + rce->misc_bits + rce->mv_bits)/bits_left;
+                break;
+            default:
+                fprintf(stderr, "unknown strategy\n");
+                short_term_q=3; //gcc warning fix
+            }
+
+            if(short_term_q>31.0) short_term_q=31.0;
+            else if (short_term_q<1.0) short_term_q=1.0;
+
+            q= 1/((1/avg_quantizer[pict_type] - 1/short_term_q)*s->qcompress + 1/short_term_q);
+            if     (q<qmin) q=qmin;
+            else if(q>qmax) q=qmax;
+//printf("lq:%f, sq:%f t:%f q:%f\n", avg_quantizer[rce->pict_type], short_term_q, bits_left, q);
+            rce->new_qscale= q;
+        }
+
+        /* smooth curve */
+    
+        /* find expected bits */
+        for(i=0; i<rcc->num_entries; i++){
+            RateControlEntry *rce= &rcc->entry[i];
+            double factor= rce->qscale / rce->new_qscale;
+            
+            rce->expected_bits= expected_bits;
+            expected_bits += (int)(rce->misc_bits + rce->mv_bits + (rce->i_tex_bits + rce->p_tex_bits)*factor + 0.5);
+        }
+
+//        printf("%d %d %f\n", (int)expected_bits, (int)all_available_bits, rate_factor);
+        if(expected_bits > all_available_bits) rate_factor-= step;
+    }
+
+    return 0;
+}
+
+int ff_rate_estimate_qscale_pass2(MpegEncContext *s)
+{
+    int qmin= s->qmin;
+    int qmax= s->qmax;
+    float q;
+    int qscale;
+    float br_compensation;
+    double diff;
+    int picture_number= s->picture_number;
+    RateControlEntry *rce= &s->rc_context.entry[picture_number];
+    int64_t wanted_bits= rce->expected_bits;
+    emms_c();
+
+//    printf("%d %d %d\n", picture_number, (int)wanted_bits, (int)s->total_bits);
+    
+    if(s->pict_type==B_TYPE){
+        qmin= (int)(qmin*s->b_quant_factor+0.5);
+        qmax= (int)(qmax*s->b_quant_factor+0.5);
+    }
+    if(qmin<2) qmin=2;
+    if(qmax>31) qmax=31;
+    if(qmax<=qmin) qmax= qmin;
+
+    q= rce->new_qscale;
+
+    diff= s->total_bits - wanted_bits;
+    br_compensation= (s->bit_rate_tolerance - diff)/s->bit_rate_tolerance;
+    if(br_compensation<=0.0) br_compensation=0.001;
+    q/=br_compensation;
+
+    qscale= (int)(q + 0.5);
+    if     (qscale<qmin) qscale=qmin;
+    else if(qscale>qmax) qscale=qmax;
+//    printf("%d %d %d %d type:%d\n", qmin, qscale, qmax, picture_number, s->pict_type); fflush(stdout);
+    return qscale;
+}

-- 
Libav/FFmpeg packaging



More information about the pkg-multimedia-commits mailing list