ref: cf561bad1d027da0b28b4cd75036942e97d4fef7
parent: 483b262bab7cae4387dae4d07d126fb9915cc6c8
author: Paul Wilkins <paulwilkins@google.com>
date: Wed Jan 11 09:05:57 EST 2012
Rate control on static scenes plus Y2dc delta Q fix. A problem can arise on static clips with force key frames where attempts to avoid popping lead to a progressive reduction in key frame Q that ultimately may lead to unexpected overspend against the rate target. The changes in this patch help to insure that in such clips the quality of the key frames across the clip is more uniform (rather than starting bad and getting better - especially at low target rates). This patch also includes a fix that removes a delta on the Y2DC when the baseline q index < 4 as this is no longer needed. There is also a fix to try and prevent repeat single step Q adjustment in the recode loop leading to lots of recodes, especially where the use of forced skips as part of segmentation has made the impact of Q on the number of bits generated much smaller. Patch 2: Amend "last_boosted_qindex" calculation for arf overlay frames. Change-Id: Ia1feeb79ed8ed014e4239994fcf5e58e68fd9459
--- a/vp8/encoder/firstpass.c
+++ b/vp8/encoder/firstpass.c
@@ -3032,10 +3032,26 @@
// We do three calculations for kf size.
// The first is based on the error score for the whole kf group.
- // The second (optionaly) on the key frames own error if this is smaller than the average for the group.
- // The final one insures that the frame receives at least the allocation it would have received based on its own error score vs the error score remaining
-
- allocation_chunks = ((cpi->twopass.frames_to_key - 1) * 100) + kf_boost; // cpi->twopass.frames_to_key-1 because key frame itself is taken care of by kf_boost
+ // The second (optionaly) on the key frames own error if this is
+ // smaller than the average for the group.
+ // The final one insures that the frame receives at least the
+ // allocation it would have received based on its own error score vs
+ // the error score remaining
+ // Special case if the sequence appears almost totaly static
+ // as measured by the decay accumulator. In this case we want to
+ // spend almost all of the bits on the key frame.
+ // cpi->twopass.frames_to_key-1 because key frame itself is taken
+ // care of by kf_boost.
+ if ( decay_accumulator >= 0.99 )
+ {
+ allocation_chunks =
+ ((cpi->twopass.frames_to_key - 1) * 10) + kf_boost;
+ }
+ else
+ {
+ allocation_chunks =
+ ((cpi->twopass.frames_to_key - 1) * 100) + kf_boost;
+ }
// Normalize Altboost and allocations chunck down to prevent overflow
while (kf_boost > 1000)
--- a/vp8/encoder/mbgraph.c
+++ b/vp8/encoder/mbgraph.c
@@ -477,12 +477,16 @@
//if ( ncnt[1] && (ncnt[0] / ncnt[1] < 10) )
if ( 1 )
{
- cpi->mbgraph_use_arf_segmentation = ncnt[1];
+ // Note % of blocks that are marked as static
+ cpi->static_mb_pct =
+ (ncnt[1] * 100) / cm->MBs;
+
vp8_enable_segmentation((VP8_PTR) cpi);
}
else
{
- cpi->mbgraph_use_arf_segmentation = 0;
+ cpi->static_mb_pct = 0;
+
vp8_disable_segmentation((VP8_PTR) cpi);
}
--- a/vp8/encoder/onyx_if.c
+++ b/vp8/encoder/onyx_if.c
@@ -492,6 +492,7 @@
vpx_memset( cpi->segmentation_map, 0, (cm->mb_rows * cm->mb_cols));
xd->update_mb_segmentation_map = 0;
xd->update_mb_segmentation_data = 0;
+ cpi->static_mb_pct = 0;
// Disable segmentation
vp8_disable_segmentation((VP8_PTR)cpi);
@@ -507,6 +508,7 @@
vpx_memset( cpi->segmentation_map, 0, (cm->mb_rows * cm->mb_cols));
xd->update_mb_segmentation_map = 0;
xd->update_mb_segmentation_data = 0;
+ cpi->static_mb_pct = 0;
// Disable segmentation and individual segment features by default
vp8_disable_segmentation((VP8_PTR)cpi);
@@ -557,7 +559,7 @@
set_segdata( xd, 1, SEG_LVL_ALT_LF, -2 );
enable_segfeature(xd, 1, SEG_LVL_ALT_LF);
- if ( high_q )
+ if ( high_q || (cpi->static_mb_pct == 100) )
{
set_segref(xd, 1, ALTREF_FRAME);
enable_segfeature(xd, 1, SEG_LVL_REF_FRAME);
@@ -1973,6 +1975,8 @@
cpi->total_actual_bits = 0;
cpi->total_target_vs_actual = 0;
+ cpi->static_mb_pct = 0;
+
#if VP8_TEMPORAL_ALT_REF
{
int i;
@@ -2233,6 +2237,7 @@
{
cpi->last_q[0] = cpi->oxcf.fixed_q;
cpi->last_q[1] = cpi->oxcf.fixed_q;
+ cpi->last_boosted_qindex = cpi->oxcf.fixed_q;
}
cpi->Speed = cpi->oxcf.cpu_used;
@@ -2694,6 +2699,9 @@
fprintf(f, "%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t%8.0f\n",
dr, cpi->total / cpi->count, total_psnr, cpi->totalp / cpi->count, total_psnr2, total_ssim,
total_encode_time);
+// fprintf(f, "%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t%7.3f\t%8.0f %10ld\n",
+// dr, cpi->total / cpi->count, total_psnr, cpi->totalp / cpi->count, total_psnr2, total_ssim,
+// total_encode_time, cpi->tot_recode_hits);
}
if (cpi->b_calculate_ssimg)
@@ -2702,6 +2710,9 @@
fprintf(f, "%7.3f\t%6.4f\t%6.4f\t%6.4f\t%6.4f\t%8.0f\n", dr,
cpi->total_ssimg_y / cpi->count, cpi->total_ssimg_u / cpi->count,
cpi->total_ssimg_v / cpi->count, cpi->total_ssimg_all / cpi->count, total_encode_time);
+// fprintf(f, "%7.3f\t%6.4f\t%6.4f\t%6.4f\t%6.4f\t%8.0f %10ld\n", dr,
+// cpi->total_ssimg_y / cpi->count, cpi->total_ssimg_u / cpi->count,
+// cpi->total_ssimg_v / cpi->count, cpi->total_ssimg_all / cpi->count, total_encode_time, cpi->tot_recode_hits);
}
fclose(f);
@@ -4134,10 +4145,15 @@
// 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;
+ int delta_qindex;
+ int qindex = cpi->last_boosted_qindex;
+
+ delta_qindex = compute_qdelta( cpi, qindex,
+ (qindex * 0.75) );
+
+ cpi->active_best_quality = qindex + delta_qindex;
+ if (cpi->active_best_quality < cpi->best_quality)
+ cpi->active_best_quality = cpi->best_quality;
}
}
// One pass more conservative
@@ -4248,8 +4264,16 @@
if ( cpi->active_worst_quality < cpi->active_best_quality )
cpi->active_worst_quality = cpi->active_best_quality;
- // Determine initial Q to try
- Q = vp8_regulate_q(cpi, cpi->this_frame_target);
+ // Specuial case code to try and match quality with forced key frames
+ if ( (cm->frame_type == KEY_FRAME) && cpi->this_key_frame_forced )
+ {
+ Q = cpi->last_boosted_qindex;
+ }
+ else
+ {
+ // Determine initial Q to try
+ Q = vp8_regulate_q(cpi, cpi->this_frame_target);
+ }
last_zbin_oq = cpi->zbin_over_quant;
// Set highest allowed value for Zbin over quant
@@ -4527,23 +4551,32 @@
&cm->yv12_fb[cm->new_fb_idx],
IF_RTCD(&cpi->rtcd.variance));
+ int high_err_target = cpi->ambient_err;
+ int low_err_target = ((cpi->ambient_err * 3) >> 2);
+
// The key frame is not good enough
- if ( kf_err > ((cpi->ambient_err * 7) >> 3) )
+ if ( (kf_err > high_err_target) &&
+ (cpi->projected_frame_size <= frame_over_shoot_limit) )
{
// Lower q_high
q_high = (Q > q_low) ? (Q - 1) : q_low;
// Adjust Q
- Q = (q_high + q_low) >> 1;
+ Q = (Q * high_err_target) / kf_err;
+ if ( Q < ((q_high + q_low) >> 1))
+ Q = (q_high + q_low) >> 1;
}
// The key frame is much better than the previous frame
- else if ( kf_err < (cpi->ambient_err >> 1) )
+ else if ( (kf_err < low_err_target) &&
+ (cpi->projected_frame_size >= frame_under_shoot_limit) )
{
// Raise q_low
q_low = (Q < q_high) ? (Q + 1) : q_high;
// Adjust Q
- Q = (q_high + q_low + 1) >> 1;
+ Q = (Q * low_err_target) / kf_err;
+ if ( Q > ((q_high + q_low + 1) >> 1))
+ Q = (q_high + q_low + 1) >> 1;
}
// Clamp Q to upper and lower limits:
@@ -4569,14 +4602,12 @@
// Frame is too large
if (cpi->projected_frame_size > cpi->this_frame_target)
{
- //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
zbin_oq_low = (cpi->zbin_over_quant < zbin_oq_high) ? (cpi->zbin_over_quant + 1) : zbin_oq_high;
- //if ( undershoot_seen || (Q == MAXQ) )
- if (undershoot_seen)
+ if ( undershoot_seen || (loop_count > 1) )
{
// Update rate_correction_factor unless cpi->active_worst_quality has changed.
if (!active_worst_qchanged)
@@ -4619,7 +4650,7 @@
else // else lower zbin_oq_high
zbin_oq_high = (cpi->zbin_over_quant > zbin_oq_low) ? (cpi->zbin_over_quant - 1) : zbin_oq_low;
- if (overshoot_seen)
+ if ( overshoot_seen || (loop_count > 1) )
{
// Update rate_correction_factor unless cpi->active_worst_quality has changed.
if (!active_worst_qchanged)
@@ -4845,6 +4876,20 @@
cpi->last_q[cm->frame_type] = cm->base_qindex;
+ // 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.
+ // If all mbs in this group are skipped only update if the Q value is
+ // better than that already stored.
+ // This is used to help set quality in forced key frames to reduce popping
+ if ( (cm->base_qindex < cpi->last_boosted_qindex) ||
+ ( (cpi->static_mb_pct < 100) &&
+ ( (cm->frame_type == KEY_FRAME) ||
+ cm->refresh_alt_ref_frame ||
+ (cm->refresh_golden_frame && !cpi->is_src_frame_alt_ref) ) ) )
+ {
+ cpi->last_boosted_qindex = cm->base_qindex;
+ }
+
if (cm->frame_type == KEY_FRAME)
{
vp8_adjust_key_frame_context(cpi);
@@ -4991,7 +5036,7 @@
if (cpi->twopass.total_left_stats->coded_error != 0.0)
fprintf(f, "%10d %10d %10d %10d %10d %10d %10d"
- "%6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f"
+ "%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f"
"%6d %5d %5d %5d %8d %8.2f %10d %10.3f"
"%10.3f %8d\n",
cpi->common.current_video_frame, cpi->this_frame_target,
@@ -5023,7 +5068,7 @@
cpi->tot_recode_hits);
else
fprintf(f, "%10d %10d %10d %10d %10d %10d %10d"
- "%6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f"
+ "%7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f"
"%6d %5d %5d %5d %8d %8.2f %10d %10.3f"
"%8d\n",
cpi->common.current_video_frame,
--- a/vp8/encoder/onyx_int.h
+++ b/vp8/encoder/onyx_int.h
@@ -383,6 +383,7 @@
int this_frame_target;
int projected_frame_size;
int last_q[2]; // Separate values for Intra/Inter
+ int last_boosted_qindex; // Last boosted GF/KF/ARF q
double rate_correction_factor;
double key_frame_rate_correction_factor;
@@ -483,11 +484,7 @@
#endif
MBGRAPH_FRAME_STATS mbgraph_stats[MAX_LAG_BUFFERS];
int mbgraph_n_frames; // number of frames filled in the above
- int mbgraph_use_arf_segmentation; // set if part of an ARF is considered to be a
- // poor predictor, and thus coeffs are skipped
- // or coded at a higher Q using MB-segmentation
- // this value is the number of MBs that are
- // poor predictors (> 0 and < common.MBs)
+ int static_mb_pct; // % forced skip mbs by segmentation
int decimation_factor;
int decimation_count;
--- a/vp8/encoder/quantize.c
+++ b/vp8/encoder/quantize.c
@@ -1271,30 +1271,18 @@
void vp8_set_quantizer(struct VP8_COMP *cpi, int Q)
{
VP8_COMMON *cm = &cpi->common;
- int update = 0;
- int new_delta_q;
- cm->base_qindex = Q;
- /* if any of the delta_q values are changing update flag has to be set */
- /* currently only y2dc_delta_q may change */
-
+ // if any of the delta_q values are changing update flag will
+ // have to be set.
cm->y1dc_delta_q = 0;
cm->y2ac_delta_q = 0;
cm->uvdc_delta_q = 0;
cm->uvac_delta_q = 0;
+ cm->y2dc_delta_q = 0;
- if (Q < 4)
- {
- new_delta_q = 4-Q;
- }
- else
- new_delta_q = 0;
-
- update |= cm->y2dc_delta_q != new_delta_q;
- cm->y2dc_delta_q = new_delta_q;
-
- /* quantizer has to be reinitialized for any delta_q changes */
- if(update)
- vp8cx_init_quantizer(cpi);
+ // quantizer has to be reinitialized if any delta_q changes.
+ // As there are not any here for now this is inactive code.
+ //if(update)
+ // vp8cx_init_quantizer(cpi);
}
--- a/vp8/encoder/ratectrl.c
+++ b/vp8/encoder/ratectrl.c
@@ -24,7 +24,7 @@
#include "encodemv.h"
-#define MIN_BPB_FACTOR 0.01
+#define MIN_BPB_FACTOR 0.005
#define MAX_BPB_FACTOR 50
extern const MB_PREDICTION_MODE vp8_mode_order[MAX_MODES];
@@ -1477,6 +1477,14 @@
}
}
}
+
+ // For very small rate targets where the fractional adjustment
+ // (eg * 7/8) may be tiny make sure there is at least a minimum
+ // range.
+ *frame_over_shoot_limit += 200;
+ *frame_under_shoot_limit -= 200;
+ if ( *frame_under_shoot_limit < 0 )
+ *frame_under_shoot_limit = 0;
}
}
--
⑨