Add support for color-range.

In decoder, export (eventually) into vpx_image_t.range field. In
encoder, use oxcf->color_range to set it (same way as for
color_space).

See issue 1059.

Change-Id: Ieabbb2a785fa58cc4044bd54eee66f328f3906ce
This commit is contained in:
Ronald S. Bultje 2015-09-15 21:56:51 -04:00
parent e562c71783
commit eeb5ef0a24
18 changed files with 80 additions and 8 deletions

View File

@ -40,15 +40,16 @@ struct EncodeParameters {
int32_t lossless; int32_t lossless;
int32_t error_resilient; int32_t error_resilient;
int32_t frame_parallel; int32_t frame_parallel;
int32_t color_range;
vpx_color_space_t cs; vpx_color_space_t cs;
// TODO(JBB): quantizers / bitrate // TODO(JBB): quantizers / bitrate
}; };
const EncodeParameters kVP9EncodeParameterSet[] = { const EncodeParameters kVP9EncodeParameterSet[] = {
{0, 0, 0, 1, 0, VPX_CS_BT_601}, {0, 0, 0, 1, 0, 0, VPX_CS_BT_601},
{0, 0, 0, 0, 0, VPX_CS_BT_709}, {0, 0, 0, 0, 0, 1, VPX_CS_BT_709},
{0, 0, 1, 0, 0, VPX_CS_BT_2020}, {0, 0, 1, 0, 0, 1, VPX_CS_BT_2020},
{0, 2, 0, 0, 1, VPX_CS_UNKNOWN}, {0, 2, 0, 0, 1, 0, VPX_CS_UNKNOWN},
// TODO(JBB): Test profiles (requires more work). // TODO(JBB): Test profiles (requires more work).
}; };
@ -76,6 +77,7 @@ class VpxEncoderParmsGetToDecoder
::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_COLOR_SPACE, encode_parms.cs);
encoder->Control(VP9E_SET_COLOR_RANGE, encode_parms.color_range);
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);
@ -114,6 +116,7 @@ class VpxEncoderParmsGetToDecoder
EXPECT_EQ(encode_parms.frame_parallel, EXPECT_EQ(encode_parms.frame_parallel,
common->frame_parallel_decoding_mode); common->frame_parallel_decoding_mode);
} }
EXPECT_EQ(encode_parms.color_range, common->color_range);
EXPECT_EQ(encode_parms.cs, common->color_space); EXPECT_EQ(encode_parms.cs, common->color_space);
EXPECT_EQ(encode_parms.tile_cols, common->log2_tile_cols); EXPECT_EQ(encode_parms.tile_cols, common->log2_tile_cols);
EXPECT_EQ(encode_parms.tile_rows, common->log2_tile_rows); EXPECT_EQ(encode_parms.tile_rows, common->log2_tile_rows);

View File

@ -129,6 +129,7 @@ typedef struct BufferPool {
typedef struct VP10Common { typedef struct VP10Common {
struct vpx_internal_error_info error; struct vpx_internal_error_info error;
vpx_color_space_t color_space; vpx_color_space_t color_space;
int color_range;
int width; int width;
int height; int height;
int display_width; int display_width;

View File

@ -1228,6 +1228,7 @@ static void setup_frame_size(VP10_COMMON *cm, struct vpx_read_bit_buffer *rb) {
pool->frame_bufs[cm->new_fb_idx].buf.subsampling_y = cm->subsampling_y; pool->frame_bufs[cm->new_fb_idx].buf.subsampling_y = cm->subsampling_y;
pool->frame_bufs[cm->new_fb_idx].buf.bit_depth = (unsigned int)cm->bit_depth; 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_space = cm->color_space;
pool->frame_bufs[cm->new_fb_idx].buf.color_range = cm->color_range;
} }
static INLINE int valid_ref_frame_img_fmt(vpx_bit_depth_t ref_bit_depth, static INLINE int valid_ref_frame_img_fmt(vpx_bit_depth_t ref_bit_depth,
@ -1309,6 +1310,7 @@ static void setup_frame_size_with_refs(VP10_COMMON *cm,
pool->frame_bufs[cm->new_fb_idx].buf.subsampling_y = cm->subsampling_y; pool->frame_bufs[cm->new_fb_idx].buf.subsampling_y = cm->subsampling_y;
pool->frame_bufs[cm->new_fb_idx].buf.bit_depth = (unsigned int)cm->bit_depth; 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_space = cm->color_space;
pool->frame_bufs[cm->new_fb_idx].buf.color_range = cm->color_range;
} }
static void setup_tile_info(VP10_COMMON *cm, struct vpx_read_bit_buffer *rb) { static void setup_tile_info(VP10_COMMON *cm, struct vpx_read_bit_buffer *rb) {
@ -1749,7 +1751,8 @@ static void read_bitdepth_colorspace_sampling(
} }
cm->color_space = vpx_rb_read_literal(rb, 3); cm->color_space = vpx_rb_read_literal(rb, 3);
if (cm->color_space != VPX_CS_SRGB) { if (cm->color_space != VPX_CS_SRGB) {
vpx_rb_read_bit(rb); // [16,235] (including xvycc) vs [0,255] range // [16,235] (including xvycc) vs [0,255] range
cm->color_range = vpx_rb_read_bit(rb);
if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) { if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) {
cm->subsampling_x = vpx_rb_read_bit(rb); cm->subsampling_x = vpx_rb_read_bit(rb);
cm->subsampling_y = vpx_rb_read_bit(rb); cm->subsampling_y = vpx_rb_read_bit(rb);
@ -1893,6 +1896,7 @@ static size_t read_uncompressed_header(VP10Decoder *pbi,
// 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 = VPX_CS_BT_601; cm->color_space = VPX_CS_BT_601;
cm->color_range = 0;
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
@ -1943,6 +1947,7 @@ static size_t read_uncompressed_header(VP10Decoder *pbi,
get_frame_new_buffer(cm)->bit_depth = cm->bit_depth; get_frame_new_buffer(cm)->bit_depth = cm->bit_depth;
#endif #endif
get_frame_new_buffer(cm)->color_space = cm->color_space; get_frame_new_buffer(cm)->color_space = cm->color_space;
get_frame_new_buffer(cm)->color_range = cm->color_range;
if (pbi->need_resync) { if (pbi->need_resync) {
vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME, vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME,

View File

@ -1055,7 +1055,8 @@ static void write_bitdepth_colorspace_sampling(
} }
vpx_wb_write_literal(wb, cm->color_space, 3); vpx_wb_write_literal(wb, cm->color_space, 3);
if (cm->color_space != VPX_CS_SRGB) { if (cm->color_space != VPX_CS_SRGB) {
vpx_wb_write_bit(wb, 0); // 0: [16, 235] (i.e. xvYCC), 1: [0, 255] // 0: [16, 235] (i.e. xvYCC), 1: [0, 255]
vpx_wb_write_bit(wb, cm->color_range);
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);
vpx_wb_write_bit(wb, cm->subsampling_x); vpx_wb_write_bit(wb, cm->subsampling_x);

View File

@ -735,6 +735,7 @@ static void init_config(struct VP10_COMP *cpi, VP10EncoderConfig *oxcf) {
cm->use_highbitdepth = oxcf->use_highbitdepth; cm->use_highbitdepth = oxcf->use_highbitdepth;
#endif #endif
cm->color_space = oxcf->color_space; cm->color_space = oxcf->color_space;
cm->color_range = oxcf->color_range;
cm->width = oxcf->width; cm->width = oxcf->width;
cm->height = oxcf->height; cm->height = oxcf->height;
@ -1406,6 +1407,7 @@ void vp10_change_config(struct VP10_COMP *cpi, const VP10EncoderConfig *oxcf) {
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; cm->color_space = oxcf->color_space;
cm->color_range = oxcf->color_range;
if (cm->profile <= PROFILE_1) if (cm->profile <= PROFILE_1)
assert(cm->bit_depth == VPX_BITS_8); assert(cm->bit_depth == VPX_BITS_8);
@ -3624,6 +3626,7 @@ static void encode_frame_to_data_rate(VP10_COMP *cpi,
cm->frame_to_show = get_frame_new_buffer(cm); cm->frame_to_show = get_frame_new_buffer(cm);
cm->frame_to_show->color_space = cm->color_space; cm->frame_to_show->color_space = cm->color_space;
cm->frame_to_show->color_range = cm->color_range;
// Pick the loop filter level for the frame. // Pick the loop filter level for the frame.
loopfilter_frame(cpi, cm); loopfilter_frame(cpi, cm);

View File

@ -228,6 +228,7 @@ typedef struct VP10EncoderConfig {
int use_highbitdepth; int use_highbitdepth;
#endif #endif
vpx_color_space_t color_space; vpx_color_space_t color_space;
int color_range;
} VP10EncoderConfig; } VP10EncoderConfig;
static INLINE int is_lossless_requested(const VP10EncoderConfig *cfg) { static INLINE int is_lossless_requested(const VP10EncoderConfig *cfg) {

View File

@ -45,6 +45,7 @@ struct vp10_extracfg {
vpx_bit_depth_t bit_depth; vpx_bit_depth_t bit_depth;
vp9e_tune_content content; vp9e_tune_content content;
vpx_color_space_t color_space; vpx_color_space_t color_space;
int color_range;
}; };
static struct vp10_extracfg default_extra_cfg = { static struct vp10_extracfg default_extra_cfg = {
@ -71,6 +72,7 @@ static struct vp10_extracfg default_extra_cfg = {
VPX_BITS_8, // Bit depth VPX_BITS_8, // Bit depth
VP9E_CONTENT_DEFAULT, // content VP9E_CONTENT_DEFAULT, // content
VPX_CS_UNKNOWN, // color space VPX_CS_UNKNOWN, // color space
0, // color range
}; };
struct vpx_codec_alg_priv { struct vpx_codec_alg_priv {
@ -255,6 +257,7 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
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, VPX_CS_UNKNOWN, VPX_CS_SRGB); RANGE_CHECK(extra_cfg, color_space, VPX_CS_UNKNOWN, VPX_CS_SRGB);
RANGE_CHECK(extra_cfg, color_range, 0, 1);
return VPX_CODEC_OK; return VPX_CODEC_OK;
} }
@ -398,6 +401,7 @@ static vpx_codec_err_t set_encoder_config(
#endif #endif
oxcf->color_space = extra_cfg->color_space; oxcf->color_space = extra_cfg->color_space;
oxcf->color_range = extra_cfg->color_range;
oxcf->arnr_max_frames = extra_cfg->arnr_max_frames; oxcf->arnr_max_frames = extra_cfg->arnr_max_frames;
oxcf->arnr_strength = extra_cfg->arnr_strength; oxcf->arnr_strength = extra_cfg->arnr_strength;
oxcf->min_gf_interval = extra_cfg->min_gf_interval; oxcf->min_gf_interval = extra_cfg->min_gf_interval;
@ -1221,6 +1225,13 @@ static vpx_codec_err_t ctrl_set_color_space(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_range(vpx_codec_alg_priv_t *ctx,
va_list args) {
struct vp10_extracfg extra_cfg = ctx->extra_cfg;
extra_cfg.color_range = CAST(VP9E_SET_COLOR_RANGE, 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},
@ -1254,6 +1265,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_TUNE_CONTENT, ctrl_set_tune_content}, {VP9E_SET_TUNE_CONTENT, ctrl_set_tune_content},
{VP9E_SET_COLOR_SPACE, ctrl_set_color_space}, {VP9E_SET_COLOR_SPACE, ctrl_set_color_space},
{VP9E_SET_COLOR_RANGE, ctrl_set_color_range},
{VP9E_SET_NOISE_SENSITIVITY, ctrl_set_noise_sensitivity}, {VP9E_SET_NOISE_SENSITIVITY, ctrl_set_noise_sensitivity},
{VP9E_SET_MIN_GF_INTERVAL, ctrl_set_min_gf_interval}, {VP9E_SET_MIN_GF_INTERVAL, ctrl_set_min_gf_interval},
{VP9E_SET_MAX_GF_INTERVAL, ctrl_set_max_gf_interval}, {VP9E_SET_MAX_GF_INTERVAL, ctrl_set_max_gf_interval},

View File

@ -37,6 +37,7 @@ static void yuvconfig2image(vpx_image_t *img, const YV12_BUFFER_CONFIG *yv12,
} }
} }
img->cs = yv12->color_space; img->cs = yv12->color_space;
img->range = yv12->color_range;
img->bit_depth = 8; img->bit_depth = 8;
img->w = yv12->y_stride; img->w = yv12->y_stride;
img->h = ALIGN_POWER_OF_TWO(yv12->y_height + 2 * VP9_ENC_BORDER_IN_PIXELS, 3); img->h = ALIGN_POWER_OF_TWO(yv12->y_height + 2 * VP9_ENC_BORDER_IN_PIXELS, 3);
@ -96,6 +97,7 @@ static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img,
yv12->y_stride = img->stride[VPX_PLANE_Y]; yv12->y_stride = img->stride[VPX_PLANE_Y];
yv12->uv_stride = img->stride[VPX_PLANE_U]; yv12->uv_stride = img->stride[VPX_PLANE_U];
yv12->color_space = img->cs; yv12->color_space = img->cs;
yv12->color_range = img->range;
#if CONFIG_VP9_HIGHBITDEPTH #if CONFIG_VP9_HIGHBITDEPTH
if (img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) { if (img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) {

View File

@ -112,6 +112,7 @@ typedef struct BufferPool {
typedef struct VP9Common { typedef struct VP9Common {
struct vpx_internal_error_info error; struct vpx_internal_error_info error;
vpx_color_space_t color_space; vpx_color_space_t color_space;
int color_range;
int width; int width;
int height; int height;
int display_width; int display_width;

View File

@ -1256,6 +1256,7 @@ static void setup_frame_size(VP9_COMMON *cm, struct vpx_read_bit_buffer *rb) {
pool->frame_bufs[cm->new_fb_idx].buf.subsampling_y = cm->subsampling_y; pool->frame_bufs[cm->new_fb_idx].buf.subsampling_y = cm->subsampling_y;
pool->frame_bufs[cm->new_fb_idx].buf.bit_depth = (unsigned int)cm->bit_depth; 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_space = cm->color_space;
pool->frame_bufs[cm->new_fb_idx].buf.color_range = cm->color_range;
} }
static INLINE int valid_ref_frame_img_fmt(vpx_bit_depth_t ref_bit_depth, static INLINE int valid_ref_frame_img_fmt(vpx_bit_depth_t ref_bit_depth,
@ -1337,6 +1338,7 @@ static void setup_frame_size_with_refs(VP9_COMMON *cm,
pool->frame_bufs[cm->new_fb_idx].buf.subsampling_y = cm->subsampling_y; pool->frame_bufs[cm->new_fb_idx].buf.subsampling_y = cm->subsampling_y;
pool->frame_bufs[cm->new_fb_idx].buf.bit_depth = (unsigned int)cm->bit_depth; 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_space = cm->color_space;
pool->frame_bufs[cm->new_fb_idx].buf.color_range = cm->color_range;
} }
static void setup_tile_info(VP9_COMMON *cm, struct vpx_read_bit_buffer *rb) { static void setup_tile_info(VP9_COMMON *cm, struct vpx_read_bit_buffer *rb) {
@ -1774,7 +1776,8 @@ static void read_bitdepth_colorspace_sampling(
} }
cm->color_space = vpx_rb_read_literal(rb, 3); cm->color_space = vpx_rb_read_literal(rb, 3);
if (cm->color_space != VPX_CS_SRGB) { if (cm->color_space != VPX_CS_SRGB) {
vpx_rb_read_bit(rb); // [16,235] (including xvycc) vs [0,255] range // [16,235] (including xvycc) vs [0,255] range
cm->color_range = vpx_rb_read_bit(rb);
if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) { if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) {
cm->subsampling_x = vpx_rb_read_bit(rb); cm->subsampling_x = vpx_rb_read_bit(rb);
cm->subsampling_y = vpx_rb_read_bit(rb); cm->subsampling_y = vpx_rb_read_bit(rb);
@ -1788,6 +1791,7 @@ static void read_bitdepth_colorspace_sampling(
cm->subsampling_y = cm->subsampling_x = 1; cm->subsampling_y = cm->subsampling_x = 1;
} }
} else { } else {
cm->color_range = 1;
if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) { if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) {
// Note if colorspace is SRGB then 4:4:4 chroma sampling is assumed. // Note if colorspace is SRGB then 4:4:4 chroma sampling is assumed.
// 4:2:2 or 4:4:0 chroma sampling is not allowed. // 4:2:2 or 4:4:0 chroma sampling is not allowed.
@ -1893,6 +1897,7 @@ static size_t read_uncompressed_header(VP9Decoder *pbi,
// 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 = VPX_CS_BT_601; cm->color_space = VPX_CS_BT_601;
cm->color_range = 0;
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
@ -1943,6 +1948,7 @@ static size_t read_uncompressed_header(VP9Decoder *pbi,
get_frame_new_buffer(cm)->bit_depth = cm->bit_depth; get_frame_new_buffer(cm)->bit_depth = cm->bit_depth;
#endif #endif
get_frame_new_buffer(cm)->color_space = cm->color_space; get_frame_new_buffer(cm)->color_space = cm->color_space;
get_frame_new_buffer(cm)->color_range = cm->color_range;
if (pbi->need_resync) { if (pbi->need_resync) {
vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME, vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME,

View File

@ -1060,7 +1060,8 @@ static void write_bitdepth_colorspace_sampling(
} }
vpx_wb_write_literal(wb, cm->color_space, 3); vpx_wb_write_literal(wb, cm->color_space, 3);
if (cm->color_space != VPX_CS_SRGB) { if (cm->color_space != VPX_CS_SRGB) {
vpx_wb_write_bit(wb, 0); // 0: [16, 235] (i.e. xvYCC), 1: [0, 255] // 0: [16, 235] (i.e. xvYCC), 1: [0, 255]
vpx_wb_write_bit(wb, cm->color_range);
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);
vpx_wb_write_bit(wb, cm->subsampling_x); vpx_wb_write_bit(wb, cm->subsampling_x);

View File

@ -775,6 +775,7 @@ static void init_config(struct VP9_COMP *cpi, VP9EncoderConfig *oxcf) {
cm->use_highbitdepth = oxcf->use_highbitdepth; cm->use_highbitdepth = oxcf->use_highbitdepth;
#endif #endif
cm->color_space = oxcf->color_space; cm->color_space = oxcf->color_space;
cm->color_range = oxcf->color_range;
cm->width = oxcf->width; cm->width = oxcf->width;
cm->height = oxcf->height; cm->height = oxcf->height;
@ -1462,6 +1463,7 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) {
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; cm->color_space = oxcf->color_space;
cm->color_range = oxcf->color_range;
if (cm->profile <= PROFILE_1) if (cm->profile <= PROFILE_1)
assert(cm->bit_depth == VPX_BITS_8); assert(cm->bit_depth == VPX_BITS_8);
@ -3817,6 +3819,7 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
cm->frame_to_show = get_frame_new_buffer(cm); cm->frame_to_show = get_frame_new_buffer(cm);
cm->frame_to_show->color_space = cm->color_space; cm->frame_to_show->color_space = cm->color_space;
cm->frame_to_show->color_range = cm->color_range;
// Pick the loop filter level for the frame. // Pick the loop filter level for the frame.
loopfilter_frame(cpi, cm); loopfilter_frame(cpi, cm);

View File

@ -238,6 +238,7 @@ typedef struct VP9EncoderConfig {
int use_highbitdepth; int use_highbitdepth;
#endif #endif
vpx_color_space_t color_space; vpx_color_space_t color_space;
int color_range;
VP9E_TEMPORAL_LAYERING_MODE temporal_layering_mode; VP9E_TEMPORAL_LAYERING_MODE temporal_layering_mode;
} VP9EncoderConfig; } VP9EncoderConfig;

View File

@ -45,6 +45,7 @@ struct vp9_extracfg {
vpx_bit_depth_t bit_depth; vpx_bit_depth_t bit_depth;
vp9e_tune_content content; vp9e_tune_content content;
vpx_color_space_t color_space; vpx_color_space_t color_space;
int color_range;
}; };
static struct vp9_extracfg default_extra_cfg = { static struct vp9_extracfg default_extra_cfg = {
@ -71,6 +72,7 @@ static struct vp9_extracfg default_extra_cfg = {
VPX_BITS_8, // Bit depth VPX_BITS_8, // Bit depth
VP9E_CONTENT_DEFAULT, // content VP9E_CONTENT_DEFAULT, // content
VPX_CS_UNKNOWN, // color space VPX_CS_UNKNOWN, // color space
0, // color range
}; };
struct vpx_codec_alg_priv { struct vpx_codec_alg_priv {
@ -321,6 +323,7 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx,
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, VPX_CS_UNKNOWN, VPX_CS_SRGB); RANGE_CHECK(extra_cfg, color_space, VPX_CS_UNKNOWN, VPX_CS_SRGB);
RANGE_CHECK(extra_cfg, color_range, 0, 2);
return VPX_CODEC_OK; return VPX_CODEC_OK;
} }
@ -465,6 +468,7 @@ static vpx_codec_err_t set_encoder_config(
#endif #endif
oxcf->color_space = extra_cfg->color_space; oxcf->color_space = extra_cfg->color_space;
oxcf->color_range = extra_cfg->color_range;
oxcf->arnr_max_frames = extra_cfg->arnr_max_frames; oxcf->arnr_max_frames = extra_cfg->arnr_max_frames;
oxcf->arnr_strength = extra_cfg->arnr_strength; oxcf->arnr_strength = extra_cfg->arnr_strength;
oxcf->min_gf_interval = extra_cfg->min_gf_interval; oxcf->min_gf_interval = extra_cfg->min_gf_interval;
@ -1436,6 +1440,13 @@ static vpx_codec_err_t ctrl_set_color_space(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_range(vpx_codec_alg_priv_t *ctx,
va_list args) {
struct vp9_extracfg extra_cfg = ctx->extra_cfg;
extra_cfg.color_range = CAST(VP9E_SET_COLOR_RANGE, 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},
@ -1472,6 +1483,7 @@ static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
{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_COLOR_SPACE, ctrl_set_color_space},
{VP9E_SET_COLOR_RANGE, ctrl_set_color_range},
{VP9E_SET_NOISE_SENSITIVITY, ctrl_set_noise_sensitivity}, {VP9E_SET_NOISE_SENSITIVITY, ctrl_set_noise_sensitivity},
{VP9E_SET_MIN_GF_INTERVAL, ctrl_set_min_gf_interval}, {VP9E_SET_MIN_GF_INTERVAL, ctrl_set_min_gf_interval},
{VP9E_SET_MAX_GF_INTERVAL, ctrl_set_max_gf_interval}, {VP9E_SET_MAX_GF_INTERVAL, ctrl_set_max_gf_interval},

View File

@ -37,6 +37,7 @@ static void yuvconfig2image(vpx_image_t *img, const YV12_BUFFER_CONFIG *yv12,
} }
} }
img->cs = yv12->color_space; img->cs = yv12->color_space;
img->range = yv12->color_range;
img->bit_depth = 8; img->bit_depth = 8;
img->w = yv12->y_stride; img->w = yv12->y_stride;
img->h = ALIGN_POWER_OF_TWO(yv12->y_height + 2 * VP9_ENC_BORDER_IN_PIXELS, 3); img->h = ALIGN_POWER_OF_TWO(yv12->y_height + 2 * VP9_ENC_BORDER_IN_PIXELS, 3);
@ -96,6 +97,7 @@ static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img,
yv12->y_stride = img->stride[VPX_PLANE_Y]; yv12->y_stride = img->stride[VPX_PLANE_Y];
yv12->uv_stride = img->stride[VPX_PLANE_U]; yv12->uv_stride = img->stride[VPX_PLANE_U];
yv12->color_space = img->cs; yv12->color_space = img->cs;
yv12->color_range = img->range;
#if CONFIG_VP9_HIGHBITDEPTH #if CONFIG_VP9_HIGHBITDEPTH
if (img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) { if (img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) {

View File

@ -547,6 +547,15 @@ enum vp8e_enc_control_id {
* Supported in codecs: VP9 * Supported in codecs: VP9
*/ */
VP9E_GET_ACTIVEMAP, VP9E_GET_ACTIVEMAP,
/*!\brief Codec control function to set color range bit.
* \note Valid ranges: 0..1, default is 0
* 0 = Limited range (16..235 or HBD equivalent)
* 1 = Full range (0..255 or HBD equivalent)
*
* Supported in codecs: VP9
*/
VP9E_SET_COLOR_RANGE,
}; };
/*!\brief vpx 1-D scaling mode /*!\brief vpx 1-D scaling mode
@ -757,6 +766,13 @@ VPX_CTRL_USE_TYPE(VP9E_SET_MAX_GF_INTERVAL, unsigned int)
#define VPX_CTRL_VP9E_SET_MAX_GF_INTERVAL #define VPX_CTRL_VP9E_SET_MAX_GF_INTERVAL
VPX_CTRL_USE_TYPE(VP9E_GET_ACTIVEMAP, vpx_active_map_t *) VPX_CTRL_USE_TYPE(VP9E_GET_ACTIVEMAP, vpx_active_map_t *)
/*!\brief
*
* TODO(rbultje) : add support of the control in ffmpeg
*/
#define VPX_CTRL_VP9E_SET_COLOR_RANGE
VPX_CTRL_USE_TYPE(VP9E_SET_COLOR_RANGE, int)
/*! @} - end defgroup vp8_encoder */ /*! @} - end defgroup vp8_encoder */
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"

View File

@ -82,6 +82,7 @@ extern "C" {
typedef struct vpx_image { typedef struct vpx_image {
vpx_img_fmt_t fmt; /**< Image Format */ vpx_img_fmt_t fmt; /**< Image Format */
vpx_color_space_t cs; /**< Color Space */ vpx_color_space_t cs; /**< Color Space */
int range; /**< Limited (0) vs. Full-range (1) sample data */
/* Image storage dimensions */ /* Image storage dimensions */
unsigned int w; /**< Stored image width */ unsigned int w; /**< Stored image width */

View File

@ -56,6 +56,7 @@ typedef struct yv12_buffer_config {
int subsampling_y; int subsampling_y;
unsigned int bit_depth; unsigned int bit_depth;
vpx_color_space_t color_space; vpx_color_space_t color_space;
int color_range;
int corrupted; int corrupted;
int flags; int flags;