]> granicus.if.org Git - libvpx/commitdiff
Fix CQ range and experimental KF sizing changes.
authorPaul Wilkins <paulwilkins@google.com>
Mon, 17 Jan 2011 17:23:11 +0000 (17:23 +0000)
committerPaul Wilkins <paulwilkins@google.com>
Mon, 17 Jan 2011 17:24:45 +0000 (17:24 +0000)
The CQ level was not using the q_trans[] array to convert
to a 0-127 range as per min and maxq

Experimental change to try and match the reconstruction
error for forced key frames approximately to that of the
previous frame by means of the recode loop. Though this
may cause extra recodes and the recode behavior has not
been optimized, it can only happen on forced key frames.

Change-Id: I1f7e42d526f1b1cb556dd461eff1a692bd1b5b2f

vp8/encoder/onyx_if.c
vp8/encoder/onyx_int.h
vp8/vp8_cx_iface.c

index e0d1d7043ccf20f494b52117870d87649a6f09a9..47fc3f78e02377b9c87a1be10f18954507c72614 100644 (file)
@@ -1551,6 +1551,7 @@ void vp8_init_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
         cpi->auto_worst_q              = 0;
         cpi->oxcf.best_allowed_q            = MINQ;
         cpi->oxcf.worst_allowed_q           = MAXQ;
+        cpi->oxcf.cq_level = MINQ;
 
         cpi->oxcf.end_usage                = USAGE_STREAM_FROM_SERVER;
         cpi->oxcf.starting_buffer_level     =   4000;
@@ -1651,6 +1652,7 @@ void vp8_init_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
 
     cpi->oxcf.worst_allowed_q = q_trans[oxcf->worst_allowed_q];
     cpi->oxcf.best_allowed_q  = q_trans[oxcf->best_allowed_q];
+    cpi->oxcf.cq_level = q_trans[cpi->oxcf.cq_level];
 
     if (oxcf->fixed_q >= 0)
     {
@@ -1740,6 +1742,8 @@ void vp8_init_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
     cpi->avg_frame_qindex             = cpi->oxcf.worst_allowed_q;
     cpi->best_quality                = cpi->oxcf.best_allowed_q;
     cpi->active_best_quality          = cpi->oxcf.best_allowed_q;
+    cpi->cq_target_quality = cpi->oxcf.cq_level;
+
     cpi->buffered_mode = (cpi->oxcf.optimal_buffer_level > 0) ? TRUE : FALSE;
 
     cpi->rolling_target_bits          = cpi->av_per_frame_bandwidth;
@@ -1936,6 +1940,7 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
 
     cpi->oxcf.worst_allowed_q = q_trans[oxcf->worst_allowed_q];
     cpi->oxcf.best_allowed_q = q_trans[oxcf->best_allowed_q];
+    cpi->oxcf.cq_level = q_trans[cpi->oxcf.cq_level];
 
     if (oxcf->fixed_q >= 0)
     {
@@ -2028,7 +2033,6 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
     cpi->active_best_quality          = cpi->oxcf.best_allowed_q;
     cpi->buffered_mode = (cpi->oxcf.optimal_buffer_level > 0) ? TRUE : FALSE;
 
-    // Experimental cq target value
     cpi->cq_target_quality = cpi->oxcf.cq_level;
 
     cpi->rolling_target_bits          = cpi->av_per_frame_bandwidth;
@@ -3817,29 +3821,28 @@ static void encode_frame_to_data_rate
 
         if ( cm->frame_type == KEY_FRAME )
         {
-            // Special case for key frames forced because we have reached
-            // the maximum key frame interval. Here force the Q to a range
-            // close to but just below the ambient Q to minimize the risk
-            // of popping
-            if ( cpi->this_key_frame_forced )
-            {
-                cpi->active_worst_quality = cpi->avg_frame_qindex * 7/8;
-                cpi->active_best_quality = cpi->avg_frame_qindex * 2/3;
-            }
-            else
+            if ( cpi->pass == 2 )
             {
-               if ( cpi->pass == 2 )
-               {
-                   if (cpi->gfu_boost > 600)
-                       cpi->active_best_quality = kf_low_motion_minq[Q];
-                   else
-                       cpi->active_best_quality = kf_high_motion_minq[Q];
-               }
-               // One pass more conservative
-               else
+                if (cpi->gfu_boost > 600)
+                   cpi->active_best_quality = kf_low_motion_minq[Q];
+                else
                    cpi->active_best_quality = kf_high_motion_minq[Q];
+
+                // Special case for key frames forced because we have reached
+                // the maximum key frame interval. Here force the Q to a range
+                // based on the ambient Q to reduce the risk of popping
+                if ( cpi->this_key_frame_forced )
+                {
+                    if ( cpi->active_best_quality > cpi->avg_frame_qindex * 7/8)
+                        cpi->active_best_quality = cpi->avg_frame_qindex * 7/8;
+                    else if ( cpi->active_best_quality < cpi->avg_frame_qindex >> 2 )
+                        cpi->active_best_quality = cpi->avg_frame_qindex >> 2;
+                }
             }
-        }
+            // One pass more conservative
+            else
+               cpi->active_best_quality = kf_high_motion_minq[Q];
+         }
 
         else if (cm->refresh_golden_frame || cpi->common.refresh_alt_ref_frame)
         {
@@ -4153,9 +4156,44 @@ static void encode_frame_to_data_rate
             active_worst_qchanged = FALSE;
 
 #if !(CONFIG_REALTIME_ONLY)
+        // Special case handling for forced key frames
+        if ( (cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced )
+        {
+            int last_q = Q;
+            int kf_err = vp8_calc_ss_err(cpi->Source,
+                                         &cm->yv12_fb[cm->new_fb_idx],
+                                         IF_RTCD(&cpi->rtcd.variance));
+
+            // The key frame is not good enough
+            if ( kf_err > ((cpi->ambient_err * 3) >> 2) )
+            {
+                // Lower q_high
+                q_high = (Q > q_low) ? (Q - 1) : q_low;
+
+                // Adjust Q
+                Q = (q_high + q_low) >> 1;
+            }
+            // The key frame is much better than the previous frame
+            else if ( kf_err < (cpi->ambient_err >> 1) )
+            {
+                // Raise q_low
+                q_low = (Q < q_high) ? (Q + 1) : q_high;
+
+                // Adjust Q
+                Q = (q_high + q_low + 1) >> 1;
+            }
+
+            // Clamp Q to upper and lower limits:
+            if (Q > q_high)
+                Q = q_high;
+            else if (Q < q_low)
+                Q = q_low;
+
+            Loop = ((Q != last_q)) ? TRUE : FALSE;
+        }
 
         // Is the projected frame size out of range and are we allowed to attempt to recode.
-        if ( recode_loop_test( cpi,
+        else if ( recode_loop_test( cpi,
                                frame_over_shoot_limit, frame_under_shoot_limit,
                                Q, top_index, bottom_index ) )
         {
@@ -4171,7 +4209,7 @@ static void encode_frame_to_data_rate
                 //if ( cpi->zbin_over_quant == 0 )
                 q_low = (Q < q_high) ? (Q + 1) : q_high; // Raise Qlow as to at least the current value
 
-                if (cpi->zbin_over_quant > 0)           // If we are using over quant do the same for zbin_oq_low
+                if (cpi->zbin_over_quant > 0)            // If we are using over quant do the same for zbin_oq_low
                     zbin_oq_low = (cpi->zbin_over_quant < zbin_oq_high) ? (cpi->zbin_over_quant + 1) : zbin_oq_high;
 
                 //if ( undershoot_seen || (Q == MAXQ) )
@@ -4314,6 +4352,16 @@ static void encode_frame_to_data_rate
     }
 #endif
 
+    // Special case code to reduce pulsing when key frames are forced at a
+    // fixed interval. Note the reconstruction error if it is the frame before
+    // the force key frame
+    if ( cpi->next_key_frame_forced && (cpi->frames_to_key == 0) )
+    {
+        cpi->ambient_err = vp8_calc_ss_err(cpi->Source,
+                                           &cm->yv12_fb[cm->new_fb_idx],
+                                           IF_RTCD(&cpi->rtcd.variance));
+    }
+
     // Update the GF useage maps.
     // This is done after completing the compression of a frame when all modes etc. are finalized but before loop filter
     vp8_update_gf_useage_maps(cpi, cm, &cpi->mb);
@@ -4343,7 +4391,6 @@ static void encode_frame_to_data_rate
       }
     }
 
-
     // Update the GF useage maps.
     // This is done after completing the compression of a frame when all modes etc. are finalized but before loop filter
     vp8_update_gf_useage_maps(cpi, cm, &cpi->mb);
@@ -4374,8 +4421,6 @@ static void encode_frame_to_data_rate
     else
         cm->frame_to_show = &cm->yv12_fb[cm->new_fb_idx];
 
-
-
     //#pragma omp parallel sections
     {
 
index 6b07e2f225390fde2b2ae8c8e829d3d9d2bde32a..45fafd5b65559186be95cff7a34a607f267aeba3 100644 (file)
@@ -320,6 +320,9 @@ typedef struct
     unsigned int this_key_frame_forced;
     unsigned int next_key_frame_forced;
 
+    // Ambient reconstruction err target for force key frames
+    int ambient_err;
+
     unsigned int mode_check_freq[MAX_MODES];
     unsigned int mode_test_hit_counts[MAX_MODES];
     unsigned int mode_chosen_counts[MAX_MODES];
index 4c7aca520d7a105c25afeb5971cf0fbe7e895760..1c9009a57e0fd1f4e0ee06cf9a165ca9a4138d19 100644 (file)
@@ -310,6 +310,7 @@ static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
 
     oxcf->best_allowed_q          = cfg.rc_min_quantizer;
     oxcf->worst_allowed_q         = cfg.rc_max_quantizer;
+    oxcf->cq_level                = vp8_cfg.cq_level;
     oxcf->fixed_q = -1;
 
     oxcf->under_shoot_pct         = cfg.rc_undershoot_pct;
@@ -346,7 +347,6 @@ static vpx_codec_err_t set_vp8e_config(VP8_CONFIG *oxcf,
     oxcf->arnr_type =      vp8_cfg.arnr_type;
 
     oxcf->tuning = vp8_cfg.tuning;
-    oxcf->cq_level = vp8_cfg.cq_level;
 
     /*
         printf("Current VP8 Settings: \n");