shithub: libvpx

Download patch

ref: 3cb26b486490b4961fd5c7d897112b12a121a3e7
parent: cd5932d2e18f21936fed6a83f962f6614e31507f
parent: c28b10adebc0f56892310892a9d31f10360bd43b
author: John Koleszar <jkoleszar@google.com>
date: Fri Jan 7 19:05:08 EST 2011

Merge remote branch 'origin/master' into experimental

Change-Id: Ib34bc09a295141eb65c8c0478bde6136f178909b

--- a/vp8/common/onyx.h
+++ b/vp8/common/onyx.h
@@ -46,7 +46,8 @@
     typedef enum
     {
         USAGE_STREAM_FROM_SERVER    = 0x0,
-        USAGE_LOCAL_FILE_PLAYBACK   = 0x1
+        USAGE_LOCAL_FILE_PLAYBACK   = 0x1,
+        USAGE_CONSTRAINED_QUALITY   = 0x2
     } END_USAGE;
 
 
@@ -150,6 +151,7 @@
         int fixed_q;
         int worst_allowed_q;
         int best_allowed_q;
+        int cq_level;
 
         // allow internal resizing ( currently disabled in the build !!!!!)
         int allow_spatial_resampling;
@@ -186,7 +188,6 @@
         int arnr_max_frames;
         int arnr_strength ;
         int arnr_type     ;
-
 
         struct vpx_fixed_buf         two_pass_stats_in;
         struct vpx_codec_pkt_list  *output_pkt_list;
--- a/vp8/encoder/encodeframe.c
+++ b/vp8/encoder/encodeframe.c
@@ -734,20 +734,6 @@
 
     x->activity_sum = 0;
 
-#if 0
-    // Experimental rd code
-    // 2 Pass - Possibly set Rdmult based on last frame distortion + this frame target bits or other metrics
-    // such as cpi->rate_correction_factor that indicate relative complexity.
-    /*if ( cpi->pass == 2 && (cpi->last_frame_distortion > 0) && (cpi->target_bits_per_mb > 0) )
-    {
-        //x->rdmult = ((cpi->last_frame_distortion * 256)/cpi->common.MBs)/ cpi->target_bits_per_mb;
-        x->rdmult = (int)(cpi->RDMULT * cpi->rate_correction_factor);
-    }
-    else
-        x->rdmult = cpi->RDMULT; */
-    //x->rdmult = (int)(cpi->RDMULT * pow( (cpi->rate_correction_factor * 2.0), 0.75 ));
-#endif
-
     xd->mode_info_context->mbmi.mode = DC_PRED;
     xd->mode_info_context->mbmi.uv_mode = DC_PRED;
 
--- a/vp8/encoder/firstpass.c
+++ b/vp8/encoder/firstpass.c
@@ -58,6 +58,7 @@
 
 #define KF_MB_INTRA_MIN 300
 #define GF_MB_INTRA_MIN 200
+
 #define DOUBLE_DIVIDE_CHECK(X) ((X)<0?(X)-.000001:(X)+.000001)
 
 #define POW1 (double)cpi->oxcf.two_pass_vbrbias/100.0
@@ -67,6 +68,18 @@
 static int hscale_lookup[7] = {0, 0, 1, 1, 2, 2, 3};
 
 
+const int cq_level[QINDEX_RANGE] =
+{
+    0,0,1,1,2,3,3,4,4,5,6,6,7,8,8,9,
+    9,10,11,11,12,13,13,14,15,15,16,17,17,18,19,20,
+    20,21,22,22,23,24,24,25,26,27,27,28,29,30,30,31,
+    32,33,33,34,35,36,36,37,38,39,39,40,41,42,42,43,
+    44,45,46,46,47,48,49,50,50,51,52,53,54,55,55,56,
+    57,58,59,60,60,61,62,63,64,65,66,67,67,68,69,70,
+    71,72,73,74,75,75,76,77,78,79,80,81,82,83,84,85,
+    86,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100
+};
+
 void vp8_find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame);
 int vp8_input_stats(VP8_COMP *cpi, FIRSTPASS_STATS *fps);
 
@@ -890,7 +903,7 @@
 }
 extern const int vp8_bits_per_mb[2][QINDEX_RANGE];
 
-#define BASE_ERRPERMB   150
+#define BASE_ERRPERMB   100
 static int estimate_max_q(VP8_COMP *cpi, double section_err, int section_target_bandwitdh, int Height, int Width)
 {
     int Q;
@@ -907,7 +920,7 @@
     double pow_lowq = 0.40;
 
     if (section_target_bandwitdh <= 0)
-        return MAXQ;
+        return cpi->maxq_max_limit;          // Highest value allowed
 
     target_norm_bits_per_mb = (section_target_bandwitdh < (1 << 20)) ? (512 * section_target_bandwitdh) / num_mbs : 512 * (section_target_bandwitdh / num_mbs);
 
@@ -943,10 +956,12 @@
 
     // Correction factor used for Q values >= 20
     corr_high = pow(err_per_mb / BASE_ERRPERMB, pow_highq);
-    corr_high = (corr_high < 0.05) ? 0.05 : (corr_high > 5.0) ? 5.0 : corr_high;
+    corr_high = (corr_high < 0.05)
+                    ? 0.05 : (corr_high > 5.0) ? 5.0 : corr_high;
 
-    // Try and pick a Q that should be high enough to encode the content at the given rate.
-    for (Q = 0; Q < MAXQ; Q++)
+    // Try and pick a max Q that will be high enough to encode the
+    // content at the given rate.
+    for (Q = cpi->maxq_min_limit; Q < cpi->maxq_max_limit; Q++)
     {
         int bits_per_mb_at_this_q;
 
@@ -965,6 +980,15 @@
             break;
     }
 
+    // Restriction on active max q for constrained quality mode.
+    if ( (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) &&
+         (Q < cpi->cq_target_quality) )
+         //(Q < cpi->oxcf.cq_target_quality) )
+    {
+        Q = cpi->cq_target_quality;
+        //Q = cpi->oxcf.cq_target_quality;
+    }
+
     return Q;
 }
 static int estimate_q(VP8_COMP *cpi, double section_err, int section_target_bandwitdh, int Height, int Width)
@@ -1113,6 +1137,79 @@
 
     return Q;
 }
+
+// For cq mode estimate a cq level that matches the observed
+// complexity and data rate.
+static int estimate_cq(VP8_COMP *cpi, double section_err,
+                       int section_target_bandwitdh, int Height, int Width)
+{
+    int Q;
+    int num_mbs = ((Height * Width) / (16 * 16));
+    int target_norm_bits_per_mb;
+
+    double err_per_mb = section_err / num_mbs;
+    double correction_factor;
+    double corr_high;
+    double speed_correction = 1.0;
+    double pow_highq = 0.90;
+    double pow_lowq = 0.40;
+    double clip_iiratio;
+    double clip_iifactor;
+
+    target_norm_bits_per_mb = (section_target_bandwitdh < (1 << 20))
+                              ? (512 * section_target_bandwitdh) / num_mbs
+                              : 512 * (section_target_bandwitdh / num_mbs);
+
+    // Corrections for higher compression speed settings
+    // (reduced compression expected)
+    if ((cpi->compressor_speed == 3) || (cpi->compressor_speed == 1))
+    {
+        if (cpi->oxcf.cpu_used <= 5)
+            speed_correction = 1.04 + (cpi->oxcf.cpu_used * 0.04);
+        else
+            speed_correction = 1.25;
+    }
+    // II ratio correction factor for clip as a whole
+    clip_iiratio = cpi->total_stats->intra_error /
+                   DOUBLE_DIVIDE_CHECK(cpi->total_stats->coded_error);
+    clip_iifactor = 1.0 - ((clip_iiratio - 10.0) * 0.025);
+    if (clip_iifactor < 0.80)
+        clip_iifactor = 0.80;
+
+    // Correction factor used for Q values >= 20
+    corr_high = pow(err_per_mb / BASE_ERRPERMB, pow_highq);
+    corr_high = (corr_high < 0.05) ? 0.05 : (corr_high > 5.0) ? 5.0 : corr_high;
+
+    // Try and pick a Q that can encode the content at the given rate.
+    for (Q = 0; Q < MAXQ; Q++)
+    {
+        int bits_per_mb_at_this_q;
+
+        if (Q < 50)
+        {
+            correction_factor =
+                pow( err_per_mb / BASE_ERRPERMB, (pow_lowq + Q * 0.01));
+
+            correction_factor = (correction_factor < 0.05) ? 0.05
+                                    : (correction_factor > 5.0) ? 5.0
+                                        : correction_factor;
+        }
+        else
+            correction_factor = corr_high;
+
+        bits_per_mb_at_this_q =
+            (int)( .5 + correction_factor *
+                        speed_correction *
+                        clip_iifactor *
+                        (double)vp8_bits_per_mb[INTER_FRAME][Q] / 1.0);
+
+        if (bits_per_mb_at_this_q <= target_norm_bits_per_mb)
+            break;
+    }
+
+    return cq_level[Q];
+}
+
 extern void vp8_new_frame_rate(VP8_COMP *cpi, double framerate);
 
 void vp8_init_second_pass(VP8_COMP *cpi)
@@ -1766,7 +1863,9 @@
 
         vp8_avg_stats(&sectionstats);
 
-        cpi->section_intra_rating = sectionstats.intra_error / DOUBLE_DIVIDE_CHECK(sectionstats.coded_error);
+        cpi->section_intra_rating =
+            sectionstats.intra_error /
+            DOUBLE_DIVIDE_CHECK(sectionstats.coded_error);
 
         Ratio = sectionstats.intra_error / DOUBLE_DIVIDE_CHECK(sectionstats.coded_error);
         //if( (Ratio > 11) ) //&& (sectionstats.pcnt_second_ref < .20) )
@@ -1993,21 +2092,48 @@
 
     if (cpi->common.current_video_frame == 0)
     {
-        // guess at 2nd pass q
         cpi->est_max_qcorrection_factor = 1.0;
-        tmp_q = estimate_max_q(cpi, (cpi->total_coded_error_left / frames_left), (int)(cpi->bits_left / frames_left), cpi->common.Height, cpi->common.Width);
 
-        if (tmp_q < cpi->worst_quality)
+        // Experimental code to try and set a cq_level in constrained
+        // quality mode.
+        if ( cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY )
         {
-            cpi->active_worst_quality         = tmp_q;
-            cpi->ni_av_qi                     = tmp_q;
+            int est_cq;
+
+            est_cq =
+                estimate_cq( cpi,
+                             (cpi->total_coded_error_left / frames_left),
+                             (int)(cpi->bits_left / frames_left),
+                             cpi->common.Height, cpi->common.Width);
+
+            cpi->cq_target_quality = cpi->oxcf.cq_level;
+            if ( est_cq > cpi->cq_target_quality )
+                cpi->cq_target_quality = est_cq;
         }
-        else
-        {
-            cpi->active_worst_quality         = cpi->worst_quality;
-            cpi->ni_av_qi                     = cpi->worst_quality;
-        }
+
+        // guess at maxq needed in 2nd pass
+        cpi->maxq_max_limit = cpi->worst_quality;
+        cpi->maxq_min_limit = cpi->best_quality;
+        tmp_q = estimate_max_q( cpi,
+                                (cpi->total_coded_error_left / frames_left),
+                                (int)(cpi->bits_left / frames_left),
+                                cpi->common.Height,
+                                cpi->common.Width);
+
+        // Limit the maxq value returned subsequently.
+        // This increases the risk of overspend if the initial
+        // estimate for the clip is bad, but helps prevent excessive
+        // variation in Q, especially near the end of a clip
+        // where for example a small overspend may cause Q to crash
+        cpi->maxq_max_limit = ((tmp_q + 32) < cpi->worst_quality)
+                                  ? (tmp_q + 32) : cpi->worst_quality;
+        cpi->maxq_min_limit = ((tmp_q - 32) > cpi->best_quality)
+                                  ? (tmp_q - 32) : cpi->best_quality;
+
+        cpi->active_worst_quality         = tmp_q;
+        cpi->ni_av_qi                     = tmp_q;
     }
+
     // The last few frames of a clip almost always have to few or too many
     // bits and for the sake of over exact rate control we dont want to make
     // radical adjustments to the allowed quantizer range just to use up a
@@ -2029,13 +2155,6 @@
             cpi->active_worst_quality --;
 
         cpi->active_worst_quality = ((cpi->active_worst_quality * 3) + tmp_q + 2) / 4;
-
-        // Clamp to user set limits
-        if (cpi->active_worst_quality > cpi->worst_quality)
-            cpi->active_worst_quality = cpi->worst_quality;
-        else if (cpi->active_worst_quality < cpi->best_quality)
-            cpi->active_worst_quality = cpi->best_quality;
-
     }
 
     cpi->frames_to_key --;
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -155,25 +155,25 @@
 // Tables relating active max Q to active min Q
 static const int kf_low_motion_minq[QINDEX_RANGE] =
 {
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4,
-    5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 10,10,
-    11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,
-    19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,
-    27,27,28,28,29,29,30,30,31,32,33,34,35,36,37,38,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,
+    3,3,3,3,3,3,4,4,4,5,5,5,5,5,6,6,
+    6,6,7,7,8,8,8,8,9,9,10,10,10,10,11,11,
+    11,11,12,12,13,13,13,13,14,14,15,15,15,15,16,16,
+    16,16,17,17,18,18,18,18,19,20,20,21,21,22,23,23
 };
 static const int kf_high_motion_minq[QINDEX_RANGE] =
 {
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
-    2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5,
-    6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,10,
-    11,11,12,12,13,13,14,14,15,15,16,16,17,17,18,18,
-    19,19,20,20,21,21,22,22,23,23,24,24,25,25,26,26,
-    27,27,28,28,29,29,30,30,31,31,32,32,33,33,34,34,
-    35,35,36,36,37,38,39,40,41,42,43,44,45,46,47,48,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+    1,1,1,1,1,1,1,1,2,2,2,2,3,3,3,3,
+    3,3,3,3,4,4,4,4,5,5,5,5,5,5,6,6,
+    6,6,7,7,8,8,8,8,9,9,10,10,10,10,11,11,
+    11,11,12,12,13,13,13,13,14,14,15,15,15,15,16,16,
+    16,16,17,17,18,18,18,18,19,19,20,20,20,20,21,21,
+    21,21,22,22,23,23,24,25,25,26,26,27,28,28,29,30
 };
 static const int gf_low_motion_minq[QINDEX_RANGE] =
 {
@@ -195,7 +195,7 @@
     22,22,23,23,24,24,25,25,26,26,27,27,28,28,29,29,
     30,30,31,31,32,32,33,33,34,34,35,35,36,36,37,37,
     38,39,39,40,40,41,41,42,42,43,43,44,45,46,47,48,
-    49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,
+    49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64
 };
 static const int gf_high_motion_minq[QINDEX_RANGE] =
 {
@@ -206,7 +206,7 @@
     25,25,26,26,27,27,28,28,29,29,30,30,31,31,32,32,
     33,33,34,34,35,35,36,36,37,37,38,38,39,39,40,40,
     41,41,42,42,43,44,45,46,47,48,49,50,51,52,53,54,
-    55,56,57,58,59,60,62,64,66,68,70,72,74,76,78,80,
+    55,56,57,58,59,60,62,64,66,68,70,72,74,76,78,80
 };
 static const int inter_minq[QINDEX_RANGE] =
 {
@@ -576,7 +576,7 @@
 
     cpi->mbs_tested_so_far = 0;
 
-    // best quality
+    // best quality defaults
     sf->RD = 1;
     sf->search_method = NSTEP;
     sf->improved_quant = 1;
@@ -1268,6 +1268,15 @@
 
     };
 
+    // Slow quant, dct and trellis not worthwhile for first pass
+    // so make sure they are always turned off.
+    if ( cpi->pass == 1 )
+    {
+        sf->improved_quant = 0;
+        sf->optimize_coefficients = 0;
+        sf->improved_dct = 0;
+    }
+
     if (cpi->sf.search_method == NSTEP)
     {
         vp8_init3smotion_compensation(&cpi->mb, cm->yv12_fb[cm->lst_fb_idx].y_stride);
@@ -2017,6 +2026,9 @@
     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 = oxcf->cq_level;
+
     cpi->rolling_target_bits          = cpi->av_per_frame_bandwidth;
     cpi->rolling_actual_bits          = cpi->av_per_frame_bandwidth;
     cpi->long_rolling_target_bits      = cpi->av_per_frame_bandwidth;
@@ -3081,9 +3093,6 @@
         }
     }
 
-    // Note target_size in bits * 256 per MB
-    cpi->target_bits_per_mb = (cpi->this_frame_target * 256) / cpi->common.MBs;
-
     return 1;
 }
 static void set_quantizer(VP8_COMP *cpi, int Q)
@@ -3506,12 +3515,14 @@
     {
         // General over and under shoot tests
         if ( ((cpi->projected_frame_size > high_limit) && (q < maxq)) ||
-             ((cpi->projected_frame_size < low_limit) && (q > minq)) )
+             ((cpi->projected_frame_size < low_limit) && (q > minq)) ||
+             ((cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) &&
+              (q > cpi->cq_target_quality) &&
+              (cpi->projected_frame_size <
+                  ((cpi->this_frame_target * 7) >> 3))) )
         {
             force_recode = TRUE;
         }
-        // Specific rate control mode related tests
-        // TBD
     }
 
     return force_recode;
@@ -3802,15 +3813,7 @@
                     cpi->active_best_quality = gf_high_motion_minq[Q];
                 else
                     cpi->active_best_quality = gf_mid_motion_minq[Q];
-
-                /*cpi->active_best_quality = gf_arf_minq[Q];
-                tmp = (cpi->gfu_boost > 1000) ? 600 : cpi->gfu_boost - 400;
-                //tmp = (cpi->gfu_boost > 1000) ? 600 :
-                          //(cpi->gfu_boost < 400) ? 0 : cpi->gfu_boost - 400;
-                tmp = 128 - (tmp >> 4);
-                cpi->active_best_quality = (cpi->active_best_quality * tmp)>>7;*/
-
-           }
+          }
            // KEY FRAMES
            else
            {
@@ -3823,6 +3826,14 @@
         else
         {
             cpi->active_best_quality = inter_minq[Q];
+
+            // For the constant/constrained quality mode we dont want
+            // the quality to rise above the cq level.
+            if ((cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY) &&
+                (cpi->active_best_quality < cpi->cq_target_quality) )
+            {
+                cpi->active_best_quality = cpi->cq_target_quality;
+            }
         }
 
         // If CBR and the buffer is as full then it is reasonable to allow higher quality on the frames
@@ -4557,7 +4568,8 @@
                        (cpi->oxcf.starting_buffer_level-cpi->bits_off_target),
                        (int)cpi->total_actual_bits, cm->base_qindex,
                        cpi->active_best_quality, cpi->active_worst_quality,
-                       cpi->avg_frame_qindex, cpi->zbin_over_quant,
+                       cpi->cq_target_quality, cpi->zbin_over_quant,
+                       //cpi->avg_frame_qindex, cpi->zbin_over_quant,
                        cm->refresh_golden_frame, cm->refresh_alt_ref_frame,
                        cm->frame_type, cpi->gfu_boost,
                        cpi->est_max_qcorrection_factor, (int)cpi->bits_left,
@@ -4575,7 +4587,8 @@
                        (cpi->oxcf.starting_buffer_level-cpi->bits_off_target),
                        (int)cpi->total_actual_bits, cm->base_qindex,
                        cpi->active_best_quality, cpi->active_worst_quality,
-                       cpi->avg_frame_qindex, cpi->zbin_over_quant,
+                       cpi->cq_target_quality, cpi->zbin_over_quant,
+                       //cpi->avg_frame_qindex, cpi->zbin_over_quant,
                        cm->refresh_golden_frame, cm->refresh_alt_ref_frame,
                        cm->frame_type, cpi->gfu_boost,
                        cpi->est_max_qcorrection_factor, (int)cpi->bits_left,
--- a/vp8/encoder/onyx_int.h
+++ b/vp8/encoder/onyx_int.h
@@ -365,7 +365,6 @@
     int this_frame_target;
     int projected_frame_size;
     int last_q[2];                   // Separate values for Intra/Inter
-    int target_bits_per_mb;
 
     double rate_correction_factor;
     double key_frame_rate_correction_factor;
@@ -446,6 +445,10 @@
     int active_worst_quality;
     int best_quality;
     int active_best_quality;
+
+    int cq_target_quality;
+    int maxq_max_limit;
+    int maxq_min_limit;
 
     int drop_frames_allowed;          // Are we permitted to drop frames?
     int drop_frame;                  // Drop this frame?
--- a/vp8/encoder/ratectrl.c
+++ b/vp8/encoder/ratectrl.c
@@ -1550,12 +1550,21 @@
                         *frame_under_shoot_limit = cpi->this_frame_target * 5 / 8;
                     }
                 }
-                // VBR
+                // VBR and CQ mode
                 // Note that tighter restrictions here can help quality but hurt encode speed
                 else
                 {
-                    *frame_over_shoot_limit  = cpi->this_frame_target * 11 / 8;
-                    *frame_under_shoot_limit = cpi->this_frame_target * 5 / 8;
+                    // Stron overshoot limit for constrained quality
+                    if (cpi->oxcf.end_usage == USAGE_CONSTRAINED_QUALITY)
+                    {
+                        *frame_over_shoot_limit  = cpi->this_frame_target * 11 / 8;
+                        *frame_under_shoot_limit = cpi->this_frame_target * 2 / 8;
+                    }
+                    else
+                    {
+                        *frame_over_shoot_limit  = cpi->this_frame_target * 11 / 8;
+                        *frame_under_shoot_limit = cpi->this_frame_target * 5 / 8;
+                    }
                 }
             }
         }
--- a/vp8/encoder/rdopt.c
+++ b/vp8/encoder/rdopt.c
@@ -36,7 +36,6 @@
 #include "dct.h"
 #include "systemdependent.h"
 
-#define DIAMONDSEARCH 1
 #if CONFIG_RUNTIME_CPU_DETECT
 #define IF_RTCD(x)  (x)
 #else
@@ -46,19 +45,6 @@
 
 void vp8cx_mb_init_quantizer(VP8_COMP *cpi, MACROBLOCK *x);
 
-
-#define RDFUNC(RM,DM,R,D,target_rd) ( ((128+(R)*(RM)) >> 8) + (DM)*(D) )
-/*int  RDFUNC( int RM,int DM, int R, int D, int target_r )
-{
-    int rd_value;
-
-    rd_value =  ( ((128+(R)*(RM)) >> 8) + (DM)*(D) );
-
-    return rd_value;
-}*/
-
-#define UVRDFUNC(RM,DM,R,D,target_r)  RDFUNC(RM,DM,R,D,target_r)
-
 #define RDCOST(RM,DM,R,D) ( ((128+(R)*(RM)) >> 8) + (DM)*(D) )
 
 #define MAXF(a,b)            (((a) > (b)) ? (a) : (b))
@@ -223,8 +209,6 @@
 {
     int q;
     int i;
-    int *thresh;
-    int threshmult;
     double capped_q = (Qvalue < 160) ? (double)Qvalue : 160.0;
     double rdconst = 3.00;
 
@@ -271,22 +255,6 @@
     if (q < 8)
         q = 8;
 
-    if (cpi->ref_frame_flags == VP8_ALT_FLAG)
-    {
-        thresh      = &cpi->rd_threshes[THR_NEWA];
-        threshmult  = cpi->sf.thresh_mult[THR_NEWA];
-    }
-    else if (cpi->ref_frame_flags == VP8_GOLD_FLAG)
-    {
-        thresh      = &cpi->rd_threshes[THR_NEWG];
-        threshmult  = cpi->sf.thresh_mult[THR_NEWG];
-    }
-    else
-    {
-        thresh      = &cpi->rd_threshes[THR_NEWMV];
-        threshmult  = cpi->sf.thresh_mult[THR_NEWMV];
-    }
-
     if (cpi->RDMULT > 1000)
     {
         cpi->RDDIV = 1;
@@ -775,7 +743,7 @@
     *rate       = rd_cost_mbuv(x);
     *distortion = ENCODEMB_INVOKE(&cpi->rtcd.encodemb, mbuverr)(x) / 4;
 
-    return UVRDFUNC(x->rdmult, x->rddiv, *rate, *distortion, cpi->target_bits_per_mb);
+    return RDCOST(x->rdmult, x->rddiv, *rate, *distortion);
 }
 
 int vp8_rd_pick_intra_mbuv_mode(VP8_COMP *cpi, MACROBLOCK *x, int *rate, int *rate_tokenonly, int *distortion)
@@ -800,7 +768,7 @@
 
         distortion = vp8_get_mbuvrecon_error(IF_RTCD(&cpi->rtcd.variance), x);
 
-        this_rd = UVRDFUNC(x->rdmult, x->rddiv, rate, distortion, cpi->target_bits_per_mb);
+        this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);
 
         if (this_rd < best_rd)
         {
@@ -1097,7 +1065,7 @@
     // Segmentation method overheads
     rate = vp8_cost_token(vp8_mbsplit_tree, vp8_mbsplit_probs, vp8_mbsplit_encodings + segmentation);
     rate += vp8_cost_mv_ref(SPLITMV, bsi->mdcounts);
-    this_segment_rd += RDFUNC(x->rdmult, x->rddiv, rate, 0, cpi->target_bits_per_mb);
+    this_segment_rd += RDCOST(x->rdmult, x->rddiv, rate, 0);
     br += rate;
 
     for (i = 0; i < label_count; i++)
@@ -1252,7 +1220,7 @@
             labelyrate = rdcost_mbsegment_y(x, labels, i, ta_s, tl_s);
             rate += labelyrate;
 
-            this_rd = RDFUNC(x->rdmult, x->rddiv, rate, distortion, cpi->target_bits_per_mb);
+            this_rd = RDCOST(x->rdmult, x->rddiv, rate, distortion);
 
             if (this_rd < best_label_rd)
             {
@@ -1751,7 +1719,7 @@
     //int intermodecost[MAX_MODES];
 
     MB_PREDICTION_MODE uv_intra_mode;
-    int uvintra_eob = 0;
+
     int force_no_skip = 0;
 
     MV mvp;
@@ -1770,27 +1738,6 @@
 
     ref_frame_cost[INTRA_FRAME]   = vp8_cost_zero(cpi->prob_intra_coded);
 
-    // Experimental code
-    // Adjust the RD multiplier based on the best case distortion we saw in the most recently coded mb
-    //if ( (cpi->last_mb_distortion) > 0 && (cpi->target_bits_per_mb > 0) )
-    /*{
-        int tmprdmult;
-
-        //tmprdmult = (cpi->last_mb_distortion * 256) / ((cpi->av_per_frame_bandwidth*256)/cpi->common.MBs);
-        tmprdmult = (cpi->last_mb_distortion * 256) / cpi->target_bits_per_mb;
-        //tmprdmult = tmprdmult;
-
-        //if ( tmprdmult > cpi->RDMULT * 2 )
-        //  tmprdmult = cpi->RDMULT * 2;
-        //else if ( tmprdmult < cpi->RDMULT / 2 )
-        //  tmprdmult = cpi->RDMULT / 2;
-
-        //tmprdmult = (tmprdmult < 25) ? 25 : tmprdmult;
-
-        //x->rdmult = tmprdmult;
-
-    }*/
-
     // Special case treatment when GF and ARF are not sensible options for reference
     if (cpi->ref_frame_flags == VP8_LAST_FLAG)
     {
@@ -1820,13 +1767,7 @@
     x->e_mbd.mode_info_context->mbmi.ref_frame = INTRA_FRAME;
     vp8_rd_pick_intra_mbuv_mode(cpi, x, &uv_intra_rate, &uv_intra_rate_tokenonly, &uv_intra_distortion);
     uv_intra_mode = x->e_mbd.mode_info_context->mbmi.uv_mode;
-    {
-        uvintra_eob = 0;
 
-        for (i = 16; i < 24; i++)
-            uvintra_eob += x->e_mbd.block[i].eob;
-    }
-
     for (mode_index = 0; mode_index < MAX_MODES; mode_index++)
     {
         int this_rd = INT_MAX;
@@ -2339,8 +2280,8 @@
                             distortion_uv = sse2;
 
                             disable_skip = 1;
-                            this_rd = RDFUNC(x->rdmult, x->rddiv, rate2,
-                                             distortion2, cpi->target_bits_per_mb);
+                            this_rd = RDCOST(x->rdmult, x->rddiv, rate2,
+                                             distortion2);
 
                             break;
                         }
@@ -2414,7 +2355,7 @@
                 }
             }
             // Calculate the final RD estimate for this mode
-            this_rd = RDFUNC(x->rdmult, x->rddiv, rate2, distortion2, cpi->target_bits_per_mb);
+            this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
         }
 
         // Experimental debug code.
@@ -2442,8 +2383,8 @@
             other_cost += ref_frame_cost[x->e_mbd.mode_info_context->mbmi.ref_frame];
 
             /* Calculate the final y RD estimate for this mode */
-            best_yrd = RDFUNC(x->rdmult, x->rddiv, (rate2-rate_uv-other_cost),
-                              (distortion2-distortion_uv), cpi->target_bits_per_mb);
+            best_yrd = RDCOST(x->rdmult, x->rddiv, (rate2-rate_uv-other_cost),
+                              (distortion2-distortion_uv));
 
             *returnrate = rate2;
             *returndistortion = distortion2;
--- a/vp8/vp8_cx_iface.c
+++ b/vp8/vp8_cx_iface.c
@@ -39,6 +39,7 @@
     unsigned int                arnr_type;        /* alt_ref filter type */
     unsigned int                experimental;
     vp8e_tuning                 tuning;
+    unsigned int                cq_level;         /* constrained quality level */
 
 };
 
@@ -71,6 +72,7 @@
             3,                          /* arnr_type*/
             0,                          /* experimental mode */
             0,                          /* tuning*/
+            10,                         /* cq_level */
         }
     }
 };
@@ -150,7 +152,7 @@
 #else
     RANGE_CHECK_HI(cfg, g_lag_in_frames,    0);
 #endif
-    RANGE_CHECK(cfg, rc_end_usage,          VPX_VBR, VPX_CBR);
+    RANGE_CHECK(cfg, rc_end_usage,          VPX_VBR, VPX_CQ);
     RANGE_CHECK_HI(cfg, rc_undershoot_pct,  100);
     RANGE_CHECK_HI(cfg, rc_2pass_vbr_bias_pct, 100);
     RANGE_CHECK(cfg, kf_mode,               VPX_KF_DISABLED, VPX_KF_AUTO);
@@ -192,6 +194,7 @@
     RANGE_CHECK(vp8_cfg, arnr_max_frames, 0, 15);
     RANGE_CHECK_HI(vp8_cfg, arnr_strength,   6);
     RANGE_CHECK(vp8_cfg, arnr_type,       1, 3);
+    RANGE_CHECK(vp8_cfg, cq_level, 0, 63);
 
     if (cfg->g_pass == VPX_RC_LAST_PASS)
     {
@@ -301,6 +304,10 @@
     {
         oxcf->end_usage          = USAGE_STREAM_FROM_SERVER;
     }
+    else if (cfg.rc_end_usage == VPX_CQ)
+    {
+        oxcf->end_usage          = USAGE_CONSTRAINED_QUALITY;
+    }
 
     oxcf->target_bandwidth       = cfg.rc_target_bitrate;
 
@@ -342,6 +349,7 @@
     oxcf->arnr_type =      vp8_cfg.arnr_type;
 
     oxcf->tuning = vp8_cfg.tuning;
+    oxcf->cq_level = vp8_cfg.cq_level;
 
     /*
         printf("Current VP8 Settings: \n");
@@ -456,6 +464,7 @@
         MAP(VP8E_SET_ARNR_STRENGTH ,        xcfg.arnr_strength);
         MAP(VP8E_SET_ARNR_TYPE     ,        xcfg.arnr_type);
         MAP(VP8E_SET_TUNING,                xcfg.tuning);
+        MAP(VP8E_SET_CQ_LEVEL,              xcfg.cq_level);
 
     }
 
@@ -1056,6 +1065,7 @@
     {VP8E_SET_ARNR_STRENGTH ,           set_param},
     {VP8E_SET_ARNR_TYPE     ,           set_param},
     {VP8E_SET_TUNING,                   set_param},
+    {VP8E_SET_CQ_LEVEL,                 set_param},
     { -1, NULL},
 };
 
@@ -1091,7 +1101,6 @@
 
         4,                  /* rc_min_quantizer */
         63,                 /* rc_max_quantizer */
-
         95,                 /* rc_undershoot_pct */
         200,                /* rc_overshoot_pct */
 
--- a/vpx/vp8cx.h
+++ b/vpx/vp8cx.h
@@ -151,6 +151,7 @@
     VP8E_SET_ARNR_STRENGTH ,         /**< control function to set the filter strength for the arf */
     VP8E_SET_ARNR_TYPE     ,         /**< control function to set the type of filter to use for the arf*/
     VP8E_SET_TUNING,                 /**< control function to set visual tuning */
+    VP8E_SET_CQ_LEVEL,               /**< control function to set constrained quality level */
 };
 
 /*!\brief vpx 1-D scaling mode
@@ -277,6 +278,7 @@
 VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_STRENGTH ,     unsigned int)
 VPX_CTRL_USE_TYPE(VP8E_SET_ARNR_TYPE     ,     unsigned int)
 VPX_CTRL_USE_TYPE(VP8E_SET_TUNING,             vp8e_tuning)
+VPX_CTRL_USE_TYPE(VP8E_SET_CQ_LEVEL     ,      unsigned int)
 
 VPX_CTRL_USE_TYPE(VP8E_GET_LAST_QUANTIZER,     int *)
 VPX_CTRL_USE_TYPE(VP8E_GET_LAST_QUANTIZER_64,  int *)
--- a/vpx/vpx_encoder.h
+++ b/vpx/vpx_encoder.h
@@ -179,7 +179,8 @@
     enum vpx_rc_mode
     {
         VPX_VBR, /**< Variable Bit Rate (VBR) mode */
-        VPX_CBR  /**< Constant Bit Rate (CBR) mode */
+        VPX_CBR,  /**< Constant Bit Rate (CBR) mode */
+        VPX_CQ   /**< Constant Quality  (CQ)  mode */
     };
 
 
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -917,7 +917,7 @@
 static const arg_def_t resize_down_thresh = ARG_DEF(NULL, "resize-down", 1,
         "Downscale threshold (buf %)");
 static const arg_def_t end_usage          = ARG_DEF(NULL, "end-usage", 1,
-        "VBR=0 | CBR=1");
+        "VBR=0 | CBR=1 | CQ=2");
 static const arg_def_t target_bitrate     = ARG_DEF(NULL, "target-bitrate", 1,
         "Bitrate (kbps)");
 static const arg_def_t min_quantizer      = ARG_DEF(NULL, "min-q", 1,
@@ -1000,12 +1000,14 @@
 };
 static const arg_def_t tune_ssim = ARG_DEF_ENUM(NULL, "tune", 1,
                                    "Material to favor", tuning_enum);
+static const arg_def_t cq_level = ARG_DEF(NULL, "cq-level", 1,
+                                   "Constrained Quality Level");
 
 static const arg_def_t *vp8_args[] =
 {
     &cpu_used, &auto_altref, &noise_sens, &sharpness, &static_thresh,
     &token_parts, &arnr_maxframes, &arnr_strength, &arnr_type,
-    &tune_ssim, NULL
+    &tune_ssim, &cq_level, NULL
 };
 static const int vp8_arg_ctrl_map[] =
 {
@@ -1013,7 +1015,7 @@
     VP8E_SET_NOISE_SENSITIVITY, VP8E_SET_SHARPNESS, VP8E_SET_STATIC_THRESHOLD,
     VP8E_SET_TOKEN_PARTITIONS,
     VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH , VP8E_SET_ARNR_TYPE,
-    VP8E_SET_TUNING, 0
+    VP8E_SET_TUNING, VP8E_SET_CQ_LEVEL, 0
 };
 #endif