From: Deb Mukherjee Date: Tue, 5 Aug 2014 20:00:43 +0000 (-0700) Subject: Changes hdr for profiles > 1 for intraonly frames X-Git-Tag: v1.4.0~1075^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=09bf1d61c;p=libvpx 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 --- diff --git a/vp9/common/vp9_enums.h b/vp9/common/vp9_enums.h index 0c2898d21..d77631341 100644 --- a/vp9/common/vp9_enums.h +++ b/vp9/common/vp9_enums.h @@ -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, diff --git a/vp9/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c index a448bd2b4..1d4b53fa0 100644 --- a/vp9/decoder/vp9_decodeframe.c +++ b/vp9/decoder/vp9_decodeframe.c @@ -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); diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c index 2434aaff9..5e6af98f3 100644 --- a/vp9/encoder/vp9_bitstream.c +++ b/vp9/encoder/vp9_bitstream.c @@ -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 { diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index b1c5326f4..6ba4ac69f 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -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; } diff --git a/vp9/vp9_dx_iface.c b/vp9/vp9_dx_iface.c index c52884084..da537d946 100644 --- a/vp9/vp9_dx_iface.c +++ b/vp9/vp9_dx_iface.c @@ -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); }