From 812945a8f143df6a627cb292ec7a77a4ed6509f0 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Fri, 25 Sep 2015 21:51:55 -0400 Subject: [PATCH] vp9/10: improve support for render_width/height. In the decoder, map this to the output variable vpx_image_t.r_w/h. This is intended as an improved version of VP9D_GET_DISPLAY_SIZE, which doesn't work with parallel frame decoding. In the encoder, map this to a codec control func (VP9E_SET_RENDER_SIZE) that takes a w/h pair argument in a int[2] (identical to VP9D_GET_DISPLAY_SIZE). Also add render_size to the encoder_param_get_to_decoder unit test. See issue 1030. Change-Id: I12124c13602d832bf4c44090db08c1009c94c7e8 --- test/encode_test_driver.h | 5 +++++ test/vp9_encoder_parms_get_to_decoder.cc | 9 ++++++++- vp10/decoder/decodeframe.c | 6 ++++++ vp10/encoder/encoder.c | 11 +++++++++-- vp10/encoder/encoder.h | 2 ++ vp10/vp10_cx_iface.c | 16 ++++++++++++++++ vp10/vp10_iface_common.h | 4 ++++ vp8/vp8_dx_iface.c | 4 ++-- vp9/decoder/vp9_decodeframe.c | 6 ++++++ vp9/encoder/vp9_encoder.c | 11 +++++++++-- vp9/encoder/vp9_encoder.h | 2 ++ vp9/vp9_cx_iface.c | 16 ++++++++++++++++ vp9/vp9_iface_common.h | 4 ++++ vpx/vp8cx.h | 15 +++++++++++++++ vpx/vpx_image.h | 4 ++++ vpx_scale/yv12config.h | 2 ++ 16 files changed, 110 insertions(+), 7 deletions(-) diff --git a/test/encode_test_driver.h b/test/encode_test_driver.h index 9ecc498..6d0a72f 100644 --- a/test/encode_test_driver.h +++ b/test/encode_test_driver.h @@ -124,6 +124,11 @@ class Encoder { ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); } + void Control(int ctrl_id, int *arg) { + const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg); + ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); + } + void Control(int ctrl_id, struct vpx_scaling_mode *arg) { const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg); ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError(); diff --git a/test/vp9_encoder_parms_get_to_decoder.cc b/test/vp9_encoder_parms_get_to_decoder.cc index 901605d..0984e6a 100644 --- a/test/vp9_encoder_parms_get_to_decoder.cc +++ b/test/vp9_encoder_parms_get_to_decoder.cc @@ -42,6 +42,7 @@ struct EncodeParameters { int32_t frame_parallel; int32_t color_range; vpx_color_space_t cs; + int render_size[2]; // TODO(JBB): quantizers / bitrate }; @@ -49,7 +50,7 @@ const EncodeParameters kVP9EncodeParameterSet[] = { {0, 0, 0, 1, 0, 0, VPX_CS_BT_601}, {0, 0, 0, 0, 0, 1, VPX_CS_BT_709}, {0, 0, 1, 0, 0, 1, VPX_CS_BT_2020}, - {0, 2, 0, 0, 1, 0, VPX_CS_UNKNOWN}, + {0, 2, 0, 0, 1, 0, VPX_CS_UNKNOWN, { 640, 480 }}, // TODO(JBB): Test profiles (requires more work). }; @@ -88,6 +89,8 @@ class VpxEncoderParmsGetToDecoder encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7); encoder->Control(VP8E_SET_ARNR_STRENGTH, 5); encoder->Control(VP8E_SET_ARNR_TYPE, 3); + if (encode_parms.render_size[0] > 0 && encode_parms.render_size[1] > 0) + encoder->Control(VP9E_SET_RENDER_SIZE, encode_parms.render_size); } } @@ -118,6 +121,10 @@ class VpxEncoderParmsGetToDecoder } EXPECT_EQ(encode_parms.color_range, common->color_range); EXPECT_EQ(encode_parms.cs, common->color_space); + if (encode_parms.render_size[0] > 0 && encode_parms.render_size[1] > 0) { + EXPECT_EQ(encode_parms.render_size[0], common->render_width); + EXPECT_EQ(encode_parms.render_size[1], common->render_height); + } EXPECT_EQ(encode_parms.tile_cols, common->log2_tile_cols); EXPECT_EQ(encode_parms.tile_rows, common->log2_tile_rows); diff --git a/vp10/decoder/decodeframe.c b/vp10/decoder/decodeframe.c index 80fac52..91096a2 100644 --- a/vp10/decoder/decodeframe.c +++ b/vp10/decoder/decodeframe.c @@ -1253,6 +1253,8 @@ static void setup_frame_size(VP10_COMMON *cm, struct vpx_read_bit_buffer *rb) { pool->frame_bufs[cm->new_fb_idx].buf.bit_depth = (unsigned int)cm->bit_depth; pool->frame_bufs[cm->new_fb_idx].buf.color_space = cm->color_space; pool->frame_bufs[cm->new_fb_idx].buf.color_range = cm->color_range; + pool->frame_bufs[cm->new_fb_idx].buf.render_width = cm->render_width; + pool->frame_bufs[cm->new_fb_idx].buf.render_height = cm->render_height; } static INLINE int valid_ref_frame_img_fmt(vpx_bit_depth_t ref_bit_depth, @@ -1335,6 +1337,8 @@ static void setup_frame_size_with_refs(VP10_COMMON *cm, pool->frame_bufs[cm->new_fb_idx].buf.bit_depth = (unsigned int)cm->bit_depth; pool->frame_bufs[cm->new_fb_idx].buf.color_space = cm->color_space; pool->frame_bufs[cm->new_fb_idx].buf.color_range = cm->color_range; + pool->frame_bufs[cm->new_fb_idx].buf.render_width = cm->render_width; + pool->frame_bufs[cm->new_fb_idx].buf.render_height = cm->render_height; } static void setup_tile_info(VP10_COMMON *cm, struct vpx_read_bit_buffer *rb) { @@ -1975,6 +1979,8 @@ static size_t read_uncompressed_header(VP10Decoder *pbi, #endif get_frame_new_buffer(cm)->color_space = cm->color_space; get_frame_new_buffer(cm)->color_range = cm->color_range; + get_frame_new_buffer(cm)->render_width = cm->render_width; + get_frame_new_buffer(cm)->render_height = cm->render_height; if (pbi->need_resync) { vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME, diff --git a/vp10/encoder/encoder.c b/vp10/encoder/encoder.c index 33b2789..84c1a8b 100644 --- a/vp10/encoder/encoder.c +++ b/vp10/encoder/encoder.c @@ -1455,8 +1455,13 @@ void vp10_change_config(struct VP10_COMP *cpi, const VP10EncoderConfig *oxcf) { cm->interp_filter = cpi->sf.default_interp_filter; - cm->render_width = cpi->oxcf.width; - cm->render_height = cpi->oxcf.height; + if (cpi->oxcf.render_width > 0 && cpi->oxcf.render_height > 0) { + cm->render_width = cpi->oxcf.render_width; + cm->render_height = cpi->oxcf.render_height; + } else { + cm->render_width = cpi->oxcf.width; + cm->render_height = cpi->oxcf.height; + } cm->width = cpi->oxcf.width; cm->height = cpi->oxcf.height; @@ -3626,6 +3631,8 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi, cm->frame_to_show = get_frame_new_buffer(cm); cm->frame_to_show->color_space = cm->color_space; cm->frame_to_show->color_range = cm->color_range; + cm->frame_to_show->render_width = cm->render_width; + cm->frame_to_show->render_height = cm->render_height; // Pick the loop filter level for the frame. loopfilter_frame(cpi, cm); diff --git a/vp10/encoder/encoder.h b/vp10/encoder/encoder.h index 8ab1efa..6f3f711 100644 --- a/vp10/encoder/encoder.h +++ b/vp10/encoder/encoder.h @@ -229,6 +229,8 @@ typedef struct VP10EncoderConfig { #endif vpx_color_space_t color_space; int color_range; + int render_width; + int render_height; } VP10EncoderConfig; static INLINE int is_lossless_requested(const VP10EncoderConfig *cfg) { diff --git a/vp10/vp10_cx_iface.c b/vp10/vp10_cx_iface.c index 2cb309d..304f74e 100644 --- a/vp10/vp10_cx_iface.c +++ b/vp10/vp10_cx_iface.c @@ -46,6 +46,8 @@ struct vp10_extracfg { vp9e_tune_content content; vpx_color_space_t color_space; int color_range; + int render_width; + int render_height; }; static struct vp10_extracfg default_extra_cfg = { @@ -73,6 +75,8 @@ static struct vp10_extracfg default_extra_cfg = { VP9E_CONTENT_DEFAULT, // content VPX_CS_UNKNOWN, // color space 0, // color range + 0, // render width + 0, // render height }; struct vpx_codec_alg_priv { @@ -402,6 +406,8 @@ static vpx_codec_err_t set_encoder_config( oxcf->color_space = extra_cfg->color_space; oxcf->color_range = extra_cfg->color_range; + oxcf->render_width = extra_cfg->render_width; + oxcf->render_height = extra_cfg->render_height; oxcf->arnr_max_frames = extra_cfg->arnr_max_frames; oxcf->arnr_strength = extra_cfg->arnr_strength; oxcf->min_gf_interval = extra_cfg->min_gf_interval; @@ -1232,6 +1238,15 @@ static vpx_codec_err_t ctrl_set_color_range(vpx_codec_alg_priv_t *ctx, return update_extra_cfg(ctx, &extra_cfg); } +static vpx_codec_err_t ctrl_set_render_size(vpx_codec_alg_priv_t *ctx, + va_list args) { + struct vp10_extracfg extra_cfg = ctx->extra_cfg; + int *const render_size = va_arg(args, int *); + extra_cfg.render_width = render_size[0]; + extra_cfg.render_height = render_size[0]; + return update_extra_cfg(ctx, &extra_cfg); +} + static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = { {VP8_COPY_REFERENCE, ctrl_copy_reference}, {VP8E_UPD_ENTROPY, ctrl_update_entropy}, @@ -1269,6 +1284,7 @@ static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = { {VP9E_SET_NOISE_SENSITIVITY, ctrl_set_noise_sensitivity}, {VP9E_SET_MIN_GF_INTERVAL, ctrl_set_min_gf_interval}, {VP9E_SET_MAX_GF_INTERVAL, ctrl_set_max_gf_interval}, + {VP9E_SET_RENDER_SIZE, ctrl_set_render_size}, // Getters {VP8E_GET_LAST_QUANTIZER, ctrl_get_quantizer}, diff --git a/vp10/vp10_iface_common.h b/vp10/vp10_iface_common.h index 7987d18..b2b4b7d 100644 --- a/vp10/vp10_iface_common.h +++ b/vp10/vp10_iface_common.h @@ -43,6 +43,8 @@ static void yuvconfig2image(vpx_image_t *img, const YV12_BUFFER_CONFIG *yv12, img->h = ALIGN_POWER_OF_TWO(yv12->y_height + 2 * VP9_ENC_BORDER_IN_PIXELS, 3); img->d_w = yv12->y_crop_width; img->d_h = yv12->y_crop_height; + img->r_w = yv12->render_width; + img->r_h = yv12->render_height; img->x_chroma_shift = yv12->subsampling_x; img->y_chroma_shift = yv12->subsampling_y; img->planes[VPX_PLANE_Y] = yv12->y_buffer; @@ -84,6 +86,8 @@ static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img, yv12->y_crop_width = img->d_w; yv12->y_crop_height = img->d_h; + yv12->render_width = img->r_w; + yv12->render_height = img->r_h; yv12->y_width = img->d_w; yv12->y_height = img->d_h; diff --git a/vp8/vp8_dx_iface.c b/vp8/vp8_dx_iface.c index 99e51c4..a12a2ad 100644 --- a/vp8/vp8_dx_iface.c +++ b/vp8/vp8_dx_iface.c @@ -246,8 +246,8 @@ static void yuvconfig2image(vpx_image_t *img, img->fmt = VPX_IMG_FMT_I420; img->w = yv12->y_stride; img->h = (yv12->y_height + 2 * VP8BORDERINPIXELS + 15) & ~15; - img->d_w = yv12->y_width; - img->d_h = yv12->y_height; + img->d_w = img->r_w = yv12->y_width; + img->d_h = img->r_h = yv12->y_height; img->x_chroma_shift = 1; img->y_chroma_shift = 1; img->planes[VPX_PLANE_Y] = yv12->y_buffer; diff --git a/vp9/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c index 0cd1648..fc58a6e 100644 --- a/vp9/decoder/vp9_decodeframe.c +++ b/vp9/decoder/vp9_decodeframe.c @@ -1257,6 +1257,8 @@ static void setup_frame_size(VP9_COMMON *cm, struct vpx_read_bit_buffer *rb) { pool->frame_bufs[cm->new_fb_idx].buf.bit_depth = (unsigned int)cm->bit_depth; pool->frame_bufs[cm->new_fb_idx].buf.color_space = cm->color_space; pool->frame_bufs[cm->new_fb_idx].buf.color_range = cm->color_range; + pool->frame_bufs[cm->new_fb_idx].buf.render_width = cm->render_width; + pool->frame_bufs[cm->new_fb_idx].buf.render_height = cm->render_height; } static INLINE int valid_ref_frame_img_fmt(vpx_bit_depth_t ref_bit_depth, @@ -1339,6 +1341,8 @@ static void setup_frame_size_with_refs(VP9_COMMON *cm, pool->frame_bufs[cm->new_fb_idx].buf.bit_depth = (unsigned int)cm->bit_depth; pool->frame_bufs[cm->new_fb_idx].buf.color_space = cm->color_space; pool->frame_bufs[cm->new_fb_idx].buf.color_range = cm->color_range; + pool->frame_bufs[cm->new_fb_idx].buf.render_width = cm->render_width; + pool->frame_bufs[cm->new_fb_idx].buf.render_height = cm->render_height; } static void setup_tile_info(VP9_COMMON *cm, struct vpx_read_bit_buffer *rb) { @@ -1948,6 +1952,8 @@ static size_t read_uncompressed_header(VP9Decoder *pbi, #endif get_frame_new_buffer(cm)->color_space = cm->color_space; get_frame_new_buffer(cm)->color_range = cm->color_range; + get_frame_new_buffer(cm)->render_width = cm->render_width; + get_frame_new_buffer(cm)->render_height = cm->render_height; if (pbi->need_resync) { vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME, diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 060c25f..3f4efae 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -1509,8 +1509,13 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) { cm->interp_filter = cpi->sf.default_interp_filter; - cm->render_width = cpi->oxcf.width; - cm->render_height = cpi->oxcf.height; + if (cpi->oxcf.render_width > 0 && cpi->oxcf.render_height > 0) { + cm->render_width = cpi->oxcf.render_width; + cm->render_height = cpi->oxcf.render_height; + } else { + cm->render_width = cpi->oxcf.width; + cm->render_height = cpi->oxcf.height; + } if (last_w != cpi->oxcf.width || last_h != cpi->oxcf.height) { cm->width = cpi->oxcf.width; cm->height = cpi->oxcf.height; @@ -3823,6 +3828,8 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi, cm->frame_to_show = get_frame_new_buffer(cm); cm->frame_to_show->color_space = cm->color_space; cm->frame_to_show->color_range = cm->color_range; + cm->frame_to_show->render_width = cm->render_width; + cm->frame_to_show->render_height = cm->render_height; // Pick the loop filter level for the frame. loopfilter_frame(cpi, cm); diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h index b50f2fb..174e2b4 100644 --- a/vp9/encoder/vp9_encoder.h +++ b/vp9/encoder/vp9_encoder.h @@ -239,6 +239,8 @@ typedef struct VP9EncoderConfig { #endif vpx_color_space_t color_space; int color_range; + int render_width; + int render_height; VP9E_TEMPORAL_LAYERING_MODE temporal_layering_mode; } VP9EncoderConfig; diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index aea1a5f..a253c06 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -46,6 +46,8 @@ struct vp9_extracfg { vp9e_tune_content content; vpx_color_space_t color_space; int color_range; + int render_width; + int render_height; }; static struct vp9_extracfg default_extra_cfg = { @@ -73,6 +75,8 @@ static struct vp9_extracfg default_extra_cfg = { VP9E_CONTENT_DEFAULT, // content VPX_CS_UNKNOWN, // color space 0, // color range + 0, // render width + 0, // render height }; struct vpx_codec_alg_priv { @@ -469,6 +473,8 @@ static vpx_codec_err_t set_encoder_config( oxcf->color_space = extra_cfg->color_space; oxcf->color_range = extra_cfg->color_range; + oxcf->render_width = extra_cfg->render_width; + oxcf->render_height = extra_cfg->render_height; oxcf->arnr_max_frames = extra_cfg->arnr_max_frames; oxcf->arnr_strength = extra_cfg->arnr_strength; oxcf->min_gf_interval = extra_cfg->min_gf_interval; @@ -1461,6 +1467,15 @@ static vpx_codec_err_t ctrl_set_color_range(vpx_codec_alg_priv_t *ctx, return update_extra_cfg(ctx, &extra_cfg); } +static vpx_codec_err_t ctrl_set_render_size(vpx_codec_alg_priv_t *ctx, + va_list args) { + struct vp9_extracfg extra_cfg = ctx->extra_cfg; + int *const render_size = va_arg(args, int *); + extra_cfg.render_width = render_size[0]; + extra_cfg.render_height = render_size[1]; + return update_extra_cfg(ctx, &extra_cfg); +} + static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = { {VP8_COPY_REFERENCE, ctrl_copy_reference}, {VP8E_UPD_ENTROPY, ctrl_update_entropy}, @@ -1502,6 +1517,7 @@ static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = { {VP9E_SET_MIN_GF_INTERVAL, ctrl_set_min_gf_interval}, {VP9E_SET_MAX_GF_INTERVAL, ctrl_set_max_gf_interval}, {VP9E_SET_SVC_REF_FRAME_CONFIG, ctrl_set_svc_ref_frame_config}, + {VP9E_SET_RENDER_SIZE, ctrl_set_render_size}, // Getters {VP8E_GET_LAST_QUANTIZER, ctrl_get_quantizer}, diff --git a/vp9/vp9_iface_common.h b/vp9/vp9_iface_common.h index 7d514ba..938d422 100644 --- a/vp9/vp9_iface_common.h +++ b/vp9/vp9_iface_common.h @@ -43,6 +43,8 @@ static void yuvconfig2image(vpx_image_t *img, const YV12_BUFFER_CONFIG *yv12, img->h = ALIGN_POWER_OF_TWO(yv12->y_height + 2 * VP9_ENC_BORDER_IN_PIXELS, 3); img->d_w = yv12->y_crop_width; img->d_h = yv12->y_crop_height; + img->r_w = yv12->render_width; + img->r_h = yv12->render_height; img->x_chroma_shift = yv12->subsampling_x; img->y_chroma_shift = yv12->subsampling_y; img->planes[VPX_PLANE_Y] = yv12->y_buffer; @@ -84,6 +86,8 @@ static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img, yv12->y_crop_width = img->d_w; yv12->y_crop_height = img->d_h; + yv12->render_width = img->r_w; + yv12->render_height = img->r_h; yv12->y_width = img->d_w; yv12->y_height = img->d_h; diff --git a/vpx/vp8cx.h b/vpx/vp8cx.h index a437ac9..69b8d3e 100644 --- a/vpx/vp8cx.h +++ b/vpx/vp8cx.h @@ -564,6 +564,14 @@ enum vp8e_enc_control_id { * Supported in codecs: VP9 */ VP9E_SET_SVC_REF_FRAME_CONFIG, + + /*!\brief Codec control function to set intended rendering image size. + * + * By default, this is identical to the image size in pixels. + * + * Supported in codecs: VP9 + */ + VP9E_SET_RENDER_SIZE, }; /*!\brief vpx 1-D scaling mode @@ -798,6 +806,13 @@ VPX_CTRL_USE_TYPE(VP9E_GET_ACTIVEMAP, vpx_active_map_t *) VPX_CTRL_USE_TYPE(VP9E_SET_COLOR_RANGE, int) VPX_CTRL_USE_TYPE(VP9E_SET_SVC_REF_FRAME_CONFIG, vpx_svc_ref_frame_config_t *) + +/*!\brief + * + * TODO(rbultje) : add support of the control in ffmpeg + */ +#define VPX_CTRL_VP9E_SET_RENDER_SIZE +VPX_CTRL_USE_TYPE(VP9E_SET_RENDER_SIZE, int *) /*! @} - end defgroup vp8_encoder */ #ifdef __cplusplus } // extern "C" diff --git a/vpx/vpx_image.h b/vpx/vpx_image.h index be93147..5110059 100644 --- a/vpx/vpx_image.h +++ b/vpx/vpx_image.h @@ -93,6 +93,10 @@ extern "C" { unsigned int d_w; /**< Displayed image width */ unsigned int d_h; /**< Displayed image height */ + /* Image intended rendering dimensions */ + unsigned int r_w; /**< Intended rendering image width */ + unsigned int r_h; /**< Intended rendering image height */ + /* Chroma subsampling info */ unsigned int x_chroma_shift; /**< subsampling order, X */ unsigned int y_chroma_shift; /**< subsampling order, Y */ diff --git a/vpx_scale/yv12config.h b/vpx_scale/yv12config.h index 2e12ace..3a04452 100644 --- a/vpx_scale/yv12config.h +++ b/vpx_scale/yv12config.h @@ -57,6 +57,8 @@ typedef struct yv12_buffer_config { unsigned int bit_depth; vpx_color_space_t color_space; int color_range; + int render_width; + int render_height; int corrupted; int flags; -- 2.7.4