From: jackychen Date: Thu, 1 Oct 2015 21:03:22 +0000 (-0700) Subject: Two-steps scaling in VP9 encoder dynamic resizing. X-Git-Tag: v1.5.0~88^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=ba06be38449537aff7a18c0c344ada0e3ee8ee69;p=platform%2Fupstream%2Flibvpx.git 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 --- diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index e67ce88..0615369 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -3130,26 +3130,19 @@ static void set_frame_size(VP9_COMP *cpi) { if (oxcf->pass == 0 && oxcf->rc_mode == VPX_CBR && !cpi->use_svc && - oxcf->resize_mode == RESIZE_DYNAMIC) { - if (cpi->resize_pending == 1) { - oxcf->scaled_frame_width = - (cm->width * cpi->resize_scale_num) / cpi->resize_scale_den; - oxcf->scaled_frame_height = - (cm->height * cpi->resize_scale_num) /cpi->resize_scale_den; - } else if (cpi->resize_pending == -1) { - // Go back up to original size. - oxcf->scaled_frame_width = oxcf->width; - oxcf->scaled_frame_height = oxcf->height; - } - if (cpi->resize_pending != 0) { - // There has been a change in frame size. - 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); - } + oxcf->resize_mode == RESIZE_DYNAMIC && + cpi->resize_pending != 0) { + oxcf->scaled_frame_width = + (oxcf->width * cpi->resize_scale_num) / cpi->resize_scale_den; + oxcf->scaled_frame_height = + (oxcf->height * cpi->resize_scale_num) /cpi->resize_scale_den; + // There has been a change in frame size. + 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) && diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c index 973cde8..4fe5561 100644 --- a/vp9/encoder/vp9_ratectrl.c +++ b/vp9/encoder/vp9_ratectrl.c @@ -1820,7 +1820,7 @@ void vp9_set_target_rate(VP9_COMP *cpi) { int vp9_resize_one_pass_cbr(VP9_COMP *cpi) { const VP9_COMMON *const cm = &cpi->common; RATE_CONTROL *const rc = &cpi->rc; - int resize_now = 0; + RESIZE_ACTION resize_action = NO_RESIZE; cpi->resize_scale_num = 1; cpi->resize_scale_den = 1; // 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) { // Check for resize action every "window" frames. if (cpi->resize_count >= window) { int avg_qp = cpi->resize_avg_qp / cpi->resize_count; - // Resize down if buffer level has underflowed sufficent amount in past - // window, and we are at original resolution. + // Resize down if buffer level has underflowed sufficient amount in past + // 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 - // down state. - if (cpi->resize_state == 0 && - cpi->resize_buffer_underflow > (cpi->resize_count >> 2)) { - resize_now = 1; - cpi->resize_state = 1; - } else if (cpi->resize_state == 1 && - avg_qp < 50 * cpi->rc.worst_quality / 100) { - resize_now = -1; - cpi->resize_state = 0; + // down state, i.e. 1/2 or 3/4 of original resolution. + // Currently, use a flag to turn 3/4 resizing feature on/off. + if (cpi->resize_buffer_underflow > (cpi->resize_count >> 1)) { + resize_action = DOWN_ONEHALF; + cpi->resize_state = ONE_HALF; + } else if (cpi->resize_buffer_underflow > (cpi->resize_count >> 2)) { + if (cpi->resize_state == THREE_QUARTER || ONEHALFONLY_RESIZE) { + resize_action = DOWN_ONEHALF; + 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. cpi->resize_avg_qp = 0; @@ -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 // reduce rate correction factor, - if (resize_now != 0) { + if (resize_action != NO_RESIZE) { int target_bits_per_frame; int active_worst_quality; int qindex; int tot_scale_change; - // For now, resize is by 1/2 x 1/2. - cpi->resize_scale_num = 1; - cpi->resize_scale_den = 2; + if (resize_action == DOWN_THREEFOUR || resize_action == UP_THREEFOUR) { + cpi->resize_scale_num = 3; + 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) / (cpi->resize_scale_num * cpi->resize_scale_num); // Reset buffer level to optimal, update target size. @@ -1880,7 +1901,7 @@ int vp9_resize_one_pass_cbr(VP9_COMP *cpi) { vp9_cyclic_refresh_reset_resize(cpi); // 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). - 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; active_worst_quality = calc_active_worst_quality_one_pass_cbr(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, // and if so, reduce the rate correction factor (since likely can afford // lower q for resized frame). - if (resize_now == 1 && + if (resize_action > 0 && qindex > 90 * cpi->rc.worst_quality / 100) { rc->rate_correction_factors[INTER_NORMAL] *= 0.85; } // 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 // (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) { rc->rate_correction_factors[INTER_NORMAL] *= 0.9; } } - return resize_now; + return resize_action; } // Compute average source sad (temporal sad: between current source and diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h index 11dfa35..eb7c793 100644 --- a/vp9/encoder/vp9_ratectrl.h +++ b/vp9/encoder/vp9_ratectrl.h @@ -26,6 +26,7 @@ extern "C" { #define MIN_GF_INTERVAL 4 #define MAX_GF_INTERVAL 16 +#define ONEHALFONLY_RESIZE 1 typedef enum { INTER_NORMAL = 0, @@ -43,6 +44,20 @@ typedef enum { FRAME_SCALE_STEPS } 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, // specified for the scale-up case. // e.g. 24 => 16/24 = 2/3 of native size. The restriction to 1/16th is