Changes hdr for profiles > 1 for intraonly frames

Specifies the bit-depth, color sampling and colorspace
for intra only frames for profiles > 0

Also adds checks to ensure that profile 1 and 3 are
exclusively used for non 420 streams.

Change-Id: Icfb15fa1acccbce8f757c78fa8a2f60591360745
This commit is contained in:
Deb Mukherjee 2014-08-05 13:00:43 -07:00
parent 854acfbbea
commit 09bf1d61ca
5 changed files with 119 additions and 76 deletions

View File

@ -27,10 +27,10 @@ extern "C" {
// Bitstream profiles indicated by 2-3 bits in the uncompressed header.
// 00: Profile 0. 8-bit 4:2:0 only.
// 10: Profile 1. Adds 4:4:4, 4:2:2, and 4:4:0 to Profile 0.
// 01: Profile 2. Supports 10-bit and 12-bit color only, with 4:2:0 sampling.
// 110: Profile 3. Supports 10-bit and 12-bit color only, with 4:2:2/4:4:4/4:4:0
// subsampling.
// 10: Profile 1. 8-bit 4:4:4, 4:2:2, and 4:4:0.
// 01: Profile 2. 10-bit and 12-bit color only, with 4:2:0 sampling.
// 110: Profile 3. 10-bit and 12-bit color only, with 4:2:2/4:4:4/4:4:0
// sampling.
// 111: Undefined profile.
typedef enum BITSTREAM_PROFILE {
PROFILE_0,

View File

@ -1095,6 +1095,40 @@ BITSTREAM_PROFILE vp9_read_profile(struct vp9_read_bit_buffer *rb) {
return (BITSTREAM_PROFILE) profile;
}
static void read_bitdepth_colorspace_sampling(
VP9_COMMON *cm, struct vp9_read_bit_buffer *rb) {
if (cm->profile >= PROFILE_2)
cm->bit_depth = vp9_rb_read_bit(rb) ? BITS_12 : BITS_10;
cm->color_space = (COLOR_SPACE)vp9_rb_read_literal(rb, 3);
if (cm->color_space != SRGB) {
vp9_rb_read_bit(rb); // [16,235] (including xvycc) vs [0,255] range
if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) {
cm->subsampling_x = vp9_rb_read_bit(rb);
cm->subsampling_y = vp9_rb_read_bit(rb);
if (cm->subsampling_x == 1 && cm->subsampling_y == 1)
vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
"4:2:0 color not supported in profile 1 or 3");
if (vp9_rb_read_bit(rb))
vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
"Reserved bit set");
} else {
cm->subsampling_y = cm->subsampling_x = 1;
}
} else {
if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) {
// 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.
cm->subsampling_y = cm->subsampling_x = 0;
if (vp9_rb_read_bit(rb))
vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
"Reserved bit set");
} else {
vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
"4:4:4 color not supported in profile 0 or 2");
}
}
}
static size_t read_uncompressed_header(VP9Decoder *pbi,
struct vp9_read_bit_buffer *rb) {
VP9_COMMON *const cm = &pbi->common;
@ -1137,32 +1171,8 @@ static size_t read_uncompressed_header(VP9Decoder *pbi,
if (!vp9_read_sync_code(rb))
vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
"Invalid frame sync code");
if (cm->profile > PROFILE_1)
cm->bit_depth = vp9_rb_read_bit(rb) ? BITS_12 : BITS_10;
cm->color_space = (COLOR_SPACE)vp9_rb_read_literal(rb, 3);
if (cm->color_space != SRGB) {
vp9_rb_read_bit(rb); // [16,235] (including xvycc) vs [0,255] range
if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) {
cm->subsampling_x = vp9_rb_read_bit(rb);
cm->subsampling_y = vp9_rb_read_bit(rb);
if (vp9_rb_read_bit(rb))
vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
"Reserved bit set");
} else {
cm->subsampling_y = cm->subsampling_x = 1;
}
} else {
if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) {
cm->subsampling_y = cm->subsampling_x = 0;
if (vp9_rb_read_bit(rb))
vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
"Reserved bit set");
} else {
vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
"4:4:4 color not supported in profile 0");
}
}
read_bitdepth_colorspace_sampling(cm, rb);
pbi->refresh_frame_flags = (1 << REF_FRAMES) - 1;
for (i = 0; i < REFS_PER_FRAME; ++i) {
@ -1181,15 +1191,18 @@ static size_t read_uncompressed_header(VP9Decoder *pbi,
if (!vp9_read_sync_code(rb))
vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
"Invalid frame sync code");
if (cm->profile > PROFILE_0) {
read_bitdepth_colorspace_sampling(cm, rb);
} else {
// NOTE: The intra-only frame header does not include the specification
// of either the color format or color sub-sampling in profile 0. VP9
// specifies that the default color space should be YUV 4:2:0 in this
// case (normative).
cm->color_space = BT_601;
cm->subsampling_y = cm->subsampling_x = 1;
}
pbi->refresh_frame_flags = vp9_rb_read_literal(rb, REF_FRAMES);
// NOTE: The intra-only frame header does not include the specification of
// either the color format or color sub-sampling. VP9 specifies that the
// default color space should be YUV 4:2:0 in this case (normative).
cm->color_space = BT_601;
cm->subsampling_y = cm->subsampling_x = 1;
setup_frame_size(cm, rb);
} else {
pbi->refresh_frame_flags = vp9_rb_read_literal(rb, REF_FRAMES);

View File

@ -1045,6 +1045,29 @@ static void write_profile(BITSTREAM_PROFILE profile,
}
}
static void write_bitdepth_colorspace_sampling(
VP9_COMMON *const cm, struct vp9_write_bit_buffer *wb) {
if (cm->profile >= PROFILE_2) {
assert(cm->bit_depth > BITS_8);
vp9_wb_write_bit(wb, cm->bit_depth - BITS_10);
}
vp9_wb_write_literal(wb, cm->color_space, 3);
if (cm->color_space != SRGB) {
vp9_wb_write_bit(wb, 0); // 0: [16, 235] (i.e. xvYCC), 1: [0, 255]
if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) {
assert(cm->subsampling_x != 1 || cm->subsampling_y != 1);
vp9_wb_write_bit(wb, cm->subsampling_x);
vp9_wb_write_bit(wb, cm->subsampling_y);
vp9_wb_write_bit(wb, 0); // unused
} else {
assert(cm->subsampling_x == 1 && cm->subsampling_y == 1);
}
} else {
assert(cm->profile == PROFILE_1 || cm->profile == PROFILE_3);
vp9_wb_write_bit(wb, 0); // unused
}
}
static void write_uncompressed_header(VP9_COMP *cpi,
struct vp9_write_bit_buffer *wb) {
VP9_COMMON *const cm = &cpi->common;
@ -1059,25 +1082,8 @@ static void write_uncompressed_header(VP9_COMP *cpi,
vp9_wb_write_bit(wb, cm->error_resilient_mode);
if (cm->frame_type == KEY_FRAME) {
const COLOR_SPACE cs = UNKNOWN;
write_sync_code(wb);
if (cm->profile > PROFILE_1) {
assert(cm->bit_depth > BITS_8);
vp9_wb_write_bit(wb, cm->bit_depth - BITS_10);
}
vp9_wb_write_literal(wb, cs, 3);
if (cs != SRGB) {
vp9_wb_write_bit(wb, 0); // 0: [16, 235] (i.e. xvYCC), 1: [0, 255]
if (cm->profile == PROFILE_1 || cm->profile == PROFILE_3) {
vp9_wb_write_bit(wb, cm->subsampling_x);
vp9_wb_write_bit(wb, cm->subsampling_y);
vp9_wb_write_bit(wb, 0); // unused
}
} else {
assert(cm->profile == PROFILE_1 || cm->profile == PROFILE_3);
vp9_wb_write_bit(wb, 0); // unused
}
write_bitdepth_colorspace_sampling(cm, wb);
write_frame_size(cm, wb);
} else {
if (!cm->show_frame)
@ -1089,6 +1095,11 @@ static void write_uncompressed_header(VP9_COMP *cpi,
if (cm->intra_only) {
write_sync_code(wb);
// Note for profile 0, 420 8bpp is assumed.
if (cm->profile > PROFILE_0) {
write_bitdepth_colorspace_sampling(cm, wb);
}
vp9_wb_write_literal(wb, get_refresh_mask(cpi), REF_FRAMES);
write_frame_size(cm, wb);
} else {

View File

@ -524,6 +524,7 @@ static void init_config(struct VP9_COMP *cpi, VP9EncoderConfig *oxcf) {
cm->profile = oxcf->profile;
cm->bit_depth = oxcf->bit_depth;
cm->color_space = UNKNOWN;
cm->width = oxcf->width;
cm->height = oxcf->height;
@ -2453,9 +2454,16 @@ int vp9_receive_raw_frame(VP9_COMP *cpi, unsigned int frame_flags,
vpx_usec_timer_mark(&timer);
cpi->time_receive_data += vpx_usec_timer_elapsed(&timer);
if (cm->profile == PROFILE_0 && (subsampling_x != 1 || subsampling_y != 1)) {
if ((cm->profile == PROFILE_0 || cm->profile == PROFILE_2) &&
(subsampling_x != 1 || subsampling_y != 1)) {
vpx_internal_error(&cm->error, VPX_CODEC_INVALID_PARAM,
"Non-4:2:0 color space requires profile >= 1");
"Non-4:2:0 color space requires profile 1 or 3");
res = -1;
}
if ((cm->profile == PROFILE_1 || cm->profile == PROFILE_3) &&
(subsampling_x == 1 && subsampling_y == 1)) {
vpx_internal_error(&cm->error, VPX_CODEC_INVALID_PARAM,
"4:2:0 color space requires profile 0 or 2");
res = -1;
}

View File

@ -96,6 +96,30 @@ static vpx_codec_err_t decoder_destroy(vpx_codec_alg_priv_t *ctx) {
return VPX_CODEC_OK;
}
static int parse_bitdepth_colorspace_sampling(
BITSTREAM_PROFILE profile, struct vp9_read_bit_buffer *rb) {
const int sRGB = 7;
int colorspace;
if (profile >= PROFILE_2)
rb->bit_offset += 1; // Bit-depth 10 or 12.
colorspace = vp9_rb_read_literal(rb, 3);
if (colorspace != sRGB) {
rb->bit_offset += 1; // [16,235] (including xvycc) vs [0,255] range.
if (profile == PROFILE_1 || profile == PROFILE_3) {
rb->bit_offset += 2; // subsampling x/y.
rb->bit_offset += 1; // unused.
}
} else {
if (profile == PROFILE_1 || profile == PROFILE_3) {
rb->bit_offset += 1; // unused
} else {
// RGB is only available in version 1.
return 0;
}
}
return 1;
}
static vpx_codec_err_t decoder_peek_si_internal(const uint8_t *data,
unsigned int data_sz,
vpx_codec_stream_info_t *si,
@ -142,37 +166,24 @@ static vpx_codec_err_t decoder_peek_si_internal(const uint8_t *data,
error_resilient = vp9_rb_read_bit(&rb);
if (si->is_kf) {
const int sRGB = 7;
int colorspace;
if (!vp9_read_sync_code(&rb))
return VPX_CODEC_UNSUP_BITSTREAM;
if (profile > PROFILE_1)
rb.bit_offset += 1; // Bit-depth 10 or 12
colorspace = vp9_rb_read_literal(&rb, 3);
if (colorspace != sRGB) {
rb.bit_offset += 1; // [16,235] (including xvycc) vs [0,255] range
if (profile == PROFILE_1 || profile == PROFILE_3) {
rb.bit_offset += 2; // subsampling x/y
rb.bit_offset += 1; // unused
}
} else {
if (profile == PROFILE_1 || profile == PROFILE_3) {
rb.bit_offset += 1; // unused
} else {
// RGB is only available in version 1
return VPX_CODEC_UNSUP_BITSTREAM;
}
}
if (!parse_bitdepth_colorspace_sampling(profile, &rb))
return VPX_CODEC_UNSUP_BITSTREAM;
vp9_read_frame_size(&rb, (int *)&si->w, (int *)&si->h);
} else {
intra_only_flag = show_frame ? 0 : vp9_rb_read_bit(&rb);
rb.bit_offset += error_resilient ? 0 : 2; // reset_frame_context
if (intra_only_flag) {
if (!vp9_read_sync_code(&rb))
return VPX_CODEC_UNSUP_BITSTREAM;
if (profile > PROFILE_0) {
if (!parse_bitdepth_colorspace_sampling(profile, &rb))
return VPX_CODEC_UNSUP_BITSTREAM;
}
rb.bit_offset += REF_FRAMES; // refresh_frame_flags
vp9_read_frame_size(&rb, (int *)&si->w, (int *)&si->h);
}