Auto-adaptive encoder frame resizing logic
Note: This feature is still in development. Add an option for the encoder to decide the resolution at which to encode each frame. Each KF/GF/ARF goup is tested to see if it would be better encoded at a lower resolution. At present, each KF/GF/ARF is coded first at full-size and if the coded size exceeds a threshold (twice target data rate) at the maximum active Q then the entire group is encoded at lower resolution. This feature is enabled in vpxenc by setting: --resize-allowed=1 In addition, if the vpxenc command line also specifies valid frame dimensions using: --resize-width=XXXX & --resize_height=YYYY then *all* frames will be encoded at this resolution. Change-Id: I13f341e0a82512f9e84e144e0f3b5aed8a65402b
This commit is contained in:
Родитель
84b813aa42
Коммит
23ebacdb81
|
@ -2307,26 +2307,43 @@ static void scale_and_extend_frame(const YV12_BUFFER_CONFIG *src,
|
|||
vp9_extend_frame_borders(dst);
|
||||
}
|
||||
|
||||
static int scale_down(VP9_COMP *cpi, int q) {
|
||||
RATE_CONTROL *const rc = &cpi->rc;
|
||||
GF_GROUP *const gf_group = &cpi->twopass.gf_group;
|
||||
int scale = 0;
|
||||
assert(frame_is_kf_gf_arf(cpi));
|
||||
|
||||
if (rc->frame_size_selector == UNSCALED &&
|
||||
q >= rc->rf_level_maxq[gf_group->rf_level[gf_group->index]]) {
|
||||
const int max_size_thresh = (int)(rate_thresh_mult[SCALE_STEP1]
|
||||
* MAX(rc->this_frame_target, rc->avg_frame_bandwidth));
|
||||
scale = rc->projected_frame_size > max_size_thresh ? 1 : 0;
|
||||
}
|
||||
return scale;
|
||||
}
|
||||
|
||||
// Function to test for conditions that indicate we should loop
|
||||
// back and recode a frame.
|
||||
static int recode_loop_test(const VP9_COMP *cpi,
|
||||
static int recode_loop_test(VP9_COMP *cpi,
|
||||
int high_limit, int low_limit,
|
||||
int q, int maxq, int minq) {
|
||||
const RATE_CONTROL *const rc = &cpi->rc;
|
||||
const VP9EncoderConfig *const oxcf = &cpi->oxcf;
|
||||
const int frame_is_kfgfarf = frame_is_kf_gf_arf(cpi);
|
||||
int force_recode = 0;
|
||||
|
||||
// Special case trap if maximum allowed frame size exceeded.
|
||||
if (rc->projected_frame_size > rc->max_frame_bandwidth) {
|
||||
force_recode = 1;
|
||||
if ((cpi->sf.recode_loop == ALLOW_RECODE) ||
|
||||
(frame_is_kfgfarf &&
|
||||
(cpi->sf.recode_loop == ALLOW_RECODE_KFARFGF))) {
|
||||
if (frame_is_kfgfarf &&
|
||||
(oxcf->resize_mode == RESIZE_DYNAMIC) &&
|
||||
scale_down(cpi, q)) {
|
||||
// Code this group at a lower resolution.
|
||||
cpi->resize_pending = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Is frame recode allowed.
|
||||
// Yes if either recode mode 1 is selected or mode 2 is selected
|
||||
// and the frame is a key frame, golden frame or alt_ref_frame
|
||||
} else if ((cpi->sf.recode_loop == ALLOW_RECODE) ||
|
||||
((cpi->sf.recode_loop == ALLOW_RECODE_KFARFGF) &&
|
||||
frame_is_kf_gf_arf(cpi))) {
|
||||
// General over and under shoot tests
|
||||
// TODO(agrange) high_limit could be greater than the scale-down threshold.
|
||||
if ((rc->projected_frame_size > high_limit && q < maxq) ||
|
||||
(rc->projected_frame_size < low_limit && q > minq)) {
|
||||
force_recode = 1;
|
||||
|
@ -2557,13 +2574,15 @@ static void output_frame_level_debug_stats(VP9_COMP *cpi) {
|
|||
recon_err = vp9_get_y_sse(cpi->Source, get_frame_new_buffer(cm));
|
||||
|
||||
if (cpi->twopass.total_left_stats.coded_error != 0.0)
|
||||
fprintf(f, "%10u %10d %10d %10d %10d"
|
||||
fprintf(f, "%10u %dx%d %10d %10d %10d %10d"
|
||||
"%10"PRId64" %10"PRId64" %10"PRId64" %10"PRId64" %10d "
|
||||
"%7.2lf %7.2lf %7.2lf %7.2lf %7.2lf"
|
||||
"%6d %6d %5d %5d %5d "
|
||||
"%10"PRId64" %10.3lf"
|
||||
"%10lf %8u %10"PRId64" %10d %10d\n",
|
||||
cpi->common.current_video_frame, cpi->rc.this_frame_target,
|
||||
cpi->common.current_video_frame,
|
||||
cm->width, cm->height,
|
||||
cpi->rc.this_frame_target,
|
||||
cpi->rc.projected_frame_size,
|
||||
cpi->rc.projected_frame_size / cpi->common.MBs,
|
||||
(cpi->rc.projected_frame_size - cpi->rc.this_frame_target),
|
||||
|
@ -2699,14 +2718,17 @@ static void init_motion_estimation(VP9_COMP *cpi) {
|
|||
void set_frame_size(VP9_COMP *cpi) {
|
||||
int ref_frame;
|
||||
VP9_COMMON *const cm = &cpi->common;
|
||||
const VP9EncoderConfig *const oxcf = &cpi->oxcf;
|
||||
VP9EncoderConfig *const oxcf = &cpi->oxcf;
|
||||
MACROBLOCKD *const xd = &cpi->td.mb.e_mbd;
|
||||
|
||||
if (oxcf->pass == 2 &&
|
||||
cm->current_video_frame == 0 &&
|
||||
oxcf->resize_mode == RESIZE_FIXED &&
|
||||
oxcf->rc_mode == VPX_VBR) {
|
||||
// Internal scaling is triggered on the first frame.
|
||||
oxcf->rc_mode == VPX_VBR &&
|
||||
((oxcf->resize_mode == RESIZE_FIXED && cm->current_video_frame == 0) ||
|
||||
(oxcf->resize_mode == RESIZE_DYNAMIC && cpi->resize_pending))) {
|
||||
calculate_coded_size(
|
||||
cpi, &oxcf->scaled_frame_width, &oxcf->scaled_frame_height);
|
||||
|
||||
// There has been a change in frame size.
|
||||
vp9_set_size_literal(cpi, oxcf->scaled_frame_width,
|
||||
oxcf->scaled_frame_height);
|
||||
}
|
||||
|
@ -2757,7 +2779,7 @@ void set_frame_size(VP9_COMP *cpi) {
|
|||
|
||||
static void encode_without_recode_loop(VP9_COMP *cpi) {
|
||||
VP9_COMMON *const cm = &cpi->common;
|
||||
int q, bottom_index, top_index; // Dummy variables.
|
||||
int q = 0, bottom_index = 0, top_index = 0; // Dummy variables.
|
||||
|
||||
vp9_clear_system_state();
|
||||
|
||||
|
@ -2804,13 +2826,13 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
|
|||
RATE_CONTROL *const rc = &cpi->rc;
|
||||
int bottom_index, top_index;
|
||||
int loop_count = 0;
|
||||
int loop_at_this_size = 0;
|
||||
int loop = 0;
|
||||
int overshoot_seen = 0;
|
||||
int undershoot_seen = 0;
|
||||
int frame_over_shoot_limit;
|
||||
int frame_under_shoot_limit;
|
||||
int q = 0, q_low = 0, q_high = 0;
|
||||
int frame_size_changed = 0;
|
||||
|
||||
set_size_independent_vars(cpi);
|
||||
|
||||
|
@ -2819,19 +2841,31 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
|
|||
|
||||
set_frame_size(cpi);
|
||||
|
||||
if (loop_count == 0 || frame_size_changed != 0) {
|
||||
if (loop_count == 0 || cpi->resize_pending != 0) {
|
||||
set_size_dependent_vars(cpi, &q, &bottom_index, &top_index);
|
||||
q_low = bottom_index;
|
||||
q_high = top_index;
|
||||
|
||||
// TODO(agrange) Scale cpi->max_mv_magnitude if frame-size has changed.
|
||||
set_mv_search_params(cpi);
|
||||
|
||||
// Reset the loop state for new frame size.
|
||||
overshoot_seen = 0;
|
||||
undershoot_seen = 0;
|
||||
|
||||
// Reconfiguration for change in frame size has concluded.
|
||||
cpi->resize_pending = 0;
|
||||
|
||||
q_low = bottom_index;
|
||||
q_high = top_index;
|
||||
|
||||
loop_at_this_size = 0;
|
||||
}
|
||||
|
||||
// Decide frame size bounds
|
||||
vp9_rc_compute_frame_size_bounds(cpi, rc->this_frame_target,
|
||||
&frame_under_shoot_limit,
|
||||
&frame_over_shoot_limit);
|
||||
// Decide frame size bounds first time through.
|
||||
if (loop_count == 0) {
|
||||
vp9_rc_compute_frame_size_bounds(cpi, rc->this_frame_target,
|
||||
&frame_under_shoot_limit,
|
||||
&frame_over_shoot_limit);
|
||||
}
|
||||
|
||||
cpi->Source = vp9_scale_if_required(cm, cpi->un_scaled_source,
|
||||
&cpi->scaled_source);
|
||||
|
@ -2944,6 +2978,20 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
|
|||
int last_q = q;
|
||||
int retries = 0;
|
||||
|
||||
if (cpi->resize_pending == 1) {
|
||||
// Change in frame size so go back around the recode loop.
|
||||
cpi->rc.frame_size_selector =
|
||||
SCALE_STEP1 - cpi->rc.frame_size_selector;
|
||||
cpi->rc.next_frame_size_selector = cpi->rc.frame_size_selector;
|
||||
|
||||
#if CONFIG_INTERNAL_STATS
|
||||
++cpi->tot_recode_hits;
|
||||
#endif
|
||||
++loop_count;
|
||||
loop = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Frame size out of permitted range:
|
||||
// Update correction factor & compute new Q to try...
|
||||
|
||||
|
@ -2956,7 +3004,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
|
|||
// Raise Qlow as to at least the current value
|
||||
q_low = q < q_high ? q + 1 : q_high;
|
||||
|
||||
if (undershoot_seen || loop_count > 1) {
|
||||
if (undershoot_seen || loop_at_this_size > 1) {
|
||||
// Update rate_correction_factor unless
|
||||
vp9_rc_update_rate_correction_factors(cpi);
|
||||
|
||||
|
@ -2981,7 +3029,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
|
|||
// Frame is too small
|
||||
q_high = q > q_low ? q - 1 : q_low;
|
||||
|
||||
if (overshoot_seen || loop_count > 1) {
|
||||
if (overshoot_seen || loop_at_this_size > 1) {
|
||||
vp9_rc_update_rate_correction_factors(cpi);
|
||||
q = (q_high + q_low) / 2;
|
||||
} else {
|
||||
|
@ -3011,7 +3059,7 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
|
|||
// Clamp Q to upper and lower limits:
|
||||
q = clamp(q, q_low, q_high);
|
||||
|
||||
loop = q != last_q;
|
||||
loop = (q != last_q);
|
||||
} else {
|
||||
loop = 0;
|
||||
}
|
||||
|
@ -3023,10 +3071,11 @@ static void encode_with_recode_loop(VP9_COMP *cpi,
|
|||
loop = 0;
|
||||
|
||||
if (loop) {
|
||||
loop_count++;
|
||||
++loop_count;
|
||||
++loop_at_this_size;
|
||||
|
||||
#if CONFIG_INTERNAL_STATS
|
||||
cpi->tot_recode_hits++;
|
||||
++cpi->tot_recode_hits;
|
||||
#endif
|
||||
}
|
||||
} while (loop);
|
||||
|
|
|
@ -448,6 +448,8 @@ typedef struct VP9_COMP {
|
|||
VP9_DENOISER denoiser;
|
||||
#endif
|
||||
|
||||
int resize_pending;
|
||||
|
||||
// Multi-threading
|
||||
int num_workers;
|
||||
VP9Worker *workers;
|
||||
|
@ -593,6 +595,8 @@ static INLINE int *cond_cost_list(const struct VP9_COMP *cpi, int *cost_list) {
|
|||
return cpi->sf.mv.subpel_search_method != SUBPEL_TREE ? cost_list : NULL;
|
||||
}
|
||||
|
||||
void vp9_new_framerate(VP9_COMP *cpi, double framerate);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
@ -1134,7 +1134,38 @@ static int get_twopass_worst_quality(const VP9_COMP *cpi,
|
|||
}
|
||||
}
|
||||
|
||||
extern void vp9_new_framerate(VP9_COMP *cpi, double framerate);
|
||||
static void setup_rf_level_maxq(VP9_COMP *cpi) {
|
||||
int i;
|
||||
RATE_CONTROL *const rc = &cpi->rc;
|
||||
for (i = INTER_NORMAL; i < RATE_FACTOR_LEVELS; ++i) {
|
||||
int qdelta = vp9_frame_type_qdelta(cpi, i, rc->worst_quality);
|
||||
rc->rf_level_maxq[i] = MAX(rc->worst_quality + qdelta, rc->best_quality);
|
||||
}
|
||||
}
|
||||
|
||||
void vp9_init_subsampling(VP9_COMP *cpi) {
|
||||
const VP9_COMMON *const cm = &cpi->common;
|
||||
RATE_CONTROL *const rc = &cpi->rc;
|
||||
const int w = cm->width;
|
||||
const int h = cm->height;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < FRAME_SCALE_STEPS; ++i) {
|
||||
// Note: Frames with odd-sized dimensions may result from this scaling.
|
||||
rc->frame_width[i] = (w * 16) / frame_scale_factor[i];
|
||||
rc->frame_height[i] = (h * 16) / frame_scale_factor[i];
|
||||
}
|
||||
|
||||
setup_rf_level_maxq(cpi);
|
||||
}
|
||||
|
||||
void calculate_coded_size(VP9_COMP *cpi,
|
||||
int *scaled_frame_width,
|
||||
int *scaled_frame_height) {
|
||||
RATE_CONTROL *const rc = &cpi->rc;
|
||||
*scaled_frame_width = rc->frame_width[rc->frame_size_selector];
|
||||
*scaled_frame_height = rc->frame_height[rc->frame_size_selector];
|
||||
}
|
||||
|
||||
void vp9_init_second_pass(VP9_COMP *cpi) {
|
||||
SVC *const svc = &cpi->svc;
|
||||
|
@ -1204,6 +1235,10 @@ void vp9_init_second_pass(VP9_COMP *cpi) {
|
|||
// Static sequence monitor variables.
|
||||
twopass->kf_zeromotion_pct = 100;
|
||||
twopass->last_kfgroup_zeromotion_pct = 100;
|
||||
|
||||
if (oxcf->resize_mode != RESIZE_NONE) {
|
||||
vp9_init_subsampling(cpi);
|
||||
}
|
||||
}
|
||||
|
||||
#define SR_DIFF_PART 0.0015
|
||||
|
@ -1696,8 +1731,9 @@ static void allocate_gf_group_bits(VP9_COMP *cpi, int64_t gf_group_bits,
|
|||
|
||||
// Analyse and define a gf/arf group.
|
||||
static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
|
||||
VP9_COMMON *const cm = &cpi->common;
|
||||
RATE_CONTROL *const rc = &cpi->rc;
|
||||
const VP9EncoderConfig *const oxcf = &cpi->oxcf;
|
||||
VP9EncoderConfig *const oxcf = &cpi->oxcf;
|
||||
TWO_PASS *const twopass = &cpi->twopass;
|
||||
FIRSTPASS_STATS next_frame;
|
||||
const FIRSTPASS_STATS *const start_pos = twopass->stats_in;
|
||||
|
@ -1733,10 +1769,11 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
|
|||
int64_t gf_group_bits;
|
||||
double gf_group_error_left;
|
||||
int gf_arf_bits;
|
||||
int is_key_frame = frame_is_intra_only(cm);
|
||||
|
||||
// Reset the GF group data structures unless this is a key
|
||||
// frame in which case it will already have been done.
|
||||
if (cpi->common.frame_type != KEY_FRAME) {
|
||||
if (is_key_frame == 0) {
|
||||
vp9_zero(twopass->gf_group);
|
||||
}
|
||||
|
||||
|
@ -1752,7 +1789,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
|
|||
|
||||
// If this is a key frame or the overlay from a previous arf then
|
||||
// the error score / cost of this frame has already been accounted for.
|
||||
if (cpi->common.frame_type == KEY_FRAME || rc->source_alt_ref_active) {
|
||||
if (is_key_frame || rc->source_alt_ref_active) {
|
||||
gf_group_err -= gf_first_frame_err;
|
||||
#if GROUP_ADAPTIVE_MAXQ
|
||||
gf_group_raw_error -= this_frame->coded_error;
|
||||
|
@ -1864,7 +1901,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
|
|||
rc->constrained_gf_group = (i >= rc->frames_to_key) ? 1 : 0;
|
||||
|
||||
// Set the interval until the next gf.
|
||||
if (cpi->common.frame_type == KEY_FRAME || rc->source_alt_ref_active)
|
||||
if (is_key_frame || rc->source_alt_ref_active)
|
||||
rc->baseline_gf_interval = i - 1;
|
||||
else
|
||||
rc->baseline_gf_interval = i;
|
||||
|
@ -1927,9 +1964,9 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
|
|||
get_twopass_worst_quality(cpi, group_av_err, vbr_group_bits_per_frame,
|
||||
twopass->kfgroup_inter_fraction);
|
||||
|
||||
if (tmp_q < twopass->baseline_worst_quality) {
|
||||
if (tmp_q < twopass->baseline_active_worst_quality) {
|
||||
twopass->active_worst_quality =
|
||||
(tmp_q + twopass->baseline_worst_quality + 1) / 2;
|
||||
(tmp_q + twopass->baseline_active_worst_quality + 1) / 2;
|
||||
} else {
|
||||
twopass->active_worst_quality = tmp_q;
|
||||
}
|
||||
|
@ -1951,7 +1988,7 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
|
|||
// also a key frame in which case it has already been accounted for.
|
||||
if (rc->source_alt_ref_pending) {
|
||||
gf_group_error_left = gf_group_err - mod_frame_err;
|
||||
} else if (cpi->common.frame_type != KEY_FRAME) {
|
||||
} else if (is_key_frame == 0) {
|
||||
gf_group_error_left = gf_group_err - gf_first_frame_err;
|
||||
} else {
|
||||
gf_group_error_left = gf_group_err;
|
||||
|
@ -1969,6 +2006,11 @@ static void define_gf_group(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
|
|||
calculate_section_intra_ratio(start_pos, twopass->stats_in_end,
|
||||
rc->baseline_gf_interval);
|
||||
}
|
||||
|
||||
if (oxcf->resize_mode == RESIZE_DYNAMIC) {
|
||||
// Default to starting GF groups at normal frame size.
|
||||
cpi->rc.next_frame_size_selector = UNSCALED;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(PGW) Re-examine the use of II ration in this code in the light of#
|
||||
|
@ -2293,6 +2335,11 @@ static void find_next_key_frame(VP9_COMP *cpi, FIRSTPASS_STATS *this_frame) {
|
|||
// The count of bits left is adjusted elsewhere based on real coded frame
|
||||
// sizes.
|
||||
twopass->modified_error_left -= kf_group_err;
|
||||
|
||||
if (oxcf->resize_mode == RESIZE_DYNAMIC) {
|
||||
// Default to normal-sized frame on keyframes.
|
||||
cpi->rc.next_frame_size_selector = UNSCALED;
|
||||
}
|
||||
}
|
||||
|
||||
// Define the reference buffers that will be updated post encode.
|
||||
|
@ -2433,7 +2480,7 @@ void vp9_rc_get_second_pass_params(VP9_COMP *cpi) {
|
|||
section_target_bandwidth, DEFAULT_GRP_WEIGHT);
|
||||
|
||||
twopass->active_worst_quality = tmp_q;
|
||||
twopass->baseline_worst_quality = tmp_q;
|
||||
twopass->baseline_active_worst_quality = tmp_q;
|
||||
rc->ni_av_qi = tmp_q;
|
||||
rc->last_q[INTER_FRAME] = tmp_q;
|
||||
rc->avg_q = vp9_convert_qindex_to_q(tmp_q, cm->bit_depth);
|
||||
|
|
|
@ -118,8 +118,8 @@ typedef struct {
|
|||
int kf_zeromotion_pct;
|
||||
int last_kfgroup_zeromotion_pct;
|
||||
int gf_zeromotion_pct;
|
||||
int baseline_worst_quality;
|
||||
int active_worst_quality;
|
||||
int baseline_active_worst_quality;
|
||||
int extend_minq;
|
||||
int extend_maxq;
|
||||
|
||||
|
@ -138,6 +138,13 @@ void vp9_rc_get_second_pass_params(struct VP9_COMP *cpi);
|
|||
|
||||
// Post encode update of the rate control parameters for 2-pass
|
||||
void vp9_twopass_postencode_update(struct VP9_COMP *cpi);
|
||||
|
||||
void vp9_init_subsampling(struct VP9_COMP *cpi);
|
||||
|
||||
void calculate_coded_size(struct VP9_COMP *cpi,
|
||||
int *scaled_frame_width,
|
||||
int *scaled_frame_height);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
@ -360,26 +360,32 @@ int vp9_rc_drop_frame(VP9_COMP *cpi) {
|
|||
|
||||
static double get_rate_correction_factor(const VP9_COMP *cpi) {
|
||||
const RATE_CONTROL *const rc = &cpi->rc;
|
||||
double rcf;
|
||||
|
||||
if (cpi->common.frame_type == KEY_FRAME) {
|
||||
return rc->rate_correction_factors[KF_STD];
|
||||
rcf = rc->rate_correction_factors[KF_STD];
|
||||
} else if (cpi->oxcf.pass == 2) {
|
||||
RATE_FACTOR_LEVEL rf_lvl =
|
||||
cpi->twopass.gf_group.rf_level[cpi->twopass.gf_group.index];
|
||||
return rc->rate_correction_factors[rf_lvl];
|
||||
rcf = rc->rate_correction_factors[rf_lvl];
|
||||
} else {
|
||||
if ((cpi->refresh_alt_ref_frame || cpi->refresh_golden_frame) &&
|
||||
!rc->is_src_frame_alt_ref && !cpi->use_svc &&
|
||||
(cpi->oxcf.rc_mode != VPX_CBR || cpi->oxcf.gf_cbr_boost_pct > 20))
|
||||
return rc->rate_correction_factors[GF_ARF_STD];
|
||||
rcf = rc->rate_correction_factors[GF_ARF_STD];
|
||||
else
|
||||
return rc->rate_correction_factors[INTER_NORMAL];
|
||||
rcf = rc->rate_correction_factors[INTER_NORMAL];
|
||||
}
|
||||
rcf *= rcf_mult[rc->frame_size_selector];
|
||||
return rcf > MAX_BPB_FACTOR ? MAX_BPB_FACTOR : rcf;
|
||||
}
|
||||
|
||||
static void set_rate_correction_factor(VP9_COMP *cpi, double factor) {
|
||||
RATE_CONTROL *const rc = &cpi->rc;
|
||||
|
||||
// Normalize RCF to account for the size-dependent scaling factor.
|
||||
factor /= rcf_mult[cpi->rc.frame_size_selector];
|
||||
|
||||
if (cpi->common.frame_type == KEY_FRAME) {
|
||||
rc->rate_correction_factors[KF_STD] = factor;
|
||||
} else if (cpi->oxcf.pass == 2) {
|
||||
|
@ -911,6 +917,23 @@ static int rc_pick_q_and_bounds_one_pass_vbr(const VP9_COMP *cpi,
|
|||
return q;
|
||||
}
|
||||
|
||||
int vp9_frame_type_qdelta(const VP9_COMP *cpi, int rf_level, int q) {
|
||||
static const double rate_factor_deltas[RATE_FACTOR_LEVELS] = {
|
||||
1.00, // INTER_NORMAL
|
||||
1.00, // INTER_HIGH
|
||||
1.50, // GF_ARF_LOW
|
||||
1.75, // GF_ARF_STD
|
||||
2.00, // KF_STD
|
||||
};
|
||||
static const FRAME_TYPE frame_type[RATE_FACTOR_LEVELS] =
|
||||
{INTER_FRAME, INTER_FRAME, INTER_FRAME, INTER_FRAME, KEY_FRAME};
|
||||
const VP9_COMMON *const cm = &cpi->common;
|
||||
int qdelta = vp9_compute_qdelta_by_rate(&cpi->rc, frame_type[rf_level],
|
||||
q, rate_factor_deltas[rf_level],
|
||||
cm->bit_depth);
|
||||
return qdelta;
|
||||
}
|
||||
|
||||
#define STATIC_MOTION_THRESH 95
|
||||
static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi,
|
||||
int *bottom_index,
|
||||
|
@ -918,6 +941,7 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi,
|
|||
const VP9_COMMON *const cm = &cpi->common;
|
||||
const RATE_CONTROL *const rc = &cpi->rc;
|
||||
const VP9EncoderConfig *const oxcf = &cpi->oxcf;
|
||||
const GF_GROUP *gf_group = &cpi->twopass.gf_group;
|
||||
const int cq_level = get_active_cq_level(rc, oxcf);
|
||||
int active_best_quality;
|
||||
int active_worst_quality = cpi->twopass.active_worst_quality;
|
||||
|
@ -999,7 +1023,6 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi,
|
|||
if (!cpi->refresh_alt_ref_frame) {
|
||||
active_best_quality = cq_level;
|
||||
} else {
|
||||
const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
|
||||
active_best_quality = get_gf_active_quality(rc, q, cm->bit_depth);
|
||||
|
||||
// Modify best quality for second level arfs. For mode VPX_Q this
|
||||
|
@ -1025,7 +1048,7 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi,
|
|||
}
|
||||
}
|
||||
|
||||
// Extenstion to max or min Q if undershoot or overshoot is outside
|
||||
// Extension to max or min Q if undershoot or overshoot is outside
|
||||
// the permitted range.
|
||||
if ((cpi->oxcf.rc_mode == VPX_VBR) &&
|
||||
(cpi->twopass.gf_zeromotion_pct < VLOW_MOTION_THRESHOLD)) {
|
||||
|
@ -1046,25 +1069,21 @@ static int rc_pick_q_and_bounds_two_pass(const VP9_COMP *cpi,
|
|||
if (!((frame_is_intra_only(cm) || vp9_is_upper_layer_key_frame(cpi))) ||
|
||||
!rc->this_key_frame_forced ||
|
||||
(cpi->twopass.last_kfgroup_zeromotion_pct < STATIC_MOTION_THRESH)) {
|
||||
const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
|
||||
const double rate_factor_deltas[RATE_FACTOR_LEVELS] = {
|
||||
1.00, // INTER_NORMAL
|
||||
1.00, // INTER_HIGH
|
||||
1.50, // GF_ARF_LOW
|
||||
1.75, // GF_ARF_STD
|
||||
2.00, // KF_STD
|
||||
};
|
||||
const double rate_factor =
|
||||
rate_factor_deltas[gf_group->rf_level[gf_group->index]];
|
||||
int qdelta = vp9_compute_qdelta_by_rate(&cpi->rc, cm->frame_type,
|
||||
active_worst_quality, rate_factor,
|
||||
cm->bit_depth);
|
||||
active_worst_quality = active_worst_quality + qdelta;
|
||||
active_worst_quality = MAX(active_worst_quality, active_best_quality);
|
||||
int qdelta = vp9_frame_type_qdelta(cpi, gf_group->rf_level[gf_group->index],
|
||||
active_worst_quality);
|
||||
active_worst_quality = MAX(active_worst_quality + qdelta,
|
||||
active_best_quality);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Clip the active best and worst quality values to limits.
|
||||
// Modify active_best_quality for downscaled normal frames.
|
||||
if (rc->frame_size_selector != UNSCALED && !frame_is_kf_gf_arf(cpi)) {
|
||||
int qdelta = vp9_compute_qdelta_by_rate(rc, cm->frame_type,
|
||||
active_best_quality, 2.0,
|
||||
cm->bit_depth);
|
||||
active_best_quality = MAX(active_best_quality + qdelta, rc->best_quality);
|
||||
}
|
||||
|
||||
active_best_quality = clamp(active_best_quality,
|
||||
rc->best_quality, rc->worst_quality);
|
||||
active_worst_quality = clamp(active_worst_quality,
|
||||
|
@ -1151,6 +1170,12 @@ void vp9_rc_set_frame_target(VP9_COMP *cpi, int target) {
|
|||
|
||||
rc->this_frame_target = target;
|
||||
|
||||
// Modify frame size target when down-scaling.
|
||||
if (cpi->oxcf.resize_mode == RESIZE_DYNAMIC &&
|
||||
rc->frame_size_selector != UNSCALED)
|
||||
rc->this_frame_target =
|
||||
rc->this_frame_target * rate_thresh_mult[rc->frame_size_selector];
|
||||
|
||||
// Target rate per SB64 (including partial SB64s.
|
||||
rc->sb64_target_rate = ((int64_t)rc->this_frame_target * 64 * 64) /
|
||||
(cm->width * cm->height);
|
||||
|
@ -1285,6 +1310,11 @@ void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) {
|
|||
rc->frames_since_key++;
|
||||
rc->frames_to_key--;
|
||||
}
|
||||
|
||||
// Trigger the resizing of the next frame if it is scaled.
|
||||
cpi->resize_pending =
|
||||
rc->next_frame_size_selector != rc->frame_size_selector;
|
||||
rc->frame_size_selector = rc->next_frame_size_selector;
|
||||
}
|
||||
|
||||
void vp9_rc_postencode_update_drop_frame(VP9_COMP *cpi) {
|
||||
|
|
|
@ -33,6 +33,27 @@ typedef enum {
|
|||
RATE_FACTOR_LEVELS = 5
|
||||
} RATE_FACTOR_LEVEL;
|
||||
|
||||
// Internal frame scaling level.
|
||||
typedef enum {
|
||||
UNSCALED = 0, // Frame is unscaled.
|
||||
SCALE_STEP1 = 1, // First-level down-scaling.
|
||||
FRAME_SCALE_STEPS
|
||||
} FRAME_SCALE_LEVEL;
|
||||
|
||||
// Frame dimensions multiplier wrt the native frame size, in 1/16ths,
|
||||
// specified for the scale-up case.
|
||||
// e.g. 24 => 16/24 = 2/3 of native size. The restriction to 1/16th is
|
||||
// intended to match the capabilities of the normative scaling filters,
|
||||
// giving precedence to the up-scaling accuracy.
|
||||
static const int frame_scale_factor[FRAME_SCALE_STEPS] = {16, 24};
|
||||
|
||||
// Multiplier of the target rate to be used as threshold for triggering scaling.
|
||||
static const double rate_thresh_mult[FRAME_SCALE_STEPS] = {1.0, 2.0};
|
||||
|
||||
// Scale dependent Rate Correction Factor multipliers. Compensates for the
|
||||
// greater number of bits per pixel generated in down-scaled frames.
|
||||
static const double rcf_mult[FRAME_SCALE_STEPS] = {1.0, 2.0};
|
||||
|
||||
typedef struct {
|
||||
// Rate targetting variables
|
||||
int base_frame_target; // A baseline frame target before adjustment
|
||||
|
@ -100,6 +121,7 @@ typedef struct {
|
|||
int64_t starting_buffer_level;
|
||||
int64_t optimal_buffer_level;
|
||||
int64_t maximum_buffer_size;
|
||||
|
||||
// rate control history for last frame(1) and the frame before(2).
|
||||
// -1: undershot
|
||||
// 1: overshoot
|
||||
|
@ -108,6 +130,13 @@ typedef struct {
|
|||
int rc_2_frame;
|
||||
int q_1_frame;
|
||||
int q_2_frame;
|
||||
|
||||
// Auto frame-scaling variables.
|
||||
FRAME_SCALE_LEVEL frame_size_selector;
|
||||
FRAME_SCALE_LEVEL next_frame_size_selector;
|
||||
int frame_width[FRAME_SCALE_STEPS];
|
||||
int frame_height[FRAME_SCALE_STEPS];
|
||||
int rf_level_maxq[RATE_FACTOR_LEVELS];
|
||||
} RATE_CONTROL;
|
||||
|
||||
struct VP9_COMP;
|
||||
|
@ -205,6 +234,8 @@ int vp9_compute_qdelta_by_rate(const RATE_CONTROL *rc, FRAME_TYPE frame_type,
|
|||
int qindex, double rate_target_ratio,
|
||||
vpx_bit_depth_t bit_depth);
|
||||
|
||||
int vp9_frame_type_qdelta(const struct VP9_COMP *cpi, int rf_level, int q);
|
||||
|
||||
void vp9_rc_update_framerate(struct VP9_COMP *cpi);
|
||||
|
||||
void vp9_rc_set_gf_max_interval(const struct VP9_COMP *const cpi,
|
||||
|
|
|
@ -1859,7 +1859,7 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
|||
for (midx = 0; midx < INTER_MODES; ++midx)
|
||||
bsi->rdstat[iy][midx].brdcost = INT64_MAX;
|
||||
bsi->segment_rd = INT64_MAX;
|
||||
return INT64_MAX;;
|
||||
return INT64_MAX;
|
||||
}
|
||||
|
||||
mode_idx = INTER_OFFSET(mode_selected);
|
||||
|
@ -1882,7 +1882,7 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
|||
for (midx = 0; midx < INTER_MODES; ++midx)
|
||||
bsi->rdstat[iy][midx].brdcost = INT64_MAX;
|
||||
bsi->segment_rd = INT64_MAX;
|
||||
return INT64_MAX;;
|
||||
return INT64_MAX;
|
||||
}
|
||||
}
|
||||
} /* for each label */
|
||||
|
@ -2105,24 +2105,27 @@ static void single_motion_search(VP9_COMP *cpi, MACROBLOCK *x,
|
|||
if (cpi->sf.adaptive_motion_search) {
|
||||
int bwl = b_width_log2_lookup[bsize];
|
||||
int bhl = b_height_log2_lookup[bsize];
|
||||
int i;
|
||||
int tlevel = x->pred_mv_sad[ref] >> (bwl + bhl + 4);
|
||||
|
||||
if (tlevel < 5)
|
||||
step_param += 2;
|
||||
|
||||
for (i = LAST_FRAME; i <= ALTREF_FRAME && cm->show_frame; ++i) {
|
||||
if ((x->pred_mv_sad[ref] >> 3) > x->pred_mv_sad[i]) {
|
||||
x->pred_mv[ref].row = 0;
|
||||
x->pred_mv[ref].col = 0;
|
||||
tmp_mv->as_int = INVALID_MV;
|
||||
// prev_mv_sad is not setup for dynamically scaled frames.
|
||||
if (cpi->oxcf.resize_mode != RESIZE_DYNAMIC) {
|
||||
int i;
|
||||
for (i = LAST_FRAME; i <= ALTREF_FRAME && cm->show_frame; ++i) {
|
||||
if ((x->pred_mv_sad[ref] >> 3) > x->pred_mv_sad[i]) {
|
||||
x->pred_mv[ref].row = 0;
|
||||
x->pred_mv[ref].col = 0;
|
||||
tmp_mv->as_int = INVALID_MV;
|
||||
|
||||
if (scaled_ref_frame) {
|
||||
int i;
|
||||
for (i = 0; i < MAX_MB_PLANE; i++)
|
||||
xd->plane[i].pre[0] = backup_yv12[i];
|
||||
if (scaled_ref_frame) {
|
||||
int i;
|
||||
for (i = 0; i < MAX_MB_PLANE; ++i)
|
||||
xd->plane[i].pre[0] = backup_yv12[i];
|
||||
}
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3518,6 +3521,8 @@ void vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi,
|
|||
best_mode_skippable |= !has_high_freq_coeff;
|
||||
}
|
||||
|
||||
assert(best_mode_index >= 0);
|
||||
|
||||
store_coding_context(x, ctx, best_mode_index, best_pred_diff,
|
||||
best_tx_diff, best_filter_diff, best_mode_skippable);
|
||||
}
|
||||
|
|
|
@ -105,7 +105,9 @@ static void set_good_speed_feature(VP9_COMP *cpi, VP9_COMMON *cm,
|
|||
sf->tx_size_search_method = frame_is_boosted(cpi) ? USE_FULL_RD
|
||||
: USE_LARGESTALL;
|
||||
|
||||
sf->reference_masking = 1;
|
||||
// Reference masking is not supported in dynamic scaling mode.
|
||||
sf->reference_masking = cpi->oxcf.resize_mode != RESIZE_DYNAMIC ? 1 : 0;
|
||||
|
||||
sf->mode_search_skip_flags = (cm->frame_type == KEY_FRAME) ? 0 :
|
||||
FLAG_SKIP_INTRA_DIRMISMATCH |
|
||||
FLAG_SKIP_INTRA_BESTINTER |
|
||||
|
@ -234,7 +236,10 @@ static void set_rt_speed_feature(VP9_COMP *cpi, SPEED_FEATURES *sf,
|
|||
FLAG_SKIP_COMP_BESTINTRA |
|
||||
FLAG_SKIP_INTRA_LOWVAR;
|
||||
sf->adaptive_pred_interp_filter = 2;
|
||||
sf->reference_masking = 1;
|
||||
|
||||
// Reference masking is not supported in dynamic scaling mode.
|
||||
sf->reference_masking = cpi->oxcf.resize_mode != RESIZE_DYNAMIC ? 1 : 0;
|
||||
|
||||
sf->disable_filter_search_var_thresh = 50;
|
||||
sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
|
||||
sf->auto_min_max_partition_size = RELAXED_NEIGHBORING_MIN_MAX;
|
||||
|
|
Загрузка…
Ссылка в новой задаче