Further rate control cleanups
authorDeb Mukherjee <debargha@google.com>
Wed, 4 Dec 2013 01:05:19 +0000 (17:05 -0800)
committerDeb Mukherjee <debargha@google.com>
Fri, 6 Dec 2013 00:31:04 +0000 (16:31 -0800)
Includes various cleanups.
Streamlines the interfaces so that all rate control state
updates happen in the vp9_rc_postencode_update() function.
This will hopefully make it easier to support multiple
rate control schemes.
Removes some unnecessary code, which in rare cases can casue
a difference in the constrained quality mode output, but
other than that there is no bitstream change yet.

Change-Id: I3198cc37249932feea1e3691c0b2650e7b0c22fc

vp9/encoder/vp9_firstpass.c
vp9/encoder/vp9_onyx_if.c
vp9/encoder/vp9_onyx_int.h
vp9/encoder/vp9_ratectrl.c
vp9/encoder/vp9_ratectrl.h

index 50d8036..5ec0b76 100644 (file)
@@ -2170,21 +2170,6 @@ void vp9_second_pass(VP9_COMP *cpi) {
           (int)(cpi->twopass.bits_left / frames_left);
       cpi->twopass.est_max_qcorrection_factor = 1.0;
 
-      // Set a cq_level in constrained quality mode.
-      // Commenting this code out for now since it does not seem to be
-      // working well.
-      /*
-      if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) {
-        int est_cq = estimate_cq(cpi, &cpi->twopass.total_left_stats,
-           section_target_bandwidth);
-
-        if (est_cq > cpi->cq_target_quality)
-          cpi->cq_target_quality = est_cq;
-        else
-          cpi->cq_target_quality = cpi->oxcf.cq_level;
-      }
-      */
-
       // guess at maxq needed in 2nd pass
       cpi->twopass.maxq_max_limit = cpi->rc.worst_quality;
       cpi->twopass.maxq_min_limit = cpi->rc.best_quality;
index 968cbfb..e724eca 100644 (file)
@@ -143,8 +143,9 @@ static INLINE void Scale2Ratio(int mode, int *hr, int *hs) {
   }
 }
 
-static void set_mvcost(VP9_COMP *cpi) {
+static void set_high_precision_mv(VP9_COMP *cpi, int allow_high_precision_mv) {
   MACROBLOCK *const mb = &cpi->mb;
+  cpi->common.allow_high_precision_mv = allow_high_precision_mv;
   if (cpi->common.allow_high_precision_mv) {
     mb->mvcost = mb->nmvcost_hp;
     mb->mvsadcost = mb->nmvsadcost_hp;
@@ -234,7 +235,7 @@ static void dealloc_compressor_data(VP9_COMP *cpi) {
 // Computes a q delta (in "q index" terms) to get from a starting q value
 // to a target value
 // target q value
-int vp9_compute_qdelta(VP9_COMP *cpi, double qstart, double qtarget) {
+int vp9_compute_qdelta(const VP9_COMP *cpi, double qstart, double qtarget) {
   int i;
   int start_index = cpi->rc.worst_quality;
   int target_index = cpi->rc.worst_quality;
@@ -1115,8 +1116,8 @@ static void init_config(VP9_PTR ptr, VP9_CONFIG *oxcf) {
   vp9_change_config(ptr, oxcf);
 
   // Initialize active best and worst q and average q values.
-  cpi->rc.active_worst_quality         = cpi->oxcf.worst_allowed_q;
-  cpi->rc.active_best_quality          = cpi->oxcf.best_allowed_q;
+  cpi->rc.active_worst_quality      = cpi->oxcf.worst_allowed_q;
+
   cpi->rc.avg_frame_qindex          = cpi->oxcf.worst_allowed_q;
 
   // Initialise the starting buffer levels
@@ -1205,8 +1206,7 @@ void vp9_change_config(VP9_PTR ptr, VP9_CONFIG *oxcf) {
   cm->reset_frame_context = 0;
 
   setup_features(cm);
-  cpi->common.allow_high_precision_mv = 0;  // Default mv precision
-  set_mvcost(cpi);
+  set_high_precision_mv(cpi, 0);
 
   {
     int i;
@@ -1253,12 +1253,8 @@ void vp9_change_config(VP9_PTR ptr, VP9_CONFIG *oxcf) {
 
   // active values should only be modified if out of new range
   cpi->rc.active_worst_quality = clamp(cpi->rc.active_worst_quality,
-                                    cpi->oxcf.best_allowed_q,
-                                    cpi->oxcf.worst_allowed_q);
-
-  cpi->rc.active_best_quality = clamp(cpi->rc.active_best_quality,
-                                   cpi->oxcf.best_allowed_q,
-                                   cpi->oxcf.worst_allowed_q);
+                                       cpi->rc.best_quality,
+                                       cpi->rc.worst_quality);
 
   cpi->cq_target_quality = cpi->oxcf.cq_level;
 
@@ -2369,16 +2365,6 @@ static int find_fp_qindex() {
   return i;
 }
 
-static void Pass1Encode(VP9_COMP *cpi, unsigned long *size, unsigned char *dest,
-                        unsigned int *frame_flags) {
-  (void) size;
-  (void) dest;
-  (void) frame_flags;
-
-  vp9_set_quantizer(cpi, find_fp_qindex());
-  vp9_first_pass(cpi);
-}
-
 #define WRITE_RECON_BUFFER 0
 #if WRITE_RECON_BUFFER
 void write_cx_frame_to_file(YV12_BUFFER_CONFIG *frame, int this_frame) {
@@ -2470,16 +2456,9 @@ static int recode_loop_test(VP9_COMP *cpi,
           cpi->rc.projected_frame_size <
           ((cpi->rc.this_frame_target * 7) >> 3)) {
         force_recode = 1;
-      } else if (q > cpi->oxcf.cq_level &&
-                 cpi->rc.projected_frame_size < cpi->rc.min_frame_bandwidth &&
-                 cpi->rc.active_best_quality > cpi->oxcf.cq_level) {
-        // Severe undershoot and between auto and user cq level
-        force_recode = 1;
-        cpi->rc.active_best_quality = cpi->oxcf.cq_level;
       }
     }
   }
-
   return force_recode;
 }
 
@@ -2639,7 +2618,7 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) {
 
   if (cpi->twopass.total_left_stats.coded_error != 0.0)
     fprintf(f, "%10d %10d %10d %10d %10d %10d %10d %10d %10d"
-        "%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f"
+        "%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f"
         "%6d %6d %5d %5d %5d %8.2f %10d %10.3f"
         "%10.3f %8d %10d %10d %10d\n",
         cpi->common.current_video_frame, cpi->rc.this_frame_target,
@@ -2650,7 +2629,6 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) {
         (int)cpi->rc.total_actual_bits, cm->base_qindex,
         vp9_convert_qindex_to_q(cm->base_qindex),
         (double)vp9_dc_quant(cm->base_qindex, 0) / 4.0,
-        vp9_convert_qindex_to_q(cpi->rc.active_best_quality),
         vp9_convert_qindex_to_q(cpi->rc.active_worst_quality), cpi->rc.avg_q,
         vp9_convert_qindex_to_q(cpi->rc.ni_av_qi),
         vp9_convert_qindex_to_q(cpi->cq_target_quality),
@@ -2699,6 +2677,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
   int overshoot_seen = 0;
   int undershoot_seen = 0;
   int q_low = bottom_index, q_high = top_index;
+
   do {
     vp9_clear_system_state();  // __asm emms;
 
@@ -2816,11 +2795,13 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
             // Update rate_correction_factor unless
             vp9_rc_update_rate_correction_factors(cpi, 0);
 
-            *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target);
+            *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
+                                   bottom_index, top_index);
 
             while (*q < q_low && retries < 10) {
               vp9_rc_update_rate_correction_factors(cpi, 0);
-              *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target);
+              *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
+                                     bottom_index, top_index);
               retries++;
             }
           }
@@ -2831,18 +2812,12 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
           q_high = *q > q_low ? *q - 1 : q_low;
 
           if (overshoot_seen || loop_count > 1) {
-            // Update rate_correction_factor unless
-            // cpi->rc.active_worst_quality has changed.
             vp9_rc_update_rate_correction_factors(cpi, 1);
-
             *q = (q_high + q_low) / 2;
           } else {
-            // Update rate_correction_factor unless
-            // cpi->rc.active_worst_quality has changed.
             vp9_rc_update_rate_correction_factors(cpi, 0);
-
-            *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target);
-
+            *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
+                                   bottom_index, top_index);
             // Special case reset for qlow for constrained quality.
             // This should only trigger where there is very substantial
             // undershoot on a frame and the auto cq level is above
@@ -2854,7 +2829,8 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
 
             while (*q > q_high && retries < 10) {
               vp9_rc_update_rate_correction_factors(cpi, 0);
-              *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target);
+              *q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
+                                     bottom_index, top_index);
               retries++;
             }
           }
@@ -2893,8 +2869,8 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
   int q;
   int frame_over_shoot_limit;
   int frame_under_shoot_limit;
-
   int top_index;
+  int top_index_prop;
   int bottom_index;
 
   SPEED_FEATURES *const sf = &cpi->sf;
@@ -3008,45 +2984,8 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
 
   vp9_clear_system_state();
 
-  // Decide how big to make the frame.
-  vp9_rc_pick_frame_size_and_bounds(cpi,
-                                    &frame_under_shoot_limit,
-                                    &frame_over_shoot_limit);
-
-  q = vp9_rc_pick_q_and_adjust_q_bounds(cpi,
-                                        &bottom_index,
-                                        &top_index);
-
-#if CONFIG_MULTIPLE_ARF
-  // Force the quantizer determined by the coding order pattern.
-  if (cpi->multi_arf_enabled && (cm->frame_type != KEY_FRAME) &&
-      cpi->oxcf.end_usage != USAGE_CONSTANT_QUALITY) {
-    double new_q;
-    double current_q = vp9_convert_qindex_to_q(cpi->rc.active_worst_quality);
-    int level = cpi->this_frame_weight;
-    assert(level >= 0);
-
-    // Set quantizer steps at 10% increments.
-    new_q = current_q * (1.0 - (0.2 * (cpi->max_arf_level - level)));
-    q = cpi->rc.active_worst_quality +
-        vp9_compute_qdelta(cpi, current_q, new_q);
-
-    bottom_index = q;
-    top_index    = q;
-
-    printf("frame:%d q:%d\n", cm->current_video_frame, q);
-  }
-#endif
-
   vp9_zero(cpi->rd_tx_select_threshes);
 
-  if (!frame_is_intra_only(cm)) {
-    cm->mcomp_filter_type = DEFAULT_INTERP_FILTER;
-    /* TODO: Decide this more intelligently */
-    cm->allow_high_precision_mv = q < HIGH_PRECISION_MV_QTHRESH;
-    set_mvcost(cpi);
-  }
-
 #if CONFIG_VP9_POSTPROC
   if (cpi->oxcf.noise_sensitivity > 0) {
     int l = 0;
@@ -3076,6 +3015,26 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
   vp9_write_yuv_frame(cpi->Source);
 #endif
 
+  // Decide how big to make the frame.
+  vp9_rc_pick_frame_size_target(cpi);
+
+  // Decide frame size bounds
+  vp9_rc_compute_frame_size_bounds(cpi, cpi->rc.this_frame_target,
+                                   &frame_under_shoot_limit,
+                                   &frame_over_shoot_limit);
+
+  // Decide q and q bounds
+  q = vp9_rc_pick_q_and_adjust_q_bounds(cpi,
+                                        &bottom_index,
+                                        &top_index,
+                                        &top_index_prop);
+
+  if (!frame_is_intra_only(cm)) {
+    cm->mcomp_filter_type = DEFAULT_INTERP_FILTER;
+    /* TODO: Decide this more intelligently */
+    set_high_precision_mv(cpi, (q < HIGH_PRECISION_MV_QTHRESH));
+  }
+
   encode_with_recode_loop(cpi,
                           size,
                           dest,
@@ -3161,7 +3120,7 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
    * needed in motion search besides loopfilter */
   cm->last_frame_type = cm->frame_type;
 
-  vp9_rc_postencode_update(cpi, *size, q);
+  vp9_rc_postencode_update(cpi, *size, top_index_prop);
 
 #if 0
   output_frame_level_debug_stats(cpi);
@@ -3282,6 +3241,21 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
   cm->prev_mi_grid_visible = cm->prev_mi_grid_base + cm->mode_info_stride + 1;
 }
 
+static void Pass0Encode(VP9_COMP *cpi, unsigned long *size, unsigned char *dest,
+                        unsigned int *frame_flags) {
+  encode_frame_to_data_rate(cpi, size, dest, frame_flags);
+}
+
+static void Pass1Encode(VP9_COMP *cpi, unsigned long *size, unsigned char *dest,
+                        unsigned int *frame_flags) {
+  (void) size;
+  (void) dest;
+  (void) frame_flags;
+
+  vp9_set_quantizer(cpi, find_fp_qindex());
+  vp9_first_pass(cpi);
+}
+
 static void Pass2Encode(VP9_COMP *cpi, unsigned long *size,
                         unsigned char *dest, unsigned int *frame_flags) {
   cpi->enable_encode_breakout = 1;
@@ -3293,27 +3267,6 @@ static void Pass2Encode(VP9_COMP *cpi, unsigned long *size,
   // vp9_print_modes_and_motion_vectors(&cpi->common, "encode.stt");
 
   vp9_twopass_postencode_update(cpi, *size);
-
-  /*
-#ifdef DISABLE_RC_LONG_TERM_MEM
-  cpi->twopass.bits_left -=  cpi->rc.this_frame_target;
-#else
-  cpi->twopass.bits_left -= 8 * *size;
-#endif
-
-  if (!cpi->refresh_alt_ref_frame) {
-    double lower_bounds_min_rate = FRAME_OVERHEAD_BITS * cpi->oxcf.framerate;
-    double two_pass_min_rate = (double)(cpi->oxcf.target_bandwidth
-                                        * cpi->oxcf.two_pass_vbrmin_section
-                                        / 100);
-
-    if (two_pass_min_rate < lower_bounds_min_rate)
-      two_pass_min_rate = lower_bounds_min_rate;
-
-    cpi->twopass.bits_left += (int64_t)(two_pass_min_rate
-                              / cpi->oxcf.framerate);
-  }
-  */
 }
 
 static void check_initial_width(VP9_COMP *cpi, YV12_BUFFER_CONFIG *sd) {
@@ -3386,8 +3339,7 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags,
 
   cpi->source = NULL;
 
-  cpi->common.allow_high_precision_mv = ALTREF_HIGH_PRECISION_MV;
-  set_mvcost(cpi);
+  set_high_precision_mv(cpi, ALTREF_HIGH_PRECISION_MV);
 
   // Should we code an alternate reference frame.
   if (cpi->oxcf.play_alternate && cpi->source_alt_ref_pending) {
@@ -3627,7 +3579,8 @@ int vp9_get_compressed_data(VP9_PTR ptr, unsigned int *frame_flags,
   } else if (cpi->pass == 2) {
     Pass2Encode(cpi, size, dest, frame_flags);
   } else {
-    encode_frame_to_data_rate(cpi, size, dest, frame_flags);
+    // One pass encode
+    Pass0Encode(cpi, size, dest, frame_flags);
   }
 
   if (cm->refresh_frame_context)
index b8602e0..c631565 100644 (file)
@@ -338,7 +338,7 @@ typedef struct {
   int worst_quality;
   int active_worst_quality;
   int best_quality;
-  int active_best_quality;
+  // int active_best_quality;
 } RATE_CONTROL;
 
 typedef struct VP9_COMP {
@@ -695,7 +695,7 @@ int vp9_calc_ss_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest);
 
 void vp9_alloc_compressor_data(VP9_COMP *cpi);
 
-int vp9_compute_qdelta(VP9_COMP *cpi, double qstart, double qtarget);
+int vp9_compute_qdelta(const VP9_COMP *cpi, double qstart, double qtarget);
 
 static int get_token_alloc(int mb_rows, int mb_cols) {
   return mb_rows * mb_cols * (48 * 16 + 4);
index bf1fc4f..d631b31 100644 (file)
@@ -45,6 +45,10 @@ static int gf_high_motion_minq[QINDEX_RANGE];
 static int inter_minq[QINDEX_RANGE];
 static int afq_low_motion_minq[QINDEX_RANGE];
 static int afq_high_motion_minq[QINDEX_RANGE];
+static int gf_high = 2000;
+static int gf_low = 400;
+static int kf_high = 5000;
+static int kf_low = 400;
 
 // Functions to compute the active minq lookup table entries based on a
 // formulaic approach to facilitate easier adjustment of the Q tables.
@@ -84,7 +88,7 @@ void vp9_rc_init_minq_luts(void) {
     kf_high_motion_minq[i] = calculate_minq_index(maxq,
                                                   0.000002,
                                                   -0.0012,
-                                                  0.5,
+                                                  0.50,
                                                   0.0);
 
     gf_low_motion_minq[i] = calculate_minq_index(maxq,
@@ -97,11 +101,6 @@ void vp9_rc_init_minq_luts(void) {
                                                   -0.00125,
                                                   0.50,
                                                   0.0);
-    inter_minq[i] = calculate_minq_index(maxq,
-                                         0.00000271,
-                                         -0.00113,
-                                         0.75,
-                                         0.0);
     afq_low_motion_minq[i] = calculate_minq_index(maxq,
                                                   0.0000015,
                                                   -0.0009,
@@ -112,6 +111,11 @@ void vp9_rc_init_minq_luts(void) {
                                                    -0.00125,
                                                    0.55,
                                                    0.0);
+    inter_minq[i] = calculate_minq_index(maxq,
+                                         0.00000271,
+                                         -0.00113,
+                                         0.75,
+                                         0.0);
   }
 }
 
@@ -285,7 +289,6 @@ static void calc_pframe_target_size(VP9_COMP *cpi) {
   }
 }
 
-
 void vp9_rc_update_rate_correction_factors(VP9_COMP *cpi, int damp_var) {
   const int q = cpi->common.base_qindex;
   int correction_factor = 100;
@@ -333,7 +336,6 @@ void vp9_rc_update_rate_correction_factors(VP9_COMP *cpi, int damp_var) {
       break;
   }
 
-  // if ( (correction_factor > 102) && (Q < cpi->rc.active_worst_quality) )
   if (correction_factor > 102) {
     // We are not already at the worst allowable quality
     correction_factor =
@@ -367,8 +369,9 @@ void vp9_rc_update_rate_correction_factors(VP9_COMP *cpi, int damp_var) {
 }
 
 
-int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame) {
-  int q = cpi->rc.active_worst_quality;
+int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame,
+                      int active_best_quality, int active_worst_quality) {
+  int q = active_worst_quality;
 
   int i;
   int last_error = INT_MAX;
@@ -396,7 +399,7 @@ int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame) {
     target_bits_per_mb =
         (target_bits_per_frame << BPER_MB_NORMBITS) / cpi->common.MBs;
 
-  i = cpi->rc.active_best_quality;
+  i = active_best_quality;
 
   do {
     bits_per_mb_at_this_q = (int)vp9_rc_bits_per_mb(cpi->common.frame_type, i,
@@ -412,7 +415,7 @@ int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame) {
     } else {
       last_error = bits_per_mb_at_this_q - target_bits_per_mb;
     }
-  } while (++i <= cpi->rc.active_worst_quality);
+  } while (++i <= active_worst_quality);
 
   return q;
 }
@@ -438,14 +441,17 @@ static int get_active_quality(int q,
   return active_best_quality;
 }
 
-int vp9_rc_pick_q_and_adjust_q_bounds(VP9_COMP *cpi,
+int vp9_rc_pick_q_and_adjust_q_bounds(const VP9_COMP *cpi,
                                       int *bottom_index,
-                                      int *top_index) {
-  // Set an active best quality and if necessary active worst quality
-  int q = cpi->rc.active_worst_quality;
-  VP9_COMMON *const cm = &cpi->common;
+                                      int *top_index,
+                                      int *top_index_prop) {
+  const VP9_COMMON *const cm = &cpi->common;
+  int active_best_quality;
+  int active_worst_quality = cpi->rc.active_worst_quality;
+  int q;
 
   if (frame_is_intra_only(cm)) {
+    active_best_quality = cpi->rc.best_quality;
 #if !CONFIG_MULTIPLE_ARF
     // Handle the special case for key frames forced when we have75 reached
     // the maximum key frame interval. Here force the Q to a range
@@ -457,25 +463,19 @@ int vp9_rc_pick_q_and_adjust_q_bounds(VP9_COMP *cpi,
 
       delta_qindex = vp9_compute_qdelta(cpi, last_boosted_q,
                                         (last_boosted_q * 0.75));
-
-      cpi->rc.active_best_quality = MAX(qindex + delta_qindex,
-                                        cpi->rc.best_quality);
-    } else if (cpi->pass == 0 && cpi->common.current_video_frame == 0) {
-      // If this is the first (key) frame in 1-pass, active best/worst is
-      // the user best/worst-allowed, and leave the top_index to active_worst.
-      cpi->rc.active_best_quality = cpi->oxcf.best_allowed_q;
-      cpi->rc.active_worst_quality = cpi->oxcf.worst_allowed_q;
-    } else {
-      int high = 5000;
-      int low = 400;
+      active_best_quality = MAX(qindex + delta_qindex,
+                                cpi->rc.best_quality);
+    } else if (!(cpi->pass == 0 && cpi->common.current_video_frame == 0)) {
+      // not first frame of one pass
       double q_adj_factor = 1.0;
       double q_val;
 
       // Baseline value derived from cpi->active_worst_quality and kf boost
-      cpi->rc.active_best_quality = get_active_quality(q, cpi->rc.kf_boost,
-                                                       low, high,
-                                                       kf_low_motion_minq,
-                                                       kf_high_motion_minq);
+      active_best_quality = get_active_quality(active_worst_quality,
+                                               cpi->rc.kf_boost,
+                                               kf_low, kf_high,
+                                               kf_low_motion_minq,
+                                               kf_high_motion_minq);
 
       // Allow somewhat lower kf minq with small image formats.
       if ((cm->width * cm->height) <= (352 * 288)) {
@@ -487,124 +487,128 @@ int vp9_rc_pick_q_and_adjust_q_bounds(VP9_COMP *cpi,
 
       // Convert the adjustment factor to a qindex delta
       // on active_best_quality.
-      q_val = vp9_convert_qindex_to_q(cpi->rc.active_best_quality);
-      cpi->rc.active_best_quality +=
+      q_val = vp9_convert_qindex_to_q(active_best_quality);
+      active_best_quality +=
           vp9_compute_qdelta(cpi, q_val, (q_val * q_adj_factor));
     }
 #else
     double current_q;
     // Force the KF quantizer to be 30% of the active_worst_quality.
-    current_q = vp9_convert_qindex_to_q(cpi->rc.active_worst_quality);
-    cpi->rc.active_best_quality = cpi->rc.active_worst_quality
+    current_q = vp9_convert_qindex_to_q(active_worst_quality);
+    active_best_quality = active_worst_quality
         + vp9_compute_qdelta(cpi, current_q, current_q * 0.3);
 #endif
   } else if (!cpi->is_src_frame_alt_ref &&
              (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
-    int high = 2000;
-    int low = 400;
 
-    // Use the lower of cpi->rc.active_worst_quality and recent
+    // Use the lower of active_worst_quality and recent
     // average Q as basis for GF/ARF best Q limit unless last frame was
     // a key frame.
     if (cpi->frames_since_key > 1 &&
-        cpi->rc.avg_frame_qindex < cpi->rc.active_worst_quality) {
+        cpi->rc.avg_frame_qindex < active_worst_quality) {
       q = cpi->rc.avg_frame_qindex;
+    } else {
+      q = active_worst_quality;
     }
     // For constrained quality dont allow Q less than the cq level
     if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) {
       if (q < cpi->cq_target_quality)
         q = cpi->cq_target_quality;
       if (cpi->frames_since_key > 1) {
-        cpi->rc.active_best_quality = get_active_quality(q, cpi->rc.gfu_boost,
-                                                         low, high,
-                                                         afq_low_motion_minq,
-                                                         afq_high_motion_minq);
+        active_best_quality = get_active_quality(q, cpi->rc.gfu_boost,
+                                                 gf_low, gf_high,
+                                                 afq_low_motion_minq,
+                                                 afq_high_motion_minq);
       } else {
-        cpi->rc.active_best_quality = get_active_quality(q, cpi->rc.gfu_boost,
-                                                         low, high,
-                                                         gf_low_motion_minq,
-                                                         gf_high_motion_minq);
+        active_best_quality = get_active_quality(q, cpi->rc.gfu_boost,
+                                                 gf_low, gf_high,
+                                                 gf_low_motion_minq,
+                                                 gf_high_motion_minq);
       }
       // Constrained quality use slightly lower active best.
-      cpi->rc.active_best_quality = cpi->rc.active_best_quality * 15 / 16;
+      active_best_quality = active_best_quality * 15 / 16;
 
     } else if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
       if (!cpi->refresh_alt_ref_frame) {
-        cpi->rc.active_best_quality = cpi->cq_target_quality;
+        active_best_quality = cpi->cq_target_quality;
       } else {
         if (cpi->frames_since_key > 1) {
-          cpi->rc.active_best_quality = get_active_quality(
-              q, cpi->rc.gfu_boost, low, high,
+          active_best_quality = get_active_quality(
+              q, cpi->rc.gfu_boost, gf_low, gf_high,
               afq_low_motion_minq, afq_high_motion_minq);
         } else {
-          cpi->rc.active_best_quality = get_active_quality(
-              q, cpi->rc.gfu_boost, low, high,
+          active_best_quality = get_active_quality(
+              q, cpi->rc.gfu_boost, gf_low, gf_high,
               gf_low_motion_minq, gf_high_motion_minq);
         }
       }
     } else {
-        cpi->rc.active_best_quality = get_active_quality(
-            q, cpi->rc.gfu_boost, low, high,
-            gf_low_motion_minq, gf_high_motion_minq);
+      active_best_quality = get_active_quality(
+          q, cpi->rc.gfu_boost, gf_low, gf_high,
+          gf_low_motion_minq, gf_high_motion_minq);
     }
   } else {
     if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
-      cpi->rc.active_best_quality = cpi->cq_target_quality;
+      active_best_quality = cpi->cq_target_quality;
     } else {
-      cpi->rc.active_best_quality = inter_minq[q];
-      // 1-pass: for now, use the average Q for the active_best, if its lower
-      // than active_worst.
-      if (cpi->pass == 0 && (cpi->rc.avg_frame_qindex < q))
-        cpi->rc.active_best_quality = inter_minq[cpi->rc.avg_frame_qindex];
+      if (cpi->pass == 0 &&
+          cpi->rc.avg_frame_qindex < active_worst_quality)
+        // 1-pass: for now, use the average Q for the active_best, if its lower
+        // than active_worst.
+        active_best_quality = inter_minq[cpi->rc.avg_frame_qindex];
+      else
+        active_best_quality = inter_minq[active_worst_quality];
 
       // For the constrained quality mode we don't want
       // q to fall below the cq level.
       if ((cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) &&
-          (cpi->rc.active_best_quality < cpi->cq_target_quality)) {
+          (active_best_quality < cpi->cq_target_quality)) {
         // If we are strongly undershooting the target rate in the last
         // frames then use the user passed in cq value not the auto
         // cq value.
         if (cpi->rc.rolling_actual_bits < cpi->rc.min_frame_bandwidth)
-          cpi->rc.active_best_quality = cpi->oxcf.cq_level;
+          active_best_quality = cpi->oxcf.cq_level;
         else
-          cpi->rc.active_best_quality = cpi->cq_target_quality;
+          active_best_quality = cpi->cq_target_quality;
       }
     }
   }
 
   // Clip the active best and worst quality values to limits
-  if (cpi->rc.active_worst_quality > cpi->rc.worst_quality)
-    cpi->rc.active_worst_quality = cpi->rc.worst_quality;
+  if (active_worst_quality > cpi->rc.worst_quality)
+    active_worst_quality = cpi->rc.worst_quality;
 
-  if (cpi->rc.active_best_quality < cpi->rc.best_quality)
-    cpi->rc.active_best_quality = cpi->rc.best_quality;
+  if (active_best_quality < cpi->rc.best_quality)
+    active_best_quality = cpi->rc.best_quality;
 
-  if (cpi->rc.active_best_quality > cpi->rc.worst_quality)
-    cpi->rc.active_best_quality = cpi->rc.worst_quality;
+  if (active_best_quality > cpi->rc.worst_quality)
+    active_best_quality = cpi->rc.worst_quality;
 
-  if (cpi->rc.active_worst_quality < cpi->rc.active_best_quality)
-    cpi->rc.active_worst_quality = cpi->rc.active_best_quality;
+  if (active_worst_quality < active_best_quality)
+    active_worst_quality = active_best_quality;
 
-  *top_index = cpi->rc.active_worst_quality;
-  *bottom_index = cpi->rc.active_best_quality;
+  *top_index_prop = active_worst_quality;
+  *top_index = active_worst_quality;
+  *bottom_index = active_best_quality;
 
 #if LIMIT_QRANGE_FOR_ALTREF_AND_KEY
   // Limit Q range for the adaptive loop.
   if (cm->frame_type == KEY_FRAME && !cpi->this_key_frame_forced) {
     if (!(cpi->pass == 0 && cpi->common.current_video_frame == 0)) {
+      *top_index = active_worst_quality;
       *top_index =
-          (cpi->rc.active_worst_quality + cpi->rc.active_best_quality * 3) / 4;
+          (active_worst_quality + active_best_quality * 3) / 4;
     }
   } else if (!cpi->is_src_frame_alt_ref &&
              (cpi->oxcf.end_usage != USAGE_STREAM_FROM_SERVER) &&
              (cpi->refresh_golden_frame || cpi->refresh_alt_ref_frame)) {
     *top_index =
-      (cpi->rc.active_worst_quality + cpi->rc.active_best_quality) / 2;
+      (active_worst_quality + active_best_quality) / 2;
   }
 #endif
 
   if (cpi->oxcf.end_usage == USAGE_CONSTANT_QUALITY) {
-    q = cpi->rc.active_best_quality;
+    q = active_best_quality;
   // Special case code to try and match quality with forced key frames
   } else if ((cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced) {
     q = cpi->rc.last_boosted_qindex;
@@ -614,17 +618,35 @@ int vp9_rc_pick_q_and_adjust_q_bounds(VP9_COMP *cpi,
       // 1-pass: for now, use per-frame-bw for target size of frame, scaled
       // by |x| for key frame.
       int scale = (cm->frame_type == KEY_FRAME) ? 5 : 1;
-      q = vp9_rc_regulate_q(cpi, scale * cpi->rc.av_per_frame_bandwidth);
+      q = vp9_rc_regulate_q(cpi, scale * cpi->rc.av_per_frame_bandwidth,
+                            active_best_quality, active_worst_quality);
     } else {
-      q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target);
+      q = vp9_rc_regulate_q(cpi, cpi->rc.this_frame_target,
+                            active_best_quality, active_worst_quality);
     }
     if (q > *top_index)
       q = *top_index;
   }
+#if CONFIG_MULTIPLE_ARF
+  // Force the quantizer determined by the coding order pattern.
+  if (cpi->multi_arf_enabled && (cm->frame_type != KEY_FRAME) &&
+      cpi->oxcf.end_usage != USAGE_CONSTANT_QUALITY) {
+    double new_q;
+    double current_q = vp9_convert_qindex_to_q(active_worst_quality);
+    int level = cpi->this_frame_weight;
+    assert(level >= 0);
+    new_q = current_q * (1.0 - (0.2 * (cpi->max_arf_level - level)));
+    q = active_worst_quality +
+        vp9_compute_qdelta(cpi, current_q, new_q);
+
+    *bottom_index = q;
+    *top_index    = q;
+    printf("frame:%d q:%d\n", cm->current_video_frame, q);
+  }
+#endif
   return q;
 }
 
-
 static int estimate_keyframe_frequency(VP9_COMP *cpi) {
   int i;
 
@@ -680,8 +702,7 @@ static void adjust_key_frame_context(VP9_COMP *cpi) {
   cpi->rc.key_frame_count++;
 }
 
-
-static void compute_frame_size_bounds(const VP9_COMP *cpi,
+void vp9_rc_compute_frame_size_bounds(const VP9_COMP *cpi,
                                       int this_frame_target,
                                       int *frame_under_shoot_limit,
                                       int *frame_over_shoot_limit) {
@@ -720,9 +741,7 @@ static void compute_frame_size_bounds(const VP9_COMP *cpi,
 }
 
 // return of 0 means drop frame
-int vp9_rc_pick_frame_size_and_bounds(VP9_COMP *cpi,
-                                      int *frame_under_shoot_limit,
-                                      int *frame_over_shoot_limit) {
+int vp9_rc_pick_frame_size_target(VP9_COMP *cpi) {
   VP9_COMMON *cm = &cpi->common;
 
   if (cm->frame_type == KEY_FRAME)
@@ -733,13 +752,11 @@ int vp9_rc_pick_frame_size_and_bounds(VP9_COMP *cpi,
   // Target rate per SB64 (including partial SB64s.
   cpi->rc.sb64_target_rate = ((int64_t)cpi->rc.this_frame_target * 64 * 64) /
                              (cpi->common.width * cpi->common.height);
-  compute_frame_size_bounds(cpi, cpi->rc.this_frame_target,
-                            frame_under_shoot_limit, frame_over_shoot_limit);
-
   return 1;
 }
 
-void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used, int q) {
+void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used,
+                              int worst_q) {
   VP9_COMMON *const cm = &cpi->common;
   // Update rate control heuristics
   cpi->rc.projected_frame_size = (bytes_used << 3);
@@ -750,6 +767,7 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used, int q) {
             cpi->oxcf.end_usage == USAGE_STREAM_FROM_SERVER) ? 2 : 0);
 
   cpi->rc.last_q[cm->frame_type] = cm->base_qindex;
+  cpi->rc.active_worst_quality = worst_q;
 
   // Keep record of last boosted (KF/KF/ARF) Q value.
   // If the current frame is coded at a lower Q then we also update it.
@@ -777,11 +795,11 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used, int q) {
   if (cm->frame_type != KEY_FRAME &&
       !cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame) {
     cpi->rc.ni_frames++;
-    cpi->rc.tot_q += vp9_convert_qindex_to_q(q);
+    cpi->rc.tot_q += vp9_convert_qindex_to_q(cm->base_qindex);
     cpi->rc.avg_q = cpi->rc.tot_q / (double)cpi->rc.ni_frames;
 
     // Calculate the average Q for normal inter frames (not key or GFU frames).
-    cpi->rc.ni_tot_qi += q;
+    cpi->rc.ni_tot_qi += cm->base_qindex;
     cpi->rc.ni_av_qi = cpi->rc.ni_tot_qi / cpi->rc.ni_frames;
   }
 
index f01d186..063ac8f 100644 (file)
@@ -31,23 +31,29 @@ void vp9_rc_update_rate_correction_factors(VP9_COMP *cpi, int damp_var);
 void vp9_rc_init_minq_luts(void);
 
 // return of 0 means drop frame
-// Changes rc.this_frame_target and rc.sb64_rate_target
-int vp9_rc_pick_frame_size_and_bounds(VP9_COMP *cpi,
+// Changes only rc.this_frame_target and rc.sb64_rate_target
+int vp9_rc_pick_frame_size_target(VP9_COMP *cpi);
+
+void vp9_rc_compute_frame_size_bounds(const VP9_COMP *cpi,
+                                      int this_frame_target,
                                       int *frame_under_shoot_limit,
                                       int *frame_over_shoot_limit);
+
 // Picks q and q bounds given the target for bits
-int vp9_rc_pick_q_and_adjust_q_bounds(VP9_COMP *cpi,
-                                      int * bottom_index,
-                                      int * top_index);
+int vp9_rc_pick_q_and_adjust_q_bounds(const VP9_COMP *cpi,
+                                      int *bottom_index,
+                                      int *top_index,
+                                      int *top_index_prop);
 
 // Estimates q to achieve a target bits per frame
-int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame);
+int vp9_rc_regulate_q(const VP9_COMP *cpi, int target_bits_per_frame,
+                      int active_best_quality, int active_worst_quality);
 
 // Post encode update of the rate control parameters based
 // on bytes used and q used for the frame
 void vp9_rc_postencode_update(VP9_COMP *cpi,
                               uint64_t bytes_used,
-                              int q_used);
+                              int worst_q);
 
 // estimates bits per mb for a given qindex and correction factor
 int vp9_rc_bits_per_mb(FRAME_TYPE frame_type, int qindex,