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:
parent
854acfbbea
commit
09bf1d61ca
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user