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(§ionstats);
- 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