Commit c4e78942 authored by Fergus Simpson's avatar Fergus Simpson Committed by Debargha Mukherjee

frame_superres: Add aomenc argument

Adds "superres-mode" and "superres-numerator" arguments to configure
superres scaling.

There are only two modes right now: SUPERRES_FIXED and SUPERRES_DYNAMIC.
0 sets the fixed mode and 1 sets the dynamic mode.

For the fixed mode superres will scale to the provided numerator where
possible. The cumulative scale change over resizing and superres is
limited to 1/2, so it may have to back off.

For the dynamic mode, the provided numerator will be used as the initial
numerator. Asides from that it's just random for now.

Change-Id: Ibae01c77abba2599fbf51096459d09ddca458d4f
parent 76fb1265
......@@ -402,6 +402,29 @@ typedef struct aom_codec_enc_cfg {
*/
unsigned int rc_resize_down_thresh;
/*!\brief Frame super-resolution scaling mode.
*
* Similar to spatial resampling, frame super-resolution integrates
* upscaling after the encode/decode process. Taking control of upscaling and
* using restoration filters should allow it to outperform normal resizing.
*
* Mode 0 is SUPERRES_NONE, mode 1 is SUPERRES_FIXED, and mode 2 is
* SUPERRES_DYNAMIC.
*/
unsigned int rc_superres_mode;
/*!\brief Frame super-resolution numerator.
*
* The numerator for superres to use. If fixed it will only change if the
* cumulative scale change over resizing and superres is greater than 1/2;
* this forces superres to reduce scaling.
*
* Valid numerators are 8 to 16.
*
* Ignored by SUPERRES_DYNAMIC.
*/
unsigned int rc_superres_numerator;
/*!\brief Rate control algorithm to use.
*
* Indicates whether the end usage of this stream is to be streamed over
......
......@@ -286,6 +286,12 @@ static const struct arg_enum_list end_usage_enum[] = { { "vbr", AOM_VBR },
{ "cq", AOM_CQ },
{ "q", AOM_Q },
{ NULL, 0 } };
#if CONFIG_FRAME_SUPERRES
static const arg_def_t superres_mode =
ARG_DEF(NULL, "superres-mode", 1, "Frame super-resolution mode");
static const arg_def_t superres_numerator =
ARG_DEF(NULL, "superres-numerator", 1, "Frame super-resolution numerator");
#endif // CONFIG_FRAME_SUPERRES
static const arg_def_t end_usage =
ARG_DEF_ENUM(NULL, "end-usage", 1, "Rate control mode", end_usage_enum);
static const arg_def_t target_bitrate =
......@@ -304,12 +310,17 @@ static const arg_def_t buf_initial_sz =
ARG_DEF(NULL, "buf-initial-sz", 1, "Client initial buffer size (ms)");
static const arg_def_t buf_optimal_sz =
ARG_DEF(NULL, "buf-optimal-sz", 1, "Client optimal buffer size (ms)");
static const arg_def_t *rc_args[] = {
&dropframe_thresh, &resize_allowed, &resize_width, &resize_height,
&resize_up_thresh, &resize_down_thresh, &end_usage, &target_bitrate,
&min_quantizer, &max_quantizer, &undershoot_pct, &overshoot_pct,
&buf_sz, &buf_initial_sz, &buf_optimal_sz, NULL
};
static const arg_def_t *rc_args[] = { &dropframe_thresh, &resize_allowed,
&resize_width, &resize_height,
&resize_up_thresh, &resize_down_thresh,
#if CONFIG_FRAME_SUPERRES
&superres_mode, &superres_numerator,
#endif // CONFIG_FRAME_SUPERRES
&end_usage, &target_bitrate,
&min_quantizer, &max_quantizer,
&undershoot_pct, &overshoot_pct,
&buf_sz, &buf_initial_sz,
&buf_optimal_sz, NULL };
static const arg_def_t bias_pct =
ARG_DEF(NULL, "bias-pct", 1, "CBR/VBR bias (0=CBR, 100=VBR)");
......@@ -1011,6 +1022,12 @@ static int parse_stream_params(struct AvxEncoderConfig *global,
config->cfg.rc_resize_up_thresh = arg_parse_uint(&arg);
} else if (arg_match(&arg, &resize_down_thresh, argi)) {
config->cfg.rc_resize_down_thresh = arg_parse_uint(&arg);
#if CONFIG_FRAME_SUPERRES
} else if (arg_match(&arg, &superres_mode, argi)) {
config->cfg.rc_superres_mode = arg_parse_uint(&arg);
} else if (arg_match(&arg, &superres_numerator, argi)) {
config->cfg.rc_superres_numerator = arg_parse_uint(&arg);
#endif // CONFIG_FRAME_SUPERRES
} else if (arg_match(&arg, &end_usage, argi)) {
config->cfg.rc_end_usage = arg_parse_enum_or_int(&arg);
} else if (arg_match(&arg, &target_bitrate, argi)) {
......@@ -1221,6 +1238,10 @@ static void show_stream_config(struct stream_state *stream,
SHOW(rc_scaled_height);
SHOW(rc_resize_up_thresh);
SHOW(rc_resize_down_thresh);
#if CONFIG_FRAME_SUPERRES
SHOW(rc_superres_mode);
SHOW(rc_superres_numerator);
#endif // CONFIG_FRAME_SUPERRES
SHOW(rc_end_usage);
SHOW(rc_target_bitrate);
SHOW(rc_min_quantizer);
......
......@@ -263,6 +263,12 @@ static aom_codec_err_t validate_config(aom_codec_alg_priv_t *ctx,
RANGE_CHECK_HI(cfg, rc_scaled_height, cfg->g_h);
}
#if CONFIG_FRAME_SUPERRES
RANGE_CHECK_HI(cfg, rc_superres_mode, SUPERRES_DYNAMIC);
RANGE_CHECK(cfg, rc_superres_numerator, SUPERRES_SCALE_DENOMINATOR / 2,
SUPERRES_SCALE_DENOMINATOR);
#endif // CONFIG_FRAME_SUPERRES
// AV1 does not support a lower bound on the keyframe interval in
// automatic keyframe placement mode.
if (cfg->kf_mode != AOM_KF_DISABLED && cfg->kf_min_dist != cfg->kf_max_dist &&
......@@ -505,8 +511,12 @@ static aom_codec_err_t set_encoder_config(
}
#if CONFIG_FRAME_SUPERRES
oxcf->superres_enabled = 1; // TODO(afergs): Check the config
#endif // CONFIG_FRAME_SUPERRES
oxcf->superres_mode = (SUPERRES_MODE)cfg->rc_superres_mode;
oxcf->superres_scale_numerator = (uint8_t)cfg->rc_superres_numerator;
if (oxcf->superres_mode == SUPERRES_FIXED &&
oxcf->superres_scale_numerator == SUPERRES_SCALE_DENOMINATOR)
oxcf->superres_mode = SUPERRES_NONE;
#endif // CONFIG_FRAME_SUPERRES
oxcf->maximum_buffer_size_ms = is_vbr ? 240000 : cfg->rc_buf_sz;
oxcf->starting_buffer_level_ms = is_vbr ? 60000 : cfg->rc_buf_initial_sz;
......@@ -1596,6 +1606,9 @@ static aom_codec_enc_cfg_map_t encoder_usage_cfg_map[] = {
60, // rc_resize_down_thresold
30, // rc_resize_up_thresold
0, // rc_superres_mode
SUPERRES_SCALE_DENOMINATOR, // rc_superres_numerator
AOM_VBR, // rc_end_usage
{ NULL, 0 }, // rc_twopass_stats_in
{ NULL, 0 }, // rc_firstpass_mb_stats_in
......
......@@ -546,8 +546,8 @@ typedef enum {
} RestorationType;
#endif // CONFIG_LOOP_RESTORATION
#if CONFIG_FRAME_SUPERRES
#define SUPERRES_SCALE_DENOMINATOR 16
#if CONFIG_FRAME_SUPERRES
#define SUPERRES_SCALE_BITS 3
#define SUPERRES_SCALE_NUMERATOR_MIN 8
#endif // CONFIG_FRAME_SUPERRES
......
......@@ -3849,17 +3849,20 @@ static void setup_frame_size(AV1_COMP *cpi) {
int encode_height;
av1_calculate_next_scaled_size(cpi, &encode_width, &encode_height);
printf("encode size: %dx%d ", encode_width, encode_height);
#if CONFIG_FRAME_SUPERRES
AV1_COMMON *cm = &cpi->common;
cm->superres_upscaled_width = encode_width;
cm->superres_upscaled_height = encode_height;
cpi->common.superres_scale_numerator =
av1_calculate_next_superres_scale(cpi, encode_width, encode_width);
cm->superres_scale_numerator = (uint8_t)av1_calculate_next_superres_scale(
cpi, encode_width, encode_width);
av1_calculate_superres_size(cm, &encode_width, &encode_height);
// printf("Resize/superres %d x %d -> %d x %d\n", encode_width, encode_height,
// cm->superres_upscaled_width, cm->superres_upscaled_height);
// printf("Resize/superres %d x %d -> %d x %d\n", encode_width, encode_height,
// cm->superres_upscaled_width, cm->superres_upscaled_height);
printf("superres numerator: %02d ", cm->superres_scale_numerator);
#endif // CONFIG_FRAME_SUPERRES
printf("Final encode size: %dx%d\n", encode_width, encode_height);
set_frame_size(cpi, encode_width, encode_height);
}
......
......@@ -130,6 +130,13 @@ typedef enum {
RESIZE_FIXED = 1, // All frames are coded at the specified dimension.
RESIZE_DYNAMIC = 2 // Coded size of each frame is determined by the codec.
} RESIZE_TYPE;
#if CONFIG_FRAME_SUPERRES
typedef enum {
SUPERRES_NONE = 0,
SUPERRES_FIXED = 1,
SUPERRES_DYNAMIC = 2
} SUPERRES_MODE;
#endif // CONFIG_FRAME_SUPERRES
typedef struct AV1EncoderConfig {
BITSTREAM_PROFILE profile;
......@@ -205,8 +212,9 @@ typedef struct AV1EncoderConfig {
int scaled_frame_height;
#if CONFIG_FRAME_SUPERRES
// Frame Super-Resolution size scaling
int superres_enabled;
// Frame Super-Resolution size scaling.
SUPERRES_MODE superres_mode;
uint8_t superres_scale_numerator;
#endif // CONFIG_FRAME_SUPERRES
// Enable feature to reduce the frame quantization every x frames.
......
......@@ -1670,11 +1670,12 @@ static unsigned int lcg_rand16(unsigned int *state) {
}
void av1_calculate_next_scaled_size(AV1_COMP *cpi, int *width, int *height) {
static unsigned int seed = 56789;
AV1EncoderConfig *oxcf = &cpi->oxcf;
// TODO(afergs): Get width from frame instead?
*width = oxcf->width;
*height = oxcf->height;
if (oxcf->pass == 1) return;
if (oxcf->resize_mode == RESIZE_FIXED) {
*width = oxcf->scaled_frame_width;
......@@ -1683,7 +1684,6 @@ void av1_calculate_next_scaled_size(AV1_COMP *cpi, int *width, int *height) {
}
if (oxcf->resize_mode == RESIZE_DYNAMIC) {
// NOTE: RESIZE_DYNAMIC defaults to random now.
static unsigned int seed = 56789;
if (oxcf->pass == 2 || oxcf->pass == 0) {
int scale_num = lcg_rand16(&seed) % 4 + 13;
int scale_den = 16;
......@@ -1697,22 +1697,29 @@ void av1_calculate_next_scaled_size(AV1_COMP *cpi, int *width, int *height) {
}
#if CONFIG_FRAME_SUPERRES
#define RANDOM_SUPERRES 1
int av1_calculate_next_superres_scale(AV1_COMP *cpi, int width, int height) {
// TODO(afergs): Rename av1_rc_update_superres_scale(...)?
int av1_calculate_next_superres_scale(const AV1_COMP *cpi, int width,
int height) {
static unsigned int seed = 34567;
const AV1EncoderConfig *oxcf = &cpi->oxcf;
(void)width;
(void)height;
(void)oxcf;
#if RANDOM_SUPERRES
if (oxcf->pass == 2 || oxcf->pass == 0) {
static unsigned int seed = 34567;
int new_num = lcg_rand16(&seed) % 9 + 8;
if (new_num * width / SUPERRES_SCALE_DENOMINATOR * 2 < oxcf->width ||
new_num * height / SUPERRES_SCALE_DENOMINATOR * 2 < oxcf->height)
new_num = SUPERRES_SCALE_DENOMINATOR;
return new_num;
if (oxcf->pass == 1) return SUPERRES_SCALE_DENOMINATOR;
uint8_t new_num = cpi->common.superres_scale_numerator;
switch (oxcf->superres_mode) {
case SUPERRES_NONE: return SUPERRES_SCALE_DENOMINATOR; break;
case SUPERRES_FIXED: new_num = oxcf->superres_scale_numerator; break;
case SUPERRES_DYNAMIC:
// SUPERRES_DYNAMIC: Just random for now.
new_num = lcg_rand16(&seed) % 9 + 8;
break;
default: assert(0);
}
#endif // RANDOM_SUPERRES
return SUPERRES_SCALE_DENOMINATOR;
// Make sure overall reduction is no more than 1/2 of the source size.
if (new_num * width / SUPERRES_SCALE_DENOMINATOR * 2 < oxcf->width ||
new_num * height / SUPERRES_SCALE_DENOMINATOR * 2 < oxcf->height)
new_num = SUPERRES_SCALE_DENOMINATOR;
return new_num;
}
#endif // CONFIG_FRAME_SUPERRES
......@@ -259,7 +259,7 @@ int av1_resize_one_pass_cbr(struct AV1_COMP *cpi);
void av1_calculate_next_scaled_size(struct AV1_COMP *cpi, int *width,
int *height);
#if CONFIG_FRAME_SUPERRES
int av1_calculate_next_superres_scale(struct AV1_COMP *cpi, int width,
int av1_calculate_next_superres_scale(const struct AV1_COMP *cpi, int width,
int height);
#endif // CONFIG_FRAME_SUPERRES
#ifdef __cplusplus
......
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