Commit e94b415c authored by Yaowu Xu's avatar Yaowu Xu

Add encoder control for setting color space

This commit adds encoder side control for vp9 to set color space info
in the output compressed bitstream.

It also amends the "vp9_encoder_params_get_to_decoder" test to verify
the correct color space information is passed from the encoder end to
decoder end.

Change-Id: Ibf5fba2edcb2a8dc37557f6fae5c7816efa52650
parent afae733e
...@@ -65,14 +65,15 @@ struct EncodeParameters { ...@@ -65,14 +65,15 @@ struct EncodeParameters {
int32_t lossless; int32_t lossless;
int32_t error_resilient; int32_t error_resilient;
int32_t frame_parallel; int32_t frame_parallel;
vpx_color_space_t cs;
// TODO(JBB): quantizers / bitrate // TODO(JBB): quantizers / bitrate
}; };
const EncodeParameters kVP9EncodeParameterSet[] = { const EncodeParameters kVP9EncodeParameterSet[] = {
{0, 0, 0, 1, 0}, {0, 0, 0, 1, 0, VPX_CS_BT_601},
{0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, VPX_CS_BT_709},
{0, 0, 1, 0, 0}, {0, 0, 1, 0, 0, VPX_CS_BT_2020},
{0, 2, 0, 0, 1}, {0, 2, 0, 0, 1, VPX_CS_UNKNOWN},
// TODO(JBB): Test profiles (requires more work). // TODO(JBB): Test profiles (requires more work).
}; };
...@@ -109,6 +110,7 @@ class Vp9EncoderParmsGetToDecoder ...@@ -109,6 +110,7 @@ class Vp9EncoderParmsGetToDecoder
virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video, virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
::libvpx_test::Encoder *encoder) { ::libvpx_test::Encoder *encoder) {
if (video->frame() == 1) { if (video->frame() == 1) {
encoder->Control(VP9E_SET_COLOR_SPACE, encode_parms.cs);
encoder->Control(VP9E_SET_LOSSLESS, encode_parms.lossless); encoder->Control(VP9E_SET_LOSSLESS, encode_parms.lossless);
encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING, encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING,
encode_parms.frame_parallel); encode_parms.frame_parallel);
...@@ -147,7 +149,7 @@ class Vp9EncoderParmsGetToDecoder ...@@ -147,7 +149,7 @@ class Vp9EncoderParmsGetToDecoder
EXPECT_EQ(common->frame_parallel_decoding_mode, EXPECT_EQ(common->frame_parallel_decoding_mode,
encode_parms.frame_parallel); encode_parms.frame_parallel);
} }
EXPECT_EQ(common->color_space, encode_parms.cs);
EXPECT_EQ(common->log2_tile_cols, encode_parms.tile_cols); EXPECT_EQ(common->log2_tile_cols, encode_parms.tile_cols);
EXPECT_EQ(common->log2_tile_rows, encode_parms.tile_rows); EXPECT_EQ(common->log2_tile_rows, encode_parms.tile_rows);
......
...@@ -98,17 +98,6 @@ typedef enum { ...@@ -98,17 +98,6 @@ typedef enum {
TX_TYPES = 4 TX_TYPES = 4
} TX_TYPE; } TX_TYPE;
typedef enum {
UNKNOWN = 0,
BT_601 = 1, // YUV
BT_709 = 2, // YUV
SMPTE_170 = 3, // YUV
SMPTE_240 = 4, // YUV
BT_2020 = 5, // YUV
RESERVED_2 = 6,
SRGB = 7 // RGB
} COLOR_SPACE;
typedef enum { typedef enum {
VP9_LAST_FLAG = 1 << 0, VP9_LAST_FLAG = 1 << 0,
VP9_GOLD_FLAG = 1 << 1, VP9_GOLD_FLAG = 1 << 1,
......
...@@ -76,7 +76,7 @@ typedef struct VP9Common { ...@@ -76,7 +76,7 @@ typedef struct VP9Common {
DECLARE_ALIGNED(16, int16_t, y_dequant[QINDEX_RANGE][8]); DECLARE_ALIGNED(16, int16_t, y_dequant[QINDEX_RANGE][8]);
DECLARE_ALIGNED(16, int16_t, uv_dequant[QINDEX_RANGE][8]); DECLARE_ALIGNED(16, int16_t, uv_dequant[QINDEX_RANGE][8]);
COLOR_SPACE color_space; vpx_color_space_t color_space;
int width; int width;
int height; int height;
......
...@@ -1227,8 +1227,8 @@ static void read_bitdepth_colorspace_sampling( ...@@ -1227,8 +1227,8 @@ static void read_bitdepth_colorspace_sampling(
cm->use_highbitdepth = 0; cm->use_highbitdepth = 0;
#endif #endif
} }
cm->color_space = (COLOR_SPACE)vp9_rb_read_literal(rb, 3); cm->color_space = vp9_rb_read_literal(rb, 3);
if (cm->color_space != SRGB) { if (cm->color_space != VPX_CS_SRGB) {
vp9_rb_read_bit(rb); // [16,235] (including xvycc) vs [0,255] range vp9_rb_read_bit(rb); // [16,235] (including xvycc) vs [0,255] range
if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) { if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) {
cm->subsampling_x = vp9_rb_read_bit(rb); cm->subsampling_x = vp9_rb_read_bit(rb);
...@@ -1328,7 +1328,7 @@ static size_t read_uncompressed_header(VP9Decoder *pbi, ...@@ -1328,7 +1328,7 @@ static size_t read_uncompressed_header(VP9Decoder *pbi,
// of either the color format or color sub-sampling in profile 0. VP9 // of either the color format or color sub-sampling in profile 0. VP9
// specifies that the default color format should be YUV 4:2:0 in this // specifies that the default color format should be YUV 4:2:0 in this
// case (normative). // case (normative).
cm->color_space = BT_601; cm->color_space = VPX_CS_BT_601;
cm->subsampling_y = cm->subsampling_x = 1; cm->subsampling_y = cm->subsampling_x = 1;
cm->bit_depth = VPX_BITS_8; cm->bit_depth = VPX_BITS_8;
#if CONFIG_VP9_HIGHBITDEPTH #if CONFIG_VP9_HIGHBITDEPTH
......
...@@ -1055,7 +1055,7 @@ static void write_bitdepth_colorspace_sampling( ...@@ -1055,7 +1055,7 @@ static void write_bitdepth_colorspace_sampling(
vp9_wb_write_bit(wb, cm->bit_depth == VPX_BITS_10 ? 0 : 1); vp9_wb_write_bit(wb, cm->bit_depth == VPX_BITS_10 ? 0 : 1);
} }
vp9_wb_write_literal(wb, cm->color_space, 3); vp9_wb_write_literal(wb, cm->color_space, 3);
if (cm->color_space != SRGB) { if (cm->color_space != VPX_CS_SRGB) {
vp9_wb_write_bit(wb, 0); // 0: [16, 235] (i.e. xvYCC), 1: [0, 255] vp9_wb_write_bit(wb, 0); // 0: [16, 235] (i.e. xvYCC), 1: [0, 255]
if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) { if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) {
assert(cm->subsampling_x != 1 || cm->subsampling_y != 1); assert(cm->subsampling_x != 1 || cm->subsampling_y != 1);
......
...@@ -1264,6 +1264,7 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) { ...@@ -1264,6 +1264,7 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) {
if (cm->profile != oxcf->profile) if (cm->profile != oxcf->profile)
cm->profile = oxcf->profile; cm->profile = oxcf->profile;
cm->bit_depth = oxcf->bit_depth; cm->bit_depth = oxcf->bit_depth;
cm->color_space = oxcf->color_space;
if (cm->profile <= PROFILE_1) if (cm->profile <= PROFILE_1)
assert(cm->bit_depth == VPX_BITS_8); assert(cm->bit_depth == VPX_BITS_8);
......
...@@ -231,7 +231,7 @@ typedef struct VP9EncoderConfig { ...@@ -231,7 +231,7 @@ typedef struct VP9EncoderConfig {
#if CONFIG_VP9_HIGHBITDEPTH #if CONFIG_VP9_HIGHBITDEPTH
int use_highbitdepth; int use_highbitdepth;
#endif #endif
COLOR_SPACE color_space; vpx_color_space_t color_space;
} VP9EncoderConfig; } VP9EncoderConfig;
static INLINE int is_lossless_requested(const VP9EncoderConfig *cfg) { static INLINE int is_lossless_requested(const VP9EncoderConfig *cfg) {
......
...@@ -41,8 +41,8 @@ struct vp9_extracfg { ...@@ -41,8 +41,8 @@ struct vp9_extracfg {
AQ_MODE aq_mode; AQ_MODE aq_mode;
unsigned int frame_periodic_boost; unsigned int frame_periodic_boost;
vpx_bit_depth_t bit_depth; vpx_bit_depth_t bit_depth;
COLOR_SPACE color_space;
vp9e_tune_content content; vp9e_tune_content content;
vpx_color_space_t color_space;
}; };
static struct vp9_extracfg default_extra_cfg = { static struct vp9_extracfg default_extra_cfg = {
...@@ -65,8 +65,8 @@ static struct vp9_extracfg default_extra_cfg = { ...@@ -65,8 +65,8 @@ static struct vp9_extracfg default_extra_cfg = {
NO_AQ, // aq_mode NO_AQ, // aq_mode
0, // frame_periodic_delta_q 0, // frame_periodic_delta_q
VPX_BITS_8, // Bit depth VPX_BITS_8, // Bit depth
UNKNOWN, // Color Space VP9E_CONTENT_DEFAULT, // content
VP9E_CONTENT_DEFAULT // content VPX_CS_UNKNOWN, // color space
}; };
struct vpx_codec_alg_priv { struct vpx_codec_alg_priv {
...@@ -296,7 +296,7 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx, ...@@ -296,7 +296,7 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
cfg->g_bit_depth == VPX_BITS_8) { cfg->g_bit_depth == VPX_BITS_8) {
ERROR("Codec bit-depth 8 not supported in profile > 1"); ERROR("Codec bit-depth 8 not supported in profile > 1");
} }
RANGE_CHECK(extra_cfg, color_space, UNKNOWN, SRGB); RANGE_CHECK(extra_cfg, color_space, VPX_CS_UNKNOWN, VPX_CS_SRGB);
return VPX_CODEC_OK; return VPX_CODEC_OK;
} }
...@@ -1325,6 +1325,13 @@ static vpx_codec_err_t ctrl_set_tune_content(vpx_codec_alg_priv_t *ctx, ...@@ -1325,6 +1325,13 @@ static vpx_codec_err_t ctrl_set_tune_content(vpx_codec_alg_priv_t *ctx,
return update_extra_cfg(ctx, &extra_cfg); return update_extra_cfg(ctx, &extra_cfg);
} }
static vpx_codec_err_t ctrl_set_color_space(vpx_codec_alg_priv_t *ctx,
va_list args) {
struct vp9_extracfg extra_cfg = ctx->extra_cfg;
extra_cfg.color_space = CAST(VP9E_SET_COLOR_SPACE, args);
return update_extra_cfg(ctx, &extra_cfg);
}
static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = { static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
{VP8_COPY_REFERENCE, ctrl_copy_reference}, {VP8_COPY_REFERENCE, ctrl_copy_reference},
{VP8E_UPD_ENTROPY, ctrl_update_entropy}, {VP8E_UPD_ENTROPY, ctrl_update_entropy},
...@@ -1360,6 +1367,7 @@ static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = { ...@@ -1360,6 +1367,7 @@ static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
{VP9E_REGISTER_CX_CALLBACK, ctrl_register_cx_callback}, {VP9E_REGISTER_CX_CALLBACK, ctrl_register_cx_callback},
{VP9E_SET_SVC_LAYER_ID, ctrl_set_svc_layer_id}, {VP9E_SET_SVC_LAYER_ID, ctrl_set_svc_layer_id},
{VP9E_SET_TUNE_CONTENT, ctrl_set_tune_content}, {VP9E_SET_TUNE_CONTENT, ctrl_set_tune_content},
{VP9E_SET_COLOR_SPACE, ctrl_set_color_space},
{VP9E_SET_NOISE_SENSITIVITY, ctrl_set_noise_sensitivity}, {VP9E_SET_NOISE_SENSITIVITY, ctrl_set_noise_sensitivity},
// Getters // Getters
......
...@@ -259,6 +259,19 @@ enum vp8e_enc_control_id { ...@@ -259,6 +259,19 @@ enum vp8e_enc_control_id {
VP9E_SET_TUNE_CONTENT, VP9E_SET_TUNE_CONTENT,
VP9E_GET_SVC_LAYER_ID, VP9E_GET_SVC_LAYER_ID,
VP9E_REGISTER_CX_CALLBACK, VP9E_REGISTER_CX_CALLBACK,
/*!\brief control function to set color space info.
* \note Valid ranges: 0..7, default is "UNKNOWN".
* 0 = UNKNOWN,
* 1 = BT_601
* 2 = BT_709
* 3 = SMPTE_170
* 4 = SMPTE_240
* 5 = BT_2020
* 6 = RESERVED
* 7 = SRGB
*/
VP9E_SET_COLOR_SPACE,
}; };
/*!\brief vpx 1-D scaling mode /*!\brief vpx 1-D scaling mode
...@@ -423,6 +436,8 @@ VPX_CTRL_USE_TYPE(VP9E_SET_FRAME_PERIODIC_BOOST, unsigned int) ...@@ -423,6 +436,8 @@ VPX_CTRL_USE_TYPE(VP9E_SET_FRAME_PERIODIC_BOOST, unsigned int)
VPX_CTRL_USE_TYPE(VP9E_SET_NOISE_SENSITIVITY, unsigned int) VPX_CTRL_USE_TYPE(VP9E_SET_NOISE_SENSITIVITY, unsigned int)
VPX_CTRL_USE_TYPE(VP9E_SET_TUNE_CONTENT, int) /* vp9e_tune_content */ VPX_CTRL_USE_TYPE(VP9E_SET_TUNE_CONTENT, int) /* vp9e_tune_content */
VPX_CTRL_USE_TYPE(VP9E_SET_COLOR_SPACE, int)
/*! @} - end defgroup vp8_encoder */ /*! @} - end defgroup vp8_encoder */
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
......
...@@ -442,7 +442,7 @@ static const int vp9_arg_ctrl_map[] = { ...@@ -442,7 +442,7 @@ static const int vp9_arg_ctrl_map[] = {
VP8E_SET_MAX_INTER_BITRATE_PCT, VP8E_SET_GF_CBR_BOOST_PCT, VP8E_SET_MAX_INTER_BITRATE_PCT, VP8E_SET_GF_CBR_BOOST_PCT,
VP9E_SET_LOSSLESS, VP9E_SET_FRAME_PARALLEL_DECODING, VP9E_SET_AQ_MODE, VP9E_SET_LOSSLESS, VP9E_SET_FRAME_PARALLEL_DECODING, VP9E_SET_AQ_MODE,
VP9E_SET_FRAME_PERIODIC_BOOST, VP9E_SET_NOISE_SENSITIVITY, VP9E_SET_FRAME_PERIODIC_BOOST, VP9E_SET_NOISE_SENSITIVITY,
VP9E_SET_TUNE_CONTENT, VP9E_SET_TUNE_CONTENT, VP9E_SET_COLOR_SPACE,
0 0
}; };
#endif #endif
......
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