Commit ba06be38 authored by jackychen's avatar jackychen

Two-steps scaling in VP9 encoder dynamic resizing.

Dynamic resizing now support two-steps scaling: first go down to
3/4 and then 1/2. This feature is under a flag which controls the
switch between two-steps scaling and one-step scaling (1/2 only).

Change-Id: I3a6c1d3d5668cf8e016a0a02aeca737565604a0f
parent dfeaaeb0
...@@ -3130,26 +3130,19 @@ static void set_frame_size(VP9_COMP *cpi) { ...@@ -3130,26 +3130,19 @@ static void set_frame_size(VP9_COMP *cpi) {
if (oxcf->pass == 0 && if (oxcf->pass == 0 &&
oxcf->rc_mode == VPX_CBR && oxcf->rc_mode == VPX_CBR &&
!cpi->use_svc && !cpi->use_svc &&
oxcf->resize_mode == RESIZE_DYNAMIC) { oxcf->resize_mode == RESIZE_DYNAMIC &&
if (cpi->resize_pending == 1) { cpi->resize_pending != 0) {
oxcf->scaled_frame_width = oxcf->scaled_frame_width =
(cm->width * cpi->resize_scale_num) / cpi->resize_scale_den; (oxcf->width * cpi->resize_scale_num) / cpi->resize_scale_den;
oxcf->scaled_frame_height = oxcf->scaled_frame_height =
(cm->height * cpi->resize_scale_num) /cpi->resize_scale_den; (oxcf->height * cpi->resize_scale_num) /cpi->resize_scale_den;
} else if (cpi->resize_pending == -1) { // There has been a change in frame size.
// Go back up to original size. vp9_set_size_literal(cpi,
oxcf->scaled_frame_width = oxcf->width; oxcf->scaled_frame_width,
oxcf->scaled_frame_height = oxcf->height; oxcf->scaled_frame_height);
}
if (cpi->resize_pending != 0) { // TODO(agrange) Scale cpi->max_mv_magnitude if frame-size has changed.
// There has been a change in frame size. set_mv_search_params(cpi);
vp9_set_size_literal(cpi,
oxcf->scaled_frame_width,
oxcf->scaled_frame_height);
// TODO(agrange) Scale cpi->max_mv_magnitude if frame-size has changed.
set_mv_search_params(cpi);
}
} }
if ((oxcf->pass == 2) && if ((oxcf->pass == 2) &&
......
...@@ -1820,7 +1820,7 @@ void vp9_set_target_rate(VP9_COMP *cpi) { ...@@ -1820,7 +1820,7 @@ void vp9_set_target_rate(VP9_COMP *cpi) {
int vp9_resize_one_pass_cbr(VP9_COMP *cpi) { int vp9_resize_one_pass_cbr(VP9_COMP *cpi) {
const VP9_COMMON *const cm = &cpi->common; const VP9_COMMON *const cm = &cpi->common;
RATE_CONTROL *const rc = &cpi->rc; RATE_CONTROL *const rc = &cpi->rc;
int resize_now = 0; RESIZE_ACTION resize_action = NO_RESIZE;
cpi->resize_scale_num = 1; cpi->resize_scale_num = 1;
cpi->resize_scale_den = 1; cpi->resize_scale_den = 1;
// Don't resize on key frame; reset the counters on key frame. // Don't resize on key frame; reset the counters on key frame.
...@@ -1840,18 +1840,32 @@ int vp9_resize_one_pass_cbr(VP9_COMP *cpi) { ...@@ -1840,18 +1840,32 @@ int vp9_resize_one_pass_cbr(VP9_COMP *cpi) {
// Check for resize action every "window" frames. // Check for resize action every "window" frames.
if (cpi->resize_count >= window) { if (cpi->resize_count >= window) {
int avg_qp = cpi->resize_avg_qp / cpi->resize_count; int avg_qp = cpi->resize_avg_qp / cpi->resize_count;
// Resize down if buffer level has underflowed sufficent amount in past // Resize down if buffer level has underflowed sufficient amount in past
// window, and we are at original resolution. // window, and we are at original or 3/4 of original resolution.
// Resize back up if average QP is low, and we are currently in a resized // Resize back up if average QP is low, and we are currently in a resized
// down state. // down state, i.e. 1/2 or 3/4 of original resolution.
if (cpi->resize_state == 0 && // Currently, use a flag to turn 3/4 resizing feature on/off.
cpi->resize_buffer_underflow > (cpi->resize_count >> 2)) { if (cpi->resize_buffer_underflow > (cpi->resize_count >> 1)) {
resize_now = 1; resize_action = DOWN_ONEHALF;
cpi->resize_state = 1; cpi->resize_state = ONE_HALF;
} else if (cpi->resize_state == 1 && } else if (cpi->resize_buffer_underflow > (cpi->resize_count >> 2)) {
avg_qp < 50 * cpi->rc.worst_quality / 100) { if (cpi->resize_state == THREE_QUARTER || ONEHALFONLY_RESIZE) {
resize_now = -1; resize_action = DOWN_ONEHALF;
cpi->resize_state = 0; cpi->resize_state = ONE_HALF;
} else if (cpi->resize_state == ORIG) {
resize_action = DOWN_THREEFOUR;
cpi->resize_state = THREE_QUARTER;
}
} else if (avg_qp < 60 * cpi->rc.worst_quality / 100) {
if (cpi->resize_state == THREE_QUARTER ||
avg_qp < 40 * cpi->rc.worst_quality / 100 ||
ONEHALFONLY_RESIZE) {
resize_action = UP_ORIG;
cpi->resize_state = ORIG;
} else if (cpi->resize_state == ONE_HALF) {
resize_action = UP_THREEFOUR;
cpi->resize_state = THREE_QUARTER;
}
} }
// Reset for next window measurement. // Reset for next window measurement.
cpi->resize_avg_qp = 0; cpi->resize_avg_qp = 0;
...@@ -1861,14 +1875,21 @@ int vp9_resize_one_pass_cbr(VP9_COMP *cpi) { ...@@ -1861,14 +1875,21 @@ int vp9_resize_one_pass_cbr(VP9_COMP *cpi) {
} }
// If decision is to resize, reset some quantities, and check is we should // If decision is to resize, reset some quantities, and check is we should
// reduce rate correction factor, // reduce rate correction factor,
if (resize_now != 0) { if (resize_action != NO_RESIZE) {
int target_bits_per_frame; int target_bits_per_frame;
int active_worst_quality; int active_worst_quality;
int qindex; int qindex;
int tot_scale_change; int tot_scale_change;
// For now, resize is by 1/2 x 1/2. if (resize_action == DOWN_THREEFOUR || resize_action == UP_THREEFOUR) {
cpi->resize_scale_num = 1; cpi->resize_scale_num = 3;
cpi->resize_scale_den = 2; cpi->resize_scale_den = 4;
} else if (resize_action == DOWN_ONEHALF) {
cpi->resize_scale_num = 1;
cpi->resize_scale_den = 2;
} else { // UP_ORIG or anything else
cpi->resize_scale_num = 1;
cpi->resize_scale_den = 1;
}
tot_scale_change = (cpi->resize_scale_den * cpi->resize_scale_den) / tot_scale_change = (cpi->resize_scale_den * cpi->resize_scale_den) /
(cpi->resize_scale_num * cpi->resize_scale_num); (cpi->resize_scale_num * cpi->resize_scale_num);
// Reset buffer level to optimal, update target size. // Reset buffer level to optimal, update target size.
...@@ -1880,7 +1901,7 @@ int vp9_resize_one_pass_cbr(VP9_COMP *cpi) { ...@@ -1880,7 +1901,7 @@ int vp9_resize_one_pass_cbr(VP9_COMP *cpi) {
vp9_cyclic_refresh_reset_resize(cpi); vp9_cyclic_refresh_reset_resize(cpi);
// Get the projected qindex, based on the scaled target frame size (scaled // Get the projected qindex, based on the scaled target frame size (scaled
// so target_bits_per_mb in vp9_rc_regulate_q will be correct target). // so target_bits_per_mb in vp9_rc_regulate_q will be correct target).
target_bits_per_frame = (resize_now == 1) ? target_bits_per_frame = (resize_action >= 0) ?
rc->this_frame_target * tot_scale_change : rc->this_frame_target * tot_scale_change :
rc->this_frame_target / tot_scale_change; rc->this_frame_target / tot_scale_change;
active_worst_quality = calc_active_worst_quality_one_pass_cbr(cpi); active_worst_quality = calc_active_worst_quality_one_pass_cbr(cpi);
...@@ -1891,19 +1912,19 @@ int vp9_resize_one_pass_cbr(VP9_COMP *cpi) { ...@@ -1891,19 +1912,19 @@ int vp9_resize_one_pass_cbr(VP9_COMP *cpi) {
// If resize is down, check if projected q index is close to worst_quality, // If resize is down, check if projected q index is close to worst_quality,
// and if so, reduce the rate correction factor (since likely can afford // and if so, reduce the rate correction factor (since likely can afford
// lower q for resized frame). // lower q for resized frame).
if (resize_now == 1 && if (resize_action > 0 &&
qindex > 90 * cpi->rc.worst_quality / 100) { qindex > 90 * cpi->rc.worst_quality / 100) {
rc->rate_correction_factors[INTER_NORMAL] *= 0.85; rc->rate_correction_factors[INTER_NORMAL] *= 0.85;
} }
// If resize is back up, check if projected q index is too much above the // If resize is back up, check if projected q index is too much above the
// current base_qindex, and if so, reduce the rate correction factor // current base_qindex, and if so, reduce the rate correction factor
// (since prefer to keep q for resized frame at least close to previous q). // (since prefer to keep q for resized frame at least close to previous q).
if (resize_now == -1 && if (resize_action < 0 &&
qindex > 130 * cm->base_qindex / 100) { qindex > 130 * cm->base_qindex / 100) {
rc->rate_correction_factors[INTER_NORMAL] *= 0.9; rc->rate_correction_factors[INTER_NORMAL] *= 0.9;
} }
} }
return resize_now; return resize_action;
} }
// Compute average source sad (temporal sad: between current source and // Compute average source sad (temporal sad: between current source and
......
...@@ -26,6 +26,7 @@ extern "C" { ...@@ -26,6 +26,7 @@ extern "C" {
#define MIN_GF_INTERVAL 4 #define MIN_GF_INTERVAL 4
#define MAX_GF_INTERVAL 16 #define MAX_GF_INTERVAL 16
#define ONEHALFONLY_RESIZE 1
typedef enum { typedef enum {
INTER_NORMAL = 0, INTER_NORMAL = 0,
...@@ -43,6 +44,20 @@ typedef enum { ...@@ -43,6 +44,20 @@ typedef enum {
FRAME_SCALE_STEPS FRAME_SCALE_STEPS
} FRAME_SCALE_LEVEL; } FRAME_SCALE_LEVEL;
typedef enum {
NO_RESIZE = 0,
DOWN_THREEFOUR = 1, // From orig to 3/4.
DOWN_ONEHALF = 2, // From orig or 3/4 to 1/2.
UP_THREEFOUR = -1, // From 1/2 to 3/4.
UP_ORIG = -2, // From 1/2 or 3/4 to orig.
} RESIZE_ACTION;
typedef enum {
ORIG = 0,
THREE_QUARTER = 1,
ONE_HALF = 2
} RESIZE_STATE;
// Frame dimensions multiplier wrt the native frame size, in 1/16ths, // Frame dimensions multiplier wrt the native frame size, in 1/16ths,
// specified for the scale-up case. // specified for the scale-up case.
// e.g. 24 => 16/24 = 2/3 of native size. The restriction to 1/16th is // e.g. 24 => 16/24 = 2/3 of native size. The restriction to 1/16th is
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment