changeset 3313:be941215e8e6 libavcodec

Snow 1pass ratecontrol
author lorenm
date Sun, 28 May 2006 12:38:10 +0000
parents 458b6162fa22
children aea2230e6033
files snow.c
diffstat 1 files changed, 72 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/snow.c	Fri May 26 15:44:29 2006 +0000
+++ b/snow.c	Sun May 28 12:38:10 2006 +0000
@@ -444,6 +444,7 @@
     int qlog;
     int lambda;
     int lambda2;
+    int pass1_rc;
     int mv_scale;
     int qbias;
 #define QBIAS_SHIFT 3
@@ -3852,6 +3853,50 @@
     return 0;
 }
 
+static void ratecontrol_1pass(SnowContext *s, AVFrame *pict)
+{
+    /* estimate the frame's complexity as a sum of weighted dwt coefs.
+     * FIXME we know exact mv bits at this point,
+     * but ratecontrol isn't set up to include them. */
+    uint32_t coef_sum= 0;
+    int level, orientation;
+
+    for(level=0; level<s->spatial_decomposition_count; level++){
+        for(orientation=level ? 1 : 0; orientation<4; orientation++){
+            SubBand *b= &s->plane[0].band[level][orientation];
+            DWTELEM *buf= b->buf;
+            const int w= b->width;
+            const int h= b->height;
+            const int stride= b->stride;
+            const int qlog= clip(2*QROOT + b->qlog, 0, QROOT*16);
+            const int qmul= qexp[qlog&(QROOT-1)]<<(qlog>>QSHIFT);
+            const int qdiv= (1<<16)/qmul;
+            int x, y;
+            if(orientation==0)
+                decorrelate(s, b, buf, stride, 1, 0);
+            for(y=0; y<h; y++)
+                for(x=0; x<w; x++)
+                    coef_sum+= abs(buf[x+y*stride]) * qdiv >> 16;
+            if(orientation==0)
+                correlate(s, b, buf, stride, 1, 0);
+        }
+    }
+
+    /* ugly, ratecontrol just takes a sqrt again */
+    coef_sum = (uint64_t)coef_sum * coef_sum >> 16;
+    assert(coef_sum < INT_MAX);
+
+    if(pict->pict_type == I_TYPE){
+        s->m.current_picture.mb_var_sum= coef_sum;
+        s->m.current_picture.mc_mb_var_sum= 0;
+    }else{
+        s->m.current_picture.mc_mb_var_sum= coef_sum;
+        s->m.current_picture.mb_var_sum= 0;
+    }
+
+    pict->quality= ff_rate_estimate_qscale(&s->m, 1);
+    s->lambda= pict->quality * 3/2;
+}
 
 static void calculate_vissual_weight(SnowContext *s, Plane *p){
     int width = p->width;
@@ -3910,10 +3955,11 @@
         if(!avctx->stats_out)
             avctx->stats_out = av_mallocz(256);
     }
-    if(avctx->flags&CODEC_FLAG_PASS2){
+    if(!(avctx->flags&CODEC_FLAG_QSCALE)){
         if(ff_rate_control_init(&s->m) < 0)
             return -1;
     }
+    s->pass1_rc= !(avctx->flags & (CODEC_FLAG_QSCALE|CODEC_FLAG_PASS2));
 
     for(plane_index=0; plane_index<3; plane_index++){
         calculate_vissual_weight(s, &s->plane[plane_index]);
@@ -3993,25 +4039,31 @@
     }
     s->new_picture = *pict;
 
+    s->m.picture_number= avctx->frame_number;
     if(avctx->flags&CODEC_FLAG_PASS2){
         s->m.pict_type =
         pict->pict_type= s->m.rc_context.entry[avctx->frame_number].new_pict_type;
         s->keyframe= pict->pict_type==FF_I_TYPE;
-        s->m.picture_number= avctx->frame_number;
         if(!(avctx->flags&CODEC_FLAG_QSCALE))
             pict->quality= ff_rate_estimate_qscale(&s->m, 0);
     }else{
         s->keyframe= avctx->gop_size==0 || avctx->frame_number % avctx->gop_size == 0;
+        s->m.pict_type=
         pict->pict_type= s->keyframe ? FF_I_TYPE : FF_P_TYPE;
     }
 
+    if(s->pass1_rc && avctx->frame_number == 0)
+        pict->quality= 2*FF_QP2LAMBDA;
     if(pict->quality){
         s->qlog= rint(QROOT*log(pict->quality / (float)FF_QP2LAMBDA)/log(2));
         //<64 >60
         s->qlog += 61*QROOT/8;
-    }else{
+        s->lambda = pict->quality * 3/2;
+    }
+    if(s->qlog < 0 || (!pict->quality && (avctx->flags & CODEC_FLAG_QSCALE))){
         s->qlog= LOSSLESS_QLOG;
-    }
+        s->lambda = 0;
+    }//else keep previous frame's qlog until after motion est
 
     frame_start(s);
     s->current_picture.key_frame= s->keyframe;
@@ -4050,7 +4102,7 @@
         s->m.out_format= FMT_H263;
         s->m.unrestricted_mv= 1;
 
-        s->lambda = s->m.lambda= pict->quality * 3/2; //FIXME bug somewhere else
+        s->m.lambda = s->lambda;
         s->m.qscale= (s->m.lambda*139 + FF_LAMBDA_SCALE*64) >> (FF_LAMBDA_SHIFT + 7);
         s->lambda2= s->m.lambda2= (s->m.lambda*s->m.lambda + FF_LAMBDA_SCALE/2) >> FF_LAMBDA_SHIFT;
 
@@ -4061,6 +4113,7 @@
 
 redo_frame:
 
+    s->m.pict_type = pict->pict_type;
     s->qbias= pict->pict_type == P_TYPE ? 2 : 0;
 
     encode_header(s);
@@ -4086,6 +4139,7 @@
 
         if(   plane_index==0
            && pict->pict_type == P_TYPE
+           && !(avctx->flags&CODEC_FLAG_PASS2)
            && s->m.me.scene_change_score > s->avctx->scenechange_threshold){
             ff_init_range_encoder(c, buf, buf_size);
             ff_build_rac_states(c, 0.05*(1LL<<32), 256-8);
@@ -4105,6 +4159,9 @@
 
         ff_spatial_dwt(s->spatial_dwt_buffer, w, h, w, s->spatial_decomposition_type, s->spatial_decomposition_count);
 
+        if(s->pass1_rc && plane_index==0)
+            ratecontrol_1pass(s, pict);
+
         for(level=0; level<s->spatial_decomposition_count; level++){
             for(orientation=level ? 1 : 0; orientation<4; orientation++){
                 SubBand *b= &p->band[level][orientation];
@@ -4160,17 +4217,17 @@
     s->current_picture.coded_picture_number = avctx->frame_number;
     s->current_picture.pict_type = pict->pict_type;
     s->current_picture.quality = pict->quality;
-    if(avctx->flags&CODEC_FLAG_PASS1){
-        s->m.p_tex_bits = 8*(s->c.bytestream - s->c.bytestream_start) - s->m.misc_bits - s->m.mv_bits;
-        s->m.current_picture.display_picture_number =
-        s->m.current_picture.coded_picture_number = avctx->frame_number;
-        s->m.pict_type = pict->pict_type;
-        s->m.current_picture.quality = pict->quality;
+    s->m.frame_bits = 8*(s->c.bytestream - s->c.bytestream_start);
+    s->m.p_tex_bits = s->m.frame_bits - s->m.misc_bits - s->m.mv_bits;
+    s->m.current_picture.display_picture_number =
+    s->m.current_picture.coded_picture_number = avctx->frame_number;
+    s->m.current_picture.quality = pict->quality;
+    s->m.total_bits += 8*(s->c.bytestream - s->c.bytestream_start);
+    if(s->pass1_rc)
+        ff_rate_estimate_qscale(&s->m, 0);
+    if(avctx->flags&CODEC_FLAG_PASS1)
         ff_write_pass1_stats(&s->m);
-    }
-    if(avctx->flags&CODEC_FLAG_PASS2){
-        s->m.total_bits += 8*(s->c.bytestream - s->c.bytestream_start);
-    }
+    s->m.last_pict_type = s->m.pict_type;
 
     emms_c();