From d35df2d8eaa74d7f9640f380f23e057fd7d83c35 Mon Sep 17 00:00:00 2001 From: Deb Mukherjee Date: Fri, 4 Apr 2014 17:30:16 -0700 Subject: [PATCH] High-level hooks for Profile 2 (10/12 bit) Adds some high-level hooks for profile 2 before further progress on the implementation. According to the definitiion in this patch: 1. Profile 2 only supports 10 or 12 bit color but not 8 2. Profile 2 supports all color sampling modes: 444, 422 and 420, and alpha plane. 3. Profile 3 is currently undefined. Please consider the definition carefully and suggest modifications to the definition as needed. Change-Id: I5b284fc679e54ac5aee171af72fa7994cfd28995 --- vp9/common/vp9_enums.h | 17 +++++++++++++++++ vp9/common/vp9_onyxc_int.h | 5 ++++- vp9/decoder/vp9_decodeframe.c | 22 +++++++++++++--------- vp9/encoder/vp9_bitstream.c | 23 +++++++++++++++-------- vp9/encoder/vp9_onyx_if.c | 15 +++++++++++---- vp9/encoder/vp9_onyx_int.h | 5 ++--- vp9/vp9_cx_iface.c | 17 ++++++++++++++--- 7 files changed, 76 insertions(+), 28 deletions(-) diff --git a/vp9/common/vp9_enums.h b/vp9/common/vp9_enums.h index 779dce017..068284faa 100644 --- a/vp9/common/vp9_enums.h +++ b/vp9/common/vp9_enums.h @@ -25,6 +25,23 @@ extern "C" { #define MI_MASK (MI_BLOCK_SIZE - 1) +// Bitstream profiles indicated by 2 bits in the uncompressed header. +// 00: Profile 0. 4:2:0 only. +// 10: Profile 1. adds 4:4:4, 4:2:2, alpha. +// 01: Profile 2. Supports 10-bit and 12-bit color only. +// 11: Undefined profile. +typedef enum BITSTREAM_PROFILE { + PROFILE_0, + PROFILE_1, + PROFILE_2, + MAX_PROFILES +} BITSTREAM_PROFILE; + +typedef enum BIT_DEPTH { + BITS_8, + BITS_10, + BITS_12 +} BIT_DEPTH; typedef enum BLOCK_SIZE { BLOCK_4X4, diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h index ea1b8856e..77f563f2f 100644 --- a/vp9/common/vp9_onyxc_int.h +++ b/vp9/common/vp9_onyxc_int.h @@ -179,7 +179,10 @@ typedef struct VP9Common { FRAME_COUNTS counts; unsigned int current_video_frame; - int version; + BITSTREAM_PROFILE profile; + + // BITS_8 in versions 0 and 1, BITS_10 or BITS_12 in version 2 + BIT_DEPTH bit_depth; #if CONFIG_VP9_POSTPROC struct postproc_state postproc_state; diff --git a/vp9/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c index 6784238de..f903e0919 100644 --- a/vp9/decoder/vp9_decodeframe.c +++ b/vp9/decoder/vp9_decodeframe.c @@ -1005,10 +1005,11 @@ static void error_handler(void *data) { vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME, "Truncated packet"); } -#define RESERVED \ - if (vp9_rb_read_bit(rb)) \ - vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM, \ - "Reserved bit must be unset") +static BITSTREAM_PROFILE read_profile(struct vp9_read_bit_buffer *rb) { + int profile = vp9_rb_read_bit(rb); + profile |= vp9_rb_read_bit(rb) << 1; + return (BITSTREAM_PROFILE) profile; +} static size_t read_uncompressed_header(VP9Decoder *pbi, struct vp9_read_bit_buffer *rb) { @@ -1022,8 +1023,10 @@ static size_t read_uncompressed_header(VP9Decoder *pbi, vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM, "Invalid frame marker"); - cm->version = vp9_rb_read_bit(rb); - RESERVED; + cm->profile = read_profile(rb); + if (cm->profile >= MAX_PROFILES) + vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM, + "Unsupported bitstream profile"); cm->show_existing_frame = vp9_rb_read_bit(rb); if (cm->show_existing_frame) { @@ -1048,11 +1051,12 @@ static size_t read_uncompressed_header(VP9Decoder *pbi, if (cm->frame_type == KEY_FRAME) { check_sync_code(cm, rb); - + 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->version == 1) { + if (cm->profile >= PROFILE_1) { cm->subsampling_x = vp9_rb_read_bit(rb); cm->subsampling_y = vp9_rb_read_bit(rb); vp9_rb_read_bit(rb); // has extra plane @@ -1060,7 +1064,7 @@ static size_t read_uncompressed_header(VP9Decoder *pbi, cm->subsampling_y = cm->subsampling_x = 1; } } else { - if (cm->version == 1) { + if (cm->profile >= PROFILE_1) { cm->subsampling_y = cm->subsampling_x = 0; vp9_rb_read_bit(rb); // has extra plane } else { diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c index 4313418d4..8d2afb991 100644 --- a/vp9/encoder/vp9_bitstream.c +++ b/vp9/encoder/vp9_bitstream.c @@ -1031,19 +1031,22 @@ static void write_sync_code(struct vp9_write_bit_buffer *wb) { vp9_wb_write_literal(wb, VP9_SYNC_CODE_2, 8); } +static void write_profile(BITSTREAM_PROFILE profile, + struct vp9_write_bit_buffer *wb) { + assert(profile < MAX_PROFILES); + vp9_wb_write_bit(wb, profile & 1); + vp9_wb_write_bit(wb, profile >> 1); +} + static void write_uncompressed_header(VP9_COMP *cpi, struct vp9_write_bit_buffer *wb) { VP9_COMMON *const cm = &cpi->common; vp9_wb_write_literal(wb, VP9_FRAME_MARKER, 2); - // bitstream version. - // 00 - profile 0. 4:2:0 only - // 10 - profile 1. adds 4:4:4, 4:2:2, alpha - vp9_wb_write_bit(wb, cm->version); - vp9_wb_write_bit(wb, 0); + write_profile(cm->profile, wb); - vp9_wb_write_bit(wb, 0); + vp9_wb_write_bit(wb, 0); // show_existing_frame vp9_wb_write_bit(wb, cm->frame_type); vp9_wb_write_bit(wb, cm->show_frame); vp9_wb_write_bit(wb, cm->error_resilient_mode); @@ -1051,16 +1054,20 @@ static void write_uncompressed_header(VP9_COMP *cpi, 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->version == 1) { + if (cm->profile >= PROFILE_1) { vp9_wb_write_bit(wb, cm->subsampling_x); vp9_wb_write_bit(wb, cm->subsampling_y); vp9_wb_write_bit(wb, 0); // has extra plane } } else { - assert(cm->version == 1); + assert(cm->profile == PROFILE_1); vp9_wb_write_bit(wb, 0); // has extra plane } diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c index 04c742f0a..8d0faba2b 100644 --- a/vp9/encoder/vp9_onyx_if.c +++ b/vp9/encoder/vp9_onyx_if.c @@ -754,7 +754,8 @@ static void init_config(struct VP9_COMP *cpi, VP9_CONFIG *oxcf) { cpi->oxcf = *oxcf; - cm->version = oxcf->version; + cm->profile = oxcf->profile; + cm->bit_depth = oxcf->bit_depth; cm->width = oxcf->width; cm->height = oxcf->height; @@ -794,8 +795,14 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9_CONFIG *oxcf) { VP9_COMMON *const cm = &cpi->common; RATE_CONTROL *const rc = &cpi->rc; - if (cm->version != oxcf->version) - cm->version = oxcf->version; + if (cm->profile != oxcf->profile) + cm->profile = oxcf->profile; + cm->bit_depth = oxcf->bit_depth; + + if (cm->profile <= PROFILE_1) + assert(cm->bit_depth == BITS_8); + else + assert(cm->bit_depth > BITS_8); cpi->oxcf = *oxcf; @@ -2847,7 +2854,7 @@ 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->version == 0 && (subsampling_x != 1 || subsampling_y != 1)) { + if (cm->profile == PROFILE_0 && (subsampling_x != 1 || subsampling_y != 1)) { vpx_internal_error(&cm->error, VPX_CODEC_INVALID_PARAM, "Non-4:2:0 color space requires profile >= 1"); res = -1; diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h index 6d5f62fb7..3d2c2da7b 100644 --- a/vp9/encoder/vp9_onyx_int.h +++ b/vp9/encoder/vp9_onyx_int.h @@ -186,9 +186,8 @@ typedef enum { } AQ_MODE; typedef struct VP9_CONFIG { - int version; // 4 versions of bitstream defined: - // 0 - best quality/slowest decode, - // 3 - lowest quality/fastest decode + BITSTREAM_PROFILE profile; + BIT_DEPTH bit_depth; int width; // width of data passed to the compressor int height; // height of data passed to the compressor double framerate; // set to passed in framerate diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index dfcec783c..5b2645e99 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -38,6 +38,7 @@ struct vp9_extracfg { unsigned int frame_parallel_decoding_mode; AQ_MODE aq_mode; unsigned int frame_periodic_boost; + BIT_DEPTH bit_depth; }; struct extraconfig_map { @@ -67,6 +68,7 @@ static const struct extraconfig_map extracfg_map[] = { 0, // frame_parallel_decoding_mode NO_AQ, // aq_mode 0, // frame_periodic_delta_q + BITS_8, // Bit depth } } }; @@ -252,6 +254,12 @@ static vpx_codec_err_t validate_config(vpx_codec_alg_priv_t *ctx, ERROR("rc_twopass_stats_in missing EOS stats packet"); } } + if (cfg->g_profile <= (unsigned int)PROFILE_1 && + extra_cfg->bit_depth > BITS_8) + ERROR("High bit-depth not supported in profile < 2"); + if (cfg->g_profile > (unsigned int)PROFILE_1 && + extra_cfg->bit_depth == BITS_8) + ERROR("Bit-depth 8 not supported in profile > 1"); return VPX_CODEC_OK; } @@ -277,11 +285,14 @@ static vpx_codec_err_t validate_img(vpx_codec_alg_priv_t *ctx, } -static vpx_codec_err_t set_encoder_config(VP9_CONFIG *oxcf, - const vpx_codec_enc_cfg_t *cfg, const struct vp9_extracfg *extra_cfg) { - oxcf->version = cfg->g_profile; +static vpx_codec_err_t set_encoder_config( + VP9_CONFIG *oxcf, + const vpx_codec_enc_cfg_t *cfg, + const struct vp9_extracfg *extra_cfg) { + oxcf->profile = cfg->g_profile; oxcf->width = cfg->g_w; oxcf->height = cfg->g_h; + oxcf->bit_depth = extra_cfg->bit_depth; // guess a frame rate if out of whack, use 30 oxcf->framerate = (double)cfg->g_timebase.den / cfg->g_timebase.num; if (oxcf->framerate > 180) -- 2.40.0