Save activity from first pass. Gives a small SSIM improvement (e.g. 0.04dB for 360p...
authorGregory Maxwell <greg@xiph.org>
Sat, 31 Mar 2012 18:49:57 +0000 (18:49 +0000)
committerGregory Maxwell <greg@xiph.org>
Sat, 31 Mar 2012 18:49:57 +0000 (18:49 +0000)
git-svn-id: http://svn.xiph.org/trunk/theora@18223 0101bb08-14d6-0310-b084-bc0e0c8e3800

lib/encint.h
lib/rate.c

index 0224e4d..d25de4b 100644 (file)
@@ -524,6 +524,8 @@ struct oc_frame_metrics{
   unsigned      dup_count:31;
   /*The frame type from pass 1.*/
   unsigned      frame_type:1;
+  /*The frame activity average from pass 1.*/
+  unsigned      activity_avg;
 };
 
 
index 26ac88e..6de74d9 100644 (file)
@@ -762,6 +762,7 @@ int oc_enc_update_rc_state(oc_enc_ctx *_enc,
       _enc->rc.cur_metrics.log_scale=oc_q57_to_q24(log_scale);
       _enc->rc.cur_metrics.dup_count=_enc->dup_count;
       _enc->rc.cur_metrics.frame_type=_enc->state.frame_type;
+      _enc->rc.cur_metrics.activity_avg=_enc->activity_avg;
       _enc->rc.twopass_buffer_bytes=0;
     }break;
     case 2:{
@@ -864,9 +865,9 @@ int oc_enc_update_rc_state(oc_enc_ctx *_enc,
   return dropped;
 }
 
-#define OC_RC_2PASS_VERSION   (1)
+#define OC_RC_2PASS_VERSION   (2)
 #define OC_RC_2PASS_HDR_SZ    (38)
-#define OC_RC_2PASS_PACKET_SZ (8)
+#define OC_RC_2PASS_PACKET_SZ (12)
 
 static void oc_rc_buffer_val(oc_rc_state *_rc,ogg_int64_t _val,int _bytes){
   while(_bytes-->0){
@@ -901,6 +902,7 @@ int oc_enc_rc_2pass_out(oc_enc_ctx *_enc,unsigned char **_buf){
       oc_rc_buffer_val(&_enc->rc,
        _enc->rc.cur_metrics.dup_count|_enc->rc.cur_metrics.frame_type<<31,4);
       oc_rc_buffer_val(&_enc->rc,_enc->rc.cur_metrics.log_scale,4);
+      oc_rc_buffer_val(&_enc->rc,_enc->rc.cur_metrics.activity_avg,4);
     }
   }
   else if(_enc->packet_state==OC_PACKET_DONE&&
@@ -1051,16 +1053,19 @@ int oc_enc_rc_2pass_in(oc_enc_ctx *_enc,unsigned char *_buf,size_t _bytes){
         if(_enc->rc.twopass_buffer_fill>=OC_RC_2PASS_PACKET_SZ){
           ogg_uint32_t dup_count;
           ogg_int32_t  log_scale;
+          unsigned     activity;
           int          qti;
           int          arg;
           /*Read the metrics for the next frame.*/
           dup_count=oc_rc_unbuffer_val(&_enc->rc,4);
           log_scale=oc_rc_unbuffer_val(&_enc->rc,4);
+          activity=oc_rc_unbuffer_val(&_enc->rc,4);
           _enc->rc.cur_metrics.log_scale=log_scale;
           qti=(dup_count&0x80000000)>>31;
           _enc->rc.cur_metrics.dup_count=dup_count&0x7FFFFFFF;
           _enc->rc.cur_metrics.frame_type=qti;
           _enc->rc.twopass_force_kf=qti==OC_INTRA_FRAME;
+          _enc->activity_avg=_enc->rc.cur_metrics.activity_avg=activity;
           /*"Helpfully" set the dup count back to what it was in pass 1.*/
           arg=_enc->rc.cur_metrics.dup_count;
           th_encode_ctl(_enc,TH_ENCCTL_SET_DUP_COUNT,&arg,sizeof(arg));
@@ -1088,9 +1093,11 @@ int oc_enc_rc_2pass_in(oc_enc_ctx *_enc,unsigned char *_buf,size_t _bytes){
             ogg_uint32_t      dup_count;
             ogg_int32_t       log_scale;
             int               qti;
+            unsigned          activity;
             /*Read the metrics for the next frame.*/
             dup_count=oc_rc_unbuffer_val(&_enc->rc,4);
             log_scale=oc_rc_unbuffer_val(&_enc->rc,4);
+            activity=oc_rc_unbuffer_val(&_enc->rc,4);
             /*Add the to the circular buffer.*/
             fmi=_enc->rc.frame_metrics_head+_enc->rc.nframe_metrics++;
             if(fmi>=_enc->rc.cframe_metrics)fmi-=_enc->rc.cframe_metrics;
@@ -1099,6 +1106,7 @@ int oc_enc_rc_2pass_in(oc_enc_ctx *_enc,unsigned char *_buf,size_t _bytes){
             qti=(dup_count&0x80000000)>>31;
             m->dup_count=dup_count&0x7FFFFFFF;
             m->frame_type=qti;
+            m->activity_avg=activity;
             /*And accumulate the statistics over the window.*/
             _enc->rc.nframes[qti]++;
             _enc->rc.nframes[2]+=m->dup_count;
@@ -1125,6 +1133,7 @@ int oc_enc_rc_2pass_in(oc_enc_ctx *_enc,unsigned char *_buf,size_t _bytes){
            *(_enc->rc.frame_metrics+_enc->rc.frame_metrics_head);
           _enc->rc.twopass_force_kf=
            _enc->rc.cur_metrics.frame_type==OC_INTRA_FRAME;
+          _enc->activity_avg=_enc->rc.cur_metrics.activity_avg;
           /*"Helpfully" set the dup count back to what it was in pass 1.*/
           arg=_enc->rc.cur_metrics.dup_count;
           th_encode_ctl(_enc,TH_ENCCTL_SET_DUP_COUNT,&arg,sizeof(arg));