shithub: libvpx

Download patch

ref: 339c512762542995d51086e1990cf47967687bb5
parent: a1a4d23797b2537f986859c57a73fa9330fa0ed5
author: Paul Wilkins <paulwilkins@google.com>
date: Mon Jan 17 12:23:11 EST 2011

Fix CQ range and experimental KF sizing changes.

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

--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -1551,6 +1551,7 @@
         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 @@
 
     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 @@
     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 @@
 
     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 @@
     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 @@
 
         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 )
+            if ( cpi->pass == 2 )
             {
-                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->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 @@
             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 @@
                 //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 @@
     }
 #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 @@
       }
     }
 
-
     // 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);
@@ -4373,8 +4420,6 @@
     }
     else
         cm->frame_to_show = &cm->yv12_fb[cm->new_fb_idx];
-
-
 
     //#pragma omp parallel sections
     {
--- a/vp8/encoder/onyx_int.h
+++ b/vp8/encoder/onyx_int.h
@@ -320,6 +320,9 @@
     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];
--- a/vp8/vp8_cx_iface.c
+++ b/vp8/vp8_cx_iface.c
@@ -310,6 +310,7 @@
 
     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 @@
     oxcf->arnr_type =      vp8_cfg.arnr_type;
 
     oxcf->tuning = vp8_cfg.tuning;
-    oxcf->cq_level = vp8_cfg.cq_level;
 
     /*
         printf("Current VP8 Settings: \n");