diff --git a/vp8/vp8_cx_iface.c b/vp8/vp8_cx_iface.c index 4c896b1d1..6ca6087b2 100644 --- a/vp8/vp8_cx_iface.c +++ b/vp8/vp8_cx_iface.c @@ -1235,6 +1235,8 @@ static vpx_codec_enc_cfg_map_t vp8e_usage_cfg_map[] = 0, /* rc_dropframe_thresh */ 0, /* rc_resize_allowed */ + 1, /* rc_scaled_width */ + 1, /* rc_scaled_height */ 60, /* rc_resize_down_thresold */ 30, /* rc_resize_up_thresold */ diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index 1d70538c6..4b2aa8735 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -2997,6 +2997,15 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags, cm->frame_flags = *frame_flags; + if (cpi->pass == 2 && + cm->current_video_frame == 0 && + cpi->oxcf.allow_spatial_resampling && + cpi->oxcf.end_usage == USAGE_LOCAL_FILE_PLAYBACK) { + // Internal scaling is triggered on the first frame. + vp9_set_size_literal(cpi, cpi->oxcf.scaled_frame_width, + cpi->oxcf.scaled_frame_height); + } + // Reset the frame pointers to the current frame size vp9_realloc_frame_buffer(get_frame_new_buffer(cm), cm->width, cm->height, diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h index 9ad6ae49e..ad56e2a85 100644 --- a/vp9/encoder/vp9_onyx_int.h +++ b/vp9/encoder/vp9_onyx_int.h @@ -232,6 +232,11 @@ typedef struct VP9_CONFIG { int lossless; AQ_MODE aq_mode; // Adaptive Quantization mode + // Internal frame size scaling. + int allow_spatial_resampling; + int scaled_frame_width; + int scaled_frame_height; + // Enable feature to reduce the frame quantization every x frames. int frame_periodic_boost; diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index 0623ad132..967431c0f 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -168,6 +168,11 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx, RANGE_CHECK_HI(cfg, rc_resize_down_thresh, 100); RANGE_CHECK(cfg, g_pass, VPX_RC_ONE_PASS, VPX_RC_LAST_PASS); + if (cfg->rc_resize_allowed == 1) { + RANGE_CHECK(cfg, rc_scaled_width, 1, cfg->g_w); + RANGE_CHECK(cfg, rc_scaled_height, 1, cfg->g_h); + } + RANGE_CHECK(cfg, ss_number_layers, 1, VPX_SS_MAX_LAYERS); RANGE_CHECK(cfg, ts_number_layers, 1, VPX_TS_MAX_LAYERS); if (cfg->ts_number_layers > 1) { @@ -332,6 +337,10 @@ static vpx_codec_err_t set_encoder_config( oxcf->under_shoot_pct = cfg->rc_undershoot_pct; oxcf->over_shoot_pct = cfg->rc_overshoot_pct; + oxcf->allow_spatial_resampling = cfg->rc_resize_allowed; + oxcf->scaled_frame_width = cfg->rc_scaled_width; + oxcf->scaled_frame_height = cfg->rc_scaled_height; + oxcf->maximum_buffer_size = cfg->rc_buf_sz; oxcf->starting_buffer_level = cfg->rc_buf_initial_sz; oxcf->optimal_buffer_level = cfg->rc_buf_optimal_sz; @@ -410,6 +419,9 @@ static vpx_codec_err_t set_encoder_config( printf("fixed_q: %d\n", oxcf->fixed_q); printf("worst_allowed_q: %d\n", oxcf->worst_allowed_q); printf("best_allowed_q: %d\n", oxcf->best_allowed_q); + printf("allow_spatial_resampling: %d\n", oxcf->allow_spatial_resampling); + printf("scaled_frame_width: %d\n", oxcf->scaled_frame_width); + printf("scaled_frame_height: %d\n", oxcf->scaled_frame_height); printf("two_pass_vbrbias: %d\n", oxcf->two_pass_vbrbias); printf("two_pass_vbrmin_section: %d\n", oxcf->two_pass_vbrmin_section); printf("two_pass_vbrmax_section: %d\n", oxcf->two_pass_vbrmax_section); @@ -1128,6 +1140,8 @@ static vpx_codec_enc_cfg_map_t encoder_usage_cfg_map[] = { 0, // rc_dropframe_thresh 0, // rc_resize_allowed + 1, // rc_scaled_width + 1, // rc_scaled_height 60, // rc_resize_down_thresold 30, // rc_resize_up_thresold diff --git a/vpx/vpx_encoder.h b/vpx/vpx_encoder.h index 2c882c19a..571ad3fc5 100644 --- a/vpx/vpx_encoder.h +++ b/vpx/vpx_encoder.h @@ -396,6 +396,19 @@ extern "C" { */ unsigned int rc_resize_allowed; + /*!\brief Internal coded frame width. + * + * If spatial resampling is enabled this specifies the width of the + * encoded frame. + */ + unsigned int rc_scaled_width; + + /*!\brief Internal coded frame height. + * + * If spatial resampling is enabled this specifies the height of the + * encoded frame. + */ + unsigned int rc_scaled_height; /*!\brief Spatial resampling up watermark. * diff --git a/vpxenc.c b/vpxenc.c index cb91d94da..c4d642159 100644 --- a/vpxenc.c +++ b/vpxenc.c @@ -235,6 +235,10 @@ static const arg_def_t dropframe_thresh = ARG_DEF(NULL, "drop-frame", 1, "Temporal resampling threshold (buf %)"); static const arg_def_t resize_allowed = ARG_DEF(NULL, "resize-allowed", 1, "Spatial resampling enabled (bool)"); +static const arg_def_t resize_width = ARG_DEF(NULL, "resize-width", 1, + "Width of encoded frame"); +static const arg_def_t resize_height = ARG_DEF(NULL, "resize-height", 1, + "Height of encoded frame"); static const arg_def_t resize_up_thresh = ARG_DEF(NULL, "resize-up", 1, "Upscale threshold (buf %)"); static const arg_def_t resize_down_thresh = ARG_DEF(NULL, "resize-down", 1, @@ -265,10 +269,10 @@ static const arg_def_t buf_initial_sz = ARG_DEF(NULL, "buf-initial-sz", 1, 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_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 + &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 }; @@ -883,6 +887,10 @@ static int parse_stream_params(struct VpxEncoderConfig *global, config->cfg.rc_dropframe_thresh = arg_parse_uint(&arg); } else if (arg_match(&arg, &resize_allowed, argi)) { config->cfg.rc_resize_allowed = arg_parse_uint(&arg); + } else if (arg_match(&arg, &resize_width, argi)) { + config->cfg.rc_scaled_width = arg_parse_uint(&arg); + } else if (arg_match(&arg, &resize_height, argi)) { + config->cfg.rc_scaled_height = arg_parse_uint(&arg); } else if (arg_match(&arg, &resize_up_thresh, argi)) { config->cfg.rc_resize_up_thresh = arg_parse_uint(&arg); } else if (arg_match(&arg, &resize_down_thresh, argi)) { @@ -1067,6 +1075,8 @@ static void show_stream_config(struct stream_state *stream, SHOW(g_lag_in_frames); SHOW(rc_dropframe_thresh); SHOW(rc_resize_allowed); + SHOW(rc_scaled_width); + SHOW(rc_scaled_height); SHOW(rc_resize_up_thresh); SHOW(rc_resize_down_thresh); SHOW(rc_end_usage);