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
This commit is contained in:
Родитель
483b262bab
Коммит
cf561bad1d
|
@ -3032,10 +3032,26 @@ static void find_next_key_frame(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
|
|||
|
||||
// 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)
|
||||
|
|
|
@ -477,12 +477,16 @@ void separate_arf_mbs
|
|||
//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);
|
||||
}
|
||||
|
||||
|
|
|
@ -492,6 +492,7 @@ static void init_seg_features(VP8_COMP *cpi)
|
|||
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 @@ static void init_seg_features(VP8_COMP *cpi)
|
|||
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 @@ static void init_seg_features(VP8_COMP *cpi)
|
|||
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 @@ static void init_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
|
|||
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 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf)
|
|||
{
|
||||
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 @@ void vp8_remove_compressor(VP8_PTR *ptr)
|
|||
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 @@ void vp8_remove_compressor(VP8_PTR *ptr)
|
|||
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 @@ static void encode_frame_to_data_rate
|
|||
// 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 @@ static void encode_frame_to_data_rate
|
|||
if ( cpi->active_worst_quality < cpi->active_best_quality )
|
||||
cpi->active_worst_quality = cpi->active_best_quality;
|
||||
|
||||
// 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,22 +4551,31 @@ static void encode_frame_to_data_rate
|
|||
&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_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 * low_err_target) / kf_err;
|
||||
if ( Q > ((q_high + q_low + 1) >> 1))
|
||||
Q = (q_high + q_low + 1) >> 1;
|
||||
}
|
||||
|
||||
|
@ -4569,14 +4602,12 @@ static void encode_frame_to_data_rate
|
|||
// 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 @@ static void encode_frame_to_data_rate
|
|||
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 @@ static void encode_frame_to_data_rate
|
|||
|
||||
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 @@ static void encode_frame_to_data_rate
|
|||
|
||||
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 @@ static void encode_frame_to_data_rate
|
|||
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,
|
||||
|
|
|
@ -383,6 +383,7 @@ typedef struct VP8_COMP
|
|||
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 @@ typedef struct VP8_COMP
|
|||
#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;
|
||||
|
|
|
@ -1271,30 +1271,18 @@ void vp8cx_frame_init_quantizer(VP8_COMP *cpi)
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 @@ void vp8_compute_frame_size_bounds(VP8_COMP *cpi, int *frame_under_shoot_limit,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче