blob: 06d0fb7cefa742e8f51c252c82051b439c464d92 [file] [log] [blame] [edit]
/*
* Copyright (c) 2021, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 3-Clause Clear License
* and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
* License was not distributed with this source code in the LICENSE file, you
* can obtain it at aomedia.org/license/software-license/bsd-3-c-c/. If the
* Alliance for Open Media Patent License 1.0 was not distributed with this
* source code in the PATENTS file, you can obtain it at
* aomedia.org/license/patent-license/.
*/
#include <assert.h>
#include "config/avm_config.h"
#include "av2/common/banding_metadata.h"
#include "config/avm_scale_rtcd.h"
#include "avm/avm_codec.h"
#include "avm_dsp/bitreader_buffer.h"
#include "avm_mem/avm_mem.h"
#include "avm_ports/mem_ops.h"
#include "av2/common/common.h"
#include "av2/common/obu_util.h"
#include "av2/common/timing.h"
#include "av2/decoder/decoder.h"
#include "av2/decoder/decodeframe.h"
#include "av2/decoder/obu.h"
#include "av2/common/enums.h"
// Helper macro to check if OBU type is metadata
#if !CONFIG_METADATA
#define IS_METADATA_OBU(type) ((type) == OBU_METADATA)
#else
#define IS_METADATA_OBU(type) \
((type) == OBU_METADATA_SHORT || (type) == OBU_METADATA_GROUP)
#endif // CONFIG_METADATA
#if !CONFIG_CWG_F270_OPS
avm_codec_err_t avm_get_num_layers_from_operating_point_idc(
int operating_point_idc, unsigned int *number_mlayers,
unsigned int *number_tlayers) {
// derive number of embedded/temporal layers from operating_point_idc
if (!number_mlayers || !number_tlayers) return AVM_CODEC_INVALID_PARAM;
if (operating_point_idc == 0) {
*number_tlayers = 1;
*number_mlayers = 1;
} else {
*number_mlayers = 0;
*number_tlayers = 0;
for (int j = 0; j < MAX_NUM_MLAYERS; j++) {
*number_mlayers += (operating_point_idc >> (j + MAX_NUM_TLAYERS)) & 0x1;
}
for (int j = 0; j < MAX_NUM_TLAYERS; j++) {
*number_tlayers += (operating_point_idc >> j) & 0x1;
}
}
return AVM_CODEC_OK;
}
static int is_obu_in_current_operating_point(AV2Decoder *pbi,
ObuHeader obu_header) {
if (!pbi->current_operating_point) {
return 1;
}
if ((pbi->current_operating_point >> obu_header.obu_tlayer_id) & 0x1 &&
(pbi->current_operating_point >>
(obu_header.obu_mlayer_id + MAX_NUM_TLAYERS)) &
0x1) {
return 1;
}
return 0;
}
#endif // !CONFIG_CWG_F270_OPS
static uint32_t read_temporal_delimiter_obu() { return 0; }
// Returns a boolean that indicates success.
static int read_bitstream_level(AV2_LEVEL *seq_level_idx,
struct avm_read_bit_buffer *rb) {
*seq_level_idx = avm_rb_read_literal(rb, LEVEL_BITS);
if (!is_valid_seq_level_idx(*seq_level_idx)) return 0;
return 1;
}
static void av2_read_tlayer_dependency_info(SequenceHeader *const seq,
struct avm_read_bit_buffer *rb) {
const int max_layer_id = seq->max_tlayer_id;
for (int curr_layer_id = 1; curr_layer_id <= max_layer_id; curr_layer_id++) {
for (int ref_layer_id = curr_layer_id; ref_layer_id >= 0; ref_layer_id--) {
seq->tlayer_dependency_map[curr_layer_id][ref_layer_id] =
avm_rb_read_bit(rb);
}
}
}
static void av2_read_mlayer_dependency_info(SequenceHeader *const seq,
struct avm_read_bit_buffer *rb) {
const int max_layer_id = seq->max_mlayer_id;
for (int curr_layer_id = 1; curr_layer_id <= max_layer_id; curr_layer_id++) {
for (int ref_layer_id = curr_layer_id; ref_layer_id >= 0; ref_layer_id--) {
seq->mlayer_dependency_map[curr_layer_id][ref_layer_id] =
avm_rb_read_bit(rb);
}
}
}
static INLINE int get_max_legal_dpb_size(
const struct SequenceHeader *seq_params, const int max_picture_size) {
assert(seq_params != NULL && max_picture_size > 0);
int current_picture_size =
seq_params->max_frame_width * seq_params->max_frame_height;
int max_legal_dpb_size =
AVMMIN(REF_FRAMES, (int)((max_picture_size * 8) / current_picture_size));
return max_legal_dpb_size;
}
#if CONFIG_CROP_WIN_CWG_F220
// This function validates the conformance window params
static void av2_validate_seq_conformance_window(
const struct SequenceHeader *seq_params,
struct avm_internal_error_info *error_info) {
const struct CropWindow *conf = &seq_params->conf;
if (!conf->conf_win_enabled_flag) return;
if (conf->conf_win_left_offset >= seq_params->max_frame_width) {
avm_internal_error(
error_info, AVM_CODEC_UNSUP_BITSTREAM,
"Conformance window left offset %d exceeds max width %d\n",
conf->conf_win_left_offset, seq_params->max_frame_width);
}
if (conf->conf_win_right_offset >= seq_params->max_frame_width) {
avm_internal_error(
error_info, AVM_CODEC_UNSUP_BITSTREAM,
"Conformance window right offset %d exceeds max width %d\n",
conf->conf_win_right_offset, seq_params->max_frame_width);
}
if (conf->conf_win_top_offset >= seq_params->max_frame_height) {
avm_internal_error(
error_info, AVM_CODEC_UNSUP_BITSTREAM,
"Conformance window top offset %d exceeds max height %d\n",
conf->conf_win_top_offset, seq_params->max_frame_height);
}
if (conf->conf_win_bottom_offset >= seq_params->max_frame_height) {
avm_internal_error(
error_info, AVM_CODEC_UNSUP_BITSTREAM,
"Conformance window bottom offset %d exceeds max height %d\n",
conf->conf_win_bottom_offset, seq_params->max_frame_height);
}
}
#endif // CONFIG_CROP_WIN_CWG_F220
// Returns whether two sequence headers are consistent with each other.
// Note that the 'op_params' field is not compared per Section 7.5 in the spec:
// Within a particular coded video sequence, the contents of
// sequence_header_obu must be bit-identical each time the sequence header
// appears except for the contents of operating_parameters_info.
#if !CONFIG_F024_KEYOBU
static
#endif // !CONFIG_F024_KEYOBU
int
are_seq_headers_consistent(const SequenceHeader *seq_params_old,
const SequenceHeader *seq_params_new) {
return !memcmp(seq_params_old, seq_params_new,
offsetof(SequenceHeader, op_params));
}
static uint32_t read_multi_stream_decoder_operation_obu(
AV2Decoder *pbi, struct avm_read_bit_buffer *rb) {
AV2_COMMON *const cm = &pbi->common;
const uint32_t saved_bit_offset = rb->bit_offset;
// Verify rb has been configured to report errors.
assert(rb->error_handler);
const int num_streams =
avm_rb_read_literal(rb, 3) + 2; // read number of streams
if (num_streams > AVM_MAX_NUM_STREAMS) {
avm_internal_error(
&cm->error, AVM_CODEC_UNSUP_BITSTREAM,
"The number of streams cannot exceed the max value (4).");
}
cm->num_streams = num_streams;
const int multistream_profile_idx =
avm_rb_read_literal(rb, PROFILE_BITS); // read profile of multistream
(void)multistream_profile_idx;
const int multistream_level_idx =
avm_rb_read_literal(rb, LEVEL_BITS); // read level of multistream
(void)multistream_level_idx;
const int multistream_tier_idx =
avm_rb_read_bit(rb); // read tier of multistream
(void)multistream_tier_idx;
const int multistream_even_allocation_flag =
avm_rb_read_bit(rb); // read multistream_even_allocation_flag
if (!multistream_even_allocation_flag) {
const int multistream_large_picture_idc =
avm_rb_read_literal(rb, 3); // read multistream_large_picture_idc
(void)multistream_large_picture_idc;
}
for (int i = 0; i < num_streams; i++) {
cm->stream_ids[i] = avm_rb_read_literal(rb, XLAYER_BITS); // read stream ID
const int substream_profile_idx =
avm_rb_read_literal(rb, PROFILE_BITS); // read profile of multistream
(void)substream_profile_idx;
const int substream_level_idx =
avm_rb_read_literal(rb, LEVEL_BITS); // read level of multistream
(void)substream_level_idx;
const int substream_tier_idx =
avm_rb_read_bit(rb); // read tier of multistream
(void)substream_tier_idx;
}
if (av2_check_trailing_bits(pbi, rb) != 0) {
return 0;
}
return ((rb->bit_offset - saved_bit_offset + 7) >> 3);
}
static INLINE void reset_mfh_valid(AV2_COMMON *cm) {
for (int i = 0; i < MAX_MFH_NUM; i++) {
cm->mfh_valid[i] = false;
#if CONFIG_MFH_SIGNAL_TILE_INFO
cm->mfh_params[i].mfh_tile_info_present_flag = 0;
#endif // CONFIG_MFH_SIGNAL_TILE_INFO
}
}
// On success, sets pbi->sequence_header_ready to 1 and returns the number of
// bytes read from 'rb'.
// On failure, sets pbi->common.error.error_code and returns 0.
static uint32_t read_sequence_header_obu(AV2Decoder *pbi,
struct avm_read_bit_buffer *rb) {
AV2_COMMON *const cm = &pbi->common;
const uint32_t saved_bit_offset = rb->bit_offset;
// Verify rb has been configured to report errors.
assert(rb->error_handler);
#if CONFIG_CWG_E242_SEQ_HDR_ID
// Use an element in the pbi->seq_list array to store the information as we
// decode. At the end, if no errors have occurred, cm->seq_params is updated.
uint32_t seq_header_id = avm_rb_read_uvlc(rb);
if (seq_header_id >= MAX_SEQ_NUM) {
cm->error.error_code = AVM_CODEC_UNSUP_BITSTREAM;
return 0;
}
struct SequenceHeader *seq_params;
int seq_header_pos = -1;
for (int i = 0; i < pbi->seq_header_count; i++) {
if (pbi->seq_list[i].seq_header_id == (int)seq_header_id) {
seq_header_pos = i;
break;
}
}
if (seq_header_pos != -1) {
seq_params = &pbi->seq_list[seq_header_pos];
} else {
assert(pbi->seq_header_count < MAX_SEQ_NUM);
seq_params = &pbi->seq_list[pbi->seq_header_count];
pbi->seq_header_count++;
seq_params->seq_header_id = seq_header_id;
}
#else
// Use a local variable to store the information as we decode. At the end,
// if no errors have occurred, cm->seq_params is updated.
SequenceHeader sh = cm->seq_params;
SequenceHeader *const seq_params = &sh;
#endif // CONFIG_CWG_E242_SEQ_HDR_ID
#if CONFIG_CWG_F270_OPS
seq_params->profile = av2_read_profile(rb);
if (seq_params->profile > CONFIG_MAX_DECODE_PROFILE) {
cm->error.error_code = AVM_CODEC_UNSUP_BITSTREAM;
return 0;
}
#endif // CONFIG_CWG_F270_OPS
#if !CONFIG_LCR_ID_IN_SH
int seq_lcr_id = avm_rb_read_literal(rb, 3);
if (seq_lcr_id > MAX_NUM_SEQ_LCR_ID) {
avm_internal_error(&cm->error, AVM_CODEC_UNSUP_BITSTREAM,
"Unsupported LCR id in the Sequence Header.\n");
}
seq_params->seq_lcr_id = seq_lcr_id;
#endif // !CONFIG_LCR_ID_IN_SH
#if !CONFIG_CWG_F270_OPS
seq_params->profile = av2_read_profile(rb);
if (seq_params->profile > CONFIG_MAX_DECODE_PROFILE) {
cm->error.error_code = AVM_CODEC_UNSUP_BITSTREAM;
return 0;
}
#endif // !CONFIG_CWG_F270_OPS
#if CONFIG_MODIFY_SH
seq_params->single_picture_header_flag = avm_rb_read_bit(rb);
if (seq_params->single_picture_header_flag) {
#if CONFIG_LCR_ID_IN_SH
seq_params->seq_lcr_id = LCR_ID_UNSPECIFIED;
#endif // CONFIG_LCR_ID_IN_SH
seq_params->still_picture = 1;
} else {
#if CONFIG_LCR_ID_IN_SH
int seq_lcr_id = avm_rb_read_literal(rb, 3);
if (seq_lcr_id > MAX_NUM_SEQ_LCR_ID) {
avm_internal_error(&cm->error, AVM_CODEC_UNSUP_BITSTREAM,
"Unsupported LCR id in the Sequence Header.\n");
}
seq_params->seq_lcr_id = seq_lcr_id;
#endif // CONFIG_LCR_ID_IN_SH
seq_params->still_picture = avm_rb_read_bit(rb);
}
#if CONFIG_CWG_F270_OPS
if (!read_bitstream_level(&seq_params->seq_max_level_idx, rb)) {
cm->error.error_code = AVM_CODEC_UNSUP_BITSTREAM;
return 0;
}
if (seq_params->seq_max_level_idx >= SEQ_LEVEL_4_0 &&
!seq_params->single_picture_header_flag)
seq_params->seq_tier = avm_rb_read_bit(rb);
else
seq_params->seq_tier = 0;
#else
if (!read_bitstream_level(&seq_params->seq_level_idx[0], rb)) {
cm->error.error_code = AVM_CODEC_UNSUP_BITSTREAM;
return 0;
}
if (seq_params->seq_level_idx[0] >= SEQ_LEVEL_4_0 &&
!seq_params->single_picture_header_flag)
seq_params->tier[0] = avm_rb_read_bit(rb);
else
seq_params->tier[0] = 0;
#endif // CONFIG_CWG_F270_OPS
#endif // CONFIG_MODIFY_SH
const int num_bits_width = avm_rb_read_literal(rb, 4) + 1;
const int num_bits_height = avm_rb_read_literal(rb, 4) + 1;
const int max_frame_width = avm_rb_read_literal(rb, num_bits_width) + 1;
const int max_frame_height = avm_rb_read_literal(rb, num_bits_height) + 1;
seq_params->num_bits_width = num_bits_width;
seq_params->num_bits_height = num_bits_height;
seq_params->max_frame_width = max_frame_width;
seq_params->max_frame_height = max_frame_height;
#if CONFIG_CROP_WIN_CWG_F220
av2_read_conformance_window(rb, seq_params);
av2_validate_seq_conformance_window(seq_params, &cm->error);
#endif // CONFIG_CROP_WIN_CWG_F220
#if CONFIG_CWG_F270_CI_OBU
av2_read_chroma_format_bitdepth(rb, seq_params, &cm->error);
#else
av2_read_color_config(rb, seq_params, &cm->error);
#endif // CONFIG_CWG_F270_CI_OBU
#if !CONFIG_CWG_E242_CHROMA_FORMAT_IDC
if (!(seq_params->subsampling_x == 0 && seq_params->subsampling_y == 0) &&
!(seq_params->subsampling_x == 1 && seq_params->subsampling_y == 1) &&
!(seq_params->subsampling_x == 1 && seq_params->subsampling_y == 0)) {
avm_internal_error(&cm->error, AVM_CODEC_UNSUP_BITSTREAM,
"Only 4:4:4, 4:2:2 and 4:2:0 are currently supported, "
"%d %d subsampling is not supported.\n",
seq_params->subsampling_x, seq_params->subsampling_y);
}
#endif // !CONFIG_CWG_E242_CHROMA_FORMAT_IDC
#if !CONFIG_MODIFY_SH
// Still picture or not
seq_params->still_picture = avm_rb_read_bit(rb);
seq_params->single_picture_header_flag = avm_rb_read_bit(rb);
// Video must have single_picture_header_flag = 0
if (!seq_params->still_picture && seq_params->single_picture_header_flag) {
cm->error.error_code = AVM_CODEC_UNSUP_BITSTREAM;
return 0;
}
#endif // !CONFIG_MODIFY_SH
#if CONFIG_CWG_F270_OPS
if (seq_params->single_picture_header_flag) {
seq_params->decoder_model_info_present_flag = 0;
seq_params->display_model_info_present_flag = 0;
} else {
seq_params->seq_max_display_model_info_present_flag = avm_rb_read_bit(rb);
if (seq_params->seq_max_display_model_info_present_flag)
seq_params->seq_max_initial_display_delay_minus_1 =
BUFFER_POOL_MAX_SIZE - 1;
seq_params->decoder_model_info_present_flag = avm_rb_read_bit(rb);
if (seq_params->decoder_model_info_present_flag) {
seq_params->decoder_model_info.num_units_in_decoding_tick =
avm_rb_read_unsigned_literal(rb, 32);
seq_params->seq_max_display_model_info_present_flag = avm_rb_read_bit(rb);
if (seq_params->seq_max_display_model_info_present_flag) {
seq_params->seq_max_decoder_buffer_delay = avm_rb_read_uvlc(rb);
seq_params->seq_max_encoder_buffer_delay = avm_rb_read_uvlc(rb);
seq_params->seq_max_low_delay_mode_flag = avm_rb_read_bit(rb);
} else {
seq_params->seq_max_decoder_buffer_delay = 70000;
seq_params->seq_max_encoder_buffer_delay = 20000;
seq_params->seq_max_low_delay_mode_flag = 0;
}
} else {
seq_params->decoder_model_info.num_units_in_decoding_tick = 1;
seq_params->seq_max_decoder_buffer_delay = 70000;
seq_params->seq_max_encoder_buffer_delay = 20000;
seq_params->seq_max_low_delay_mode_flag = 0;
}
seq_params->seq_max_initial_display_delay_minus_1 = 0;
// TODO: May need additional modifications with decoder model
int64_t seq_bitrate = av2_max_level_bitrate(seq_params->profile,
seq_params->seq_max_level_idx,
seq_params->seq_tier);
if (seq_bitrate == 0)
avm_internal_error(&cm->error, AVM_CODEC_UNSUP_BITSTREAM,
"AV2 does not support this combination of "
"profile, level, and tier.");
// Buffer size in bits/s is bitrate in bits/s * 1 s
int64_t buffer_size = seq_bitrate;
if (buffer_size == 0)
avm_internal_error(&cm->error, AVM_CODEC_UNSUP_BITSTREAM,
"AV2 does not support this combination of "
"profile, level, and tier.");
}
#else
if (seq_params->single_picture_header_flag) {
#if !CONFIG_CWG_F270_CI_OBU
seq_params->timing_info_present = 0;
#endif // !CONFIG_CWG_F270_CI_OBU
seq_params->decoder_model_info_present_flag = 0;
seq_params->display_model_info_present_flag = 0;
seq_params->operating_points_cnt_minus_1 = 0;
seq_params->operating_point_idc[0] = 0;
#if !CONFIG_MODIFY_SH
if (!read_bitstream_level(&seq_params->seq_level_idx[0], rb)) {
cm->error.error_code = AVM_CODEC_UNSUP_BITSTREAM;
return 0;
}
seq_params->tier[0] = 0;
#endif // !CONFIG_MODIFY_SH
seq_params->op_params[0].decoder_model_param_present_flag = 0;
seq_params->op_params[0].display_model_param_present_flag = 0;
} else {
#if !CONFIG_CWG_F270_CI_OBU
seq_params->timing_info_present = avm_rb_read_bit(rb);
if (seq_params->timing_info_present) {
av2_read_timing_info_header(&seq_params->timing_info, &cm->error, rb);
#endif // !CONFIG_CWG_F270_CI_OBU
seq_params->decoder_model_info_present_flag = avm_rb_read_bit(rb);
if (seq_params->decoder_model_info_present_flag)
av2_read_decoder_model_info(&seq_params->decoder_model_info, rb);
#if !CONFIG_CWG_F270_CI_OBU
} else {
seq_params->decoder_model_info_present_flag = 0;
}
#endif // !CONFIG_CWG_F270_CI_OBU
seq_params->display_model_info_present_flag = avm_rb_read_bit(rb);
seq_params->operating_points_cnt_minus_1 =
avm_rb_read_literal(rb, OP_POINTS_CNT_MINUS_1_BITS);
for (int i = 0; i < seq_params->operating_points_cnt_minus_1 + 1; i++) {
seq_params->operating_point_idc[i] =
avm_rb_read_literal(rb, OP_POINTS_IDC_BITS);
#if !CONFIG_MODIFY_SH
if (!read_bitstream_level(&seq_params->seq_level_idx[i], rb)) {
cm->error.error_code = AVM_CODEC_UNSUP_BITSTREAM;
return 0;
}
// This is the seq_level_idx[i] > 7 check in the spec. seq_level_idx 7
// is equivalent to level 3.3.
if (seq_params->seq_level_idx[i] >= SEQ_LEVEL_4_0)
seq_params->tier[i] = avm_rb_read_bit(rb);
else
seq_params->tier[i] = 0;
#endif // !CONFIG_MODIFY_SH
if (seq_params->decoder_model_info_present_flag) {
seq_params->op_params[i].decoder_model_param_present_flag =
avm_rb_read_bit(rb);
if (seq_params->op_params[i].decoder_model_param_present_flag)
av2_read_op_parameters_info(&seq_params->op_params[i],
seq_params->decoder_model_info
.encoder_decoder_buffer_delay_length,
rb);
} else {
seq_params->op_params[i].decoder_model_param_present_flag = 0;
}
#if CONFIG_CWG_F270_CI_OBU
if (seq_params->op_params[i].decoder_model_param_present_flag)
#else
if (seq_params->timing_info_present &&
(seq_params->timing_info.equal_picture_interval ||
seq_params->op_params[i].decoder_model_param_present_flag))
#endif // CONFIG_CWG_F270_CI_OBU
{
seq_params->op_params[i].bitrate = av2_max_level_bitrate(
seq_params->profile, seq_params->seq_level_idx[i],
seq_params->tier[i]);
// Level with seq_level_idx = 31 returns a high "dummy" bitrate to pass
// the check
if (seq_params->op_params[i].bitrate == 0)
avm_internal_error(&cm->error, AVM_CODEC_UNSUP_BITSTREAM,
"AV2 does not support this combination of "
"profile, level, and tier.");
// Buffer size in bits/s is bitrate in bits/s * 1 s
seq_params->op_params[i].buffer_size = seq_params->op_params[i].bitrate;
}
if (
#if !CONFIG_CWG_F270_CI_OBU
seq_params->timing_info_present &&
seq_params->timing_info.equal_picture_interval &&
#endif // !CONFIG_CWG_F270_CI_OBU
!seq_params->op_params[i].decoder_model_param_present_flag) {
// When the decoder_model_parameters are not sent for this op, set
// the default ones that can be used with the resource availability mode
seq_params->op_params[i].decoder_buffer_delay = 70000;
seq_params->op_params[i].encoder_buffer_delay = 20000;
seq_params->op_params[i].low_delay_mode_flag = 0;
}
if (seq_params->display_model_info_present_flag) {
seq_params->op_params[i].display_model_param_present_flag =
avm_rb_read_bit(rb);
if (seq_params->op_params[i].display_model_param_present_flag) {
seq_params->op_params[i].initial_display_delay =
avm_rb_read_literal(rb, 4) + 1;
if (seq_params->op_params[i].initial_display_delay > 10)
avm_internal_error(
&cm->error, AVM_CODEC_UNSUP_BITSTREAM,
"AV2 does not support more than 10 decoded frames delay");
} else {
seq_params->op_params[i].initial_display_delay = 10;
}
} else {
seq_params->op_params[i].display_model_param_present_flag = 0;
seq_params->op_params[i].initial_display_delay = 10;
}
}
}
// This decoder supports all levels. Choose operating point provided by
// external means
int operating_point = pbi->operating_point;
if (operating_point < 0 ||
operating_point > seq_params->operating_points_cnt_minus_1)
operating_point = 0;
pbi->current_operating_point =
seq_params->operating_point_idc[operating_point];
if (avm_get_num_layers_from_operating_point_idc(
pbi->current_operating_point, &cm->number_mlayers,
&cm->number_tlayers) != AVM_CODEC_OK) {
cm->error.error_code = AVM_CODEC_ERROR;
return 0;
}
#endif // CONFIG_CWG_F270_OPS
if (seq_params->single_picture_header_flag) {
seq_params->max_tlayer_id = 0;
seq_params->max_mlayer_id = 0;
} else {
seq_params->max_tlayer_id = avm_rb_read_literal(rb, TLAYER_BITS);
seq_params->max_mlayer_id = avm_rb_read_literal(rb, MLAYER_BITS);
}
// setup default temporal layer dependency
setup_default_temporal_layer_dependency_structure(seq_params);
// setup default embedded layer dependency
setup_default_embedded_layer_dependency_structure(seq_params);
// tlayer dependency description
seq_params->tlayer_dependency_present_flag = 0;
if (seq_params->max_tlayer_id > 0) {
seq_params->tlayer_dependency_present_flag = avm_rb_read_bit(rb);
if (seq_params->tlayer_dependency_present_flag) {
av2_read_tlayer_dependency_info(seq_params, rb);
}
}
// mlayer dependency description
seq_params->mlayer_dependency_present_flag = 0;
if (seq_params->max_mlayer_id > 0) {
seq_params->mlayer_dependency_present_flag = avm_rb_read_bit(rb);
if (seq_params->mlayer_dependency_present_flag) {
av2_read_mlayer_dependency_info(seq_params, rb);
}
}
av2_read_sequence_header(rb, seq_params
#if CONFIG_IMPROVED_REORDER_SEQ_FLAGS && !CONFIG_F255_QMOBU
,
&cm->quant_params, &cm->error
#endif // CONFIG_IMPROVED_REORDER_SEQ_FLAGS && !CONFIG_F255_QMOBU
);
// TODO(hegilmez): the current decoder-side constraint uses the largest
// possible picture size in the level definitions. This covers the worst-case
// memory requirement. If per-level memory restriction is desired,
// MAX_PICTURE_SIZE should be changed with level-defined picture size. See the
// decoder model implementation within the function
// av2_get_max_legal_dpb_size() in av2/encoder/level.c, which should be moved
// to "av2/common" to be able to use at the decoder side.
const int max_picture_size = MAX_PICTURE_SIZE;
const int max_legal_ref_frames =
get_max_legal_dpb_size(seq_params, max_picture_size);
if (seq_params->ref_frames > max_legal_ref_frames) {
avm_internal_error(&cm->error, AVM_CODEC_UNSUP_BITSTREAM,
"The maximum number of reference frames shall not be "
"greater than %d, yet the bitstream indicates that the "
"maximum DPB size is equal to %d.\n",
max_legal_ref_frames, seq_params->ref_frames);
}
seq_params->film_grain_params_present = avm_rb_read_bit(rb);
#if !CONFIG_IMPROVED_REORDER_SEQ_FLAGS
// Sequence header for coding tools beyond AV2
av2_read_sequence_header_beyond_av2(rb, seq_params
#if !CONFIG_F255_QMOBU
,
&cm->quant_params, &cm->error
#endif // !CONFIG_F255_QMOBU
);
#endif // !CONFIG_IMPROVED_REORDER_SEQ_FLAGS
#if !CONFIG_CWG_F270_CI_OBU
#if CONFIG_SCAN_TYPE_METADATA
seq_params->scan_type_info_present_flag = avm_rb_read_bit(rb);
if (seq_params->scan_type_info_present_flag) {
seq_params->scan_type_idc = avm_rb_read_literal(rb, 2);
seq_params->fixed_cvs_pic_rate_flag = avm_rb_read_bit(rb);
if (seq_params->fixed_cvs_pic_rate_flag)
seq_params->elemental_ct_duration_minus_1 = avm_rb_read_uvlc(rb);
else
seq_params->elemental_ct_duration_minus_1 = -1;
} else {
seq_params->scan_type_idc = 0;
seq_params->fixed_cvs_pic_rate_flag = 0;
seq_params->elemental_ct_duration_minus_1 = -1;
}
if (seq_params->elemental_ct_duration_minus_1 + 1 < 0 ||
seq_params->elemental_ct_duration_minus_1 + 1 > 2046) {
avm_internal_error(&cm->error, AVM_CODEC_UNSUP_BITSTREAM,
"The value of elemental_ct_duration_minus_1 + 1 shall "
"be in the range of 0 to 2046.\n",
seq_params->elemental_ct_duration_minus_1);
}
#endif // CONFIG_SCAN_TYPE_METADATA
#endif // !CONFIG_CWG_F270_CI_OBU
if (av2_check_trailing_bits(pbi, rb) != 0) {
// cm->error.error_code is already set.
return 0;
}
// If a sequence header has been decoded before, we check if the new
// one is consistent with the old one.
if (pbi->sequence_header_ready) {
if (!are_seq_headers_consistent(&cm->seq_params, seq_params)) {
pbi->sequence_header_changed = 1;
#if !CONFIG_F255_QMOBU
cm->quant_params.qmatrix_initialized = false;
#endif // !CONFIG_F255_QMOBU
reset_mfh_valid(cm);
}
}
#if CONFIG_F024_KEYOBU
pbi->is_first_layer_decoded = true;
for (int layer = 0; layer <= seq_params->max_mlayer_id; layer++)
cm->olk_refresh_frame_flags[layer] = -1;
#endif
cm->seq_params = *seq_params;
av2_set_frame_sb_size(cm, cm->seq_params.sb_size);
pbi->sequence_header_ready = 1;
return ((rb->bit_offset - saved_bit_offset + 7) >> 3);
}
static uint32_t read_multi_frame_header_obu(AV2Decoder *pbi,
struct avm_read_bit_buffer *rb) {
AV2_COMMON *const cm = &pbi->common;
const uint32_t saved_bit_offset = rb->bit_offset;
av2_read_multi_frame_header(cm, rb);
if (av2_check_trailing_bits(pbi, rb) != 0) {
// cm->error.error_code is already set.
return 0;
}
return ((rb->bit_offset - saved_bit_offset + 7) >> 3);
}
static uint32_t read_tilegroup_obu(AV2Decoder *pbi,
struct avm_read_bit_buffer *rb,
const uint8_t *data, const uint8_t *data_end,
const uint8_t **p_data_end,
OBU_TYPE obu_type, int *is_last_tg) {
AV2_COMMON *const cm = &pbi->common;
int start_tile, end_tile;
int32_t header_size, tg_payload_size;
assert(rb->bit_offset == 0);
assert(rb->bit_buffer == data);
int is_first_tg = 1; // return from av2_read_tilegroup_header
header_size =
av2_read_tilegroup_header(pbi, rb, data, p_data_end, &is_first_tg,
&start_tile, &end_tile, obu_type);
bool skip_payload = false;
#if CONFIG_F024_KEYOBU
skip_payload |= (obu_type == OBU_LEADING_SEF);
skip_payload |= (obu_type == OBU_REGULAR_SEF);
#else
skip_payload |= (obu_type == OBU_SEF);
#endif // CONFIG_F024_KEYOBU
#if CONFIG_F024_KEYOBU
skip_payload |= (obu_type == OBU_LEADING_TIP);
skip_payload |= (obu_type == OBU_REGULAR_TIP);
#else
skip_payload |= (obu_type == OBU_TIP);
#endif // CONFIG_F024_KEYOBU
skip_payload |= cm->bru.frame_inactive_flag;
skip_payload |= cm->bridge_frame_info.is_bridge_frame;
if (skip_payload) {
*is_last_tg = 1;
tg_payload_size = 0;
if (av2_check_trailing_bits(pbi, rb) != 0) {
// cm->error.error_code is already set.
return 0;
}
header_size = (int32_t)avm_rb_bytes_read(rb);
} else {
if (av2_check_byte_alignment(cm, rb)) return 0;
data += header_size;
av2_decode_tg_tiles_and_wrapup(pbi, data, data_end, p_data_end, start_tile,
end_tile, is_first_tg);
tg_payload_size = (uint32_t)(*p_data_end - data);
*is_last_tg = end_tile == cm->tiles.rows * cm->tiles.cols - 1;
}
return header_size + tg_payload_size;
}
// Returns the last nonzero byte index in 'data'. If there is no nonzero byte in
// 'data', returns -1.
static int get_last_nonzero_byte_index(const uint8_t *data, size_t sz) {
// Scan backward and return on the first nonzero byte.
int i = (int)sz - 1;
while (i >= 0 && data[i] == 0) {
--i;
}
return i;
}
// Allocates metadata that was read and adds it to the decoders metadata array.
static void alloc_read_metadata(AV2Decoder *const pbi,
OBU_METADATA_TYPE metadata_type,
const uint8_t *data, size_t sz,
avm_metadata_insert_flags_t insert_flag) {
AV2_COMMON *const cm = &pbi->common;
if (!pbi->metadata) {
pbi->metadata = avm_img_metadata_array_alloc(0);
if (!pbi->metadata) {
avm_internal_error(&cm->error, AVM_CODEC_MEM_ERROR,
"Failed to allocate metadata array");
}
}
avm_metadata_t *metadata =
avm_img_metadata_alloc(metadata_type, data, sz, insert_flag);
if (!metadata) {
avm_internal_error(&cm->error, AVM_CODEC_MEM_ERROR,
"Error allocating metadata");
}
avm_metadata_t **metadata_array =
(avm_metadata_t **)realloc(pbi->metadata->metadata_array,
(pbi->metadata->sz + 1) * sizeof(metadata));
if (!metadata_array) {
avm_img_metadata_free(metadata);
avm_internal_error(&cm->error, AVM_CODEC_MEM_ERROR,
"Error growing metadata array");
}
pbi->metadata->metadata_array = metadata_array;
pbi->metadata->metadata_array[pbi->metadata->sz] = metadata;
pbi->metadata->sz++;
}
// On failure, calls avm_internal_error() and does not return.
static void read_metadata_itut_t35(AV2Decoder *const pbi, const uint8_t *data,
size_t sz) {
AV2_COMMON *const cm = &pbi->common;
if (sz == 0) {
avm_internal_error(&cm->error, AVM_CODEC_CORRUPT_FRAME,
"itu_t_t35_country_code is missing");
}
int country_code_size = 1;
if (*data == 0xFF) {
if (sz == 1) {
avm_internal_error(&cm->error, AVM_CODEC_CORRUPT_FRAME,
"itu_t_t35_country_code_extension_byte is missing");
}
++country_code_size;
}
#if CONFIG_METADATA
const int end_index = (int)sz;
#else
int end_index = get_last_nonzero_byte_index(data, sz);
#endif // CONFIG_METADATA
if (end_index < country_code_size) {
avm_internal_error(&cm->error, AVM_CODEC_CORRUPT_FRAME,
"No trailing bits found in ITU-T T.35 metadata OBU");
}
#if !CONFIG_METADATA
// itu_t_t35_payload_bytes is byte aligned. Section 6.7.2 of the spec says:
// itu_t_t35_payload_bytes shall be bytes containing data registered as
// specified in Recommendation ITU-T T.35.
// Therefore the first trailing byte should be 0x80.
if (data[end_index] != 0x80) {
avm_internal_error(&cm->error, AVM_CODEC_CORRUPT_FRAME,
"The last nonzero byte of the ITU-T T.35 metadata OBU "
"is 0x%02x, should be 0x80.",
data[end_index]);
}
#endif // !CONFIG_METADATA
alloc_read_metadata(pbi, OBU_METADATA_TYPE_ITUT_T35, data, end_index,
AVM_MIF_ANY_FRAME);
}
// On failure, calls avm_internal_error() and does not return.
static void read_metadata_itut_t35_short(AV2Decoder *const pbi,
const uint8_t *data, size_t sz) {
AV2_COMMON *const cm = &pbi->common;
if (sz == 0) {
avm_internal_error(&cm->error, AVM_CODEC_CORRUPT_FRAME,
"itu_t_t35_country_code is missing");
}
int country_code_size = 1;
if (*data == 0xFF) {
if (sz == 1) {
avm_internal_error(&cm->error, AVM_CODEC_CORRUPT_FRAME,
"itu_t_t35_country_code_extension_byte is missing");
}
++country_code_size;
}
int end_index = get_last_nonzero_byte_index(data, sz);
if (end_index < country_code_size) {
avm_internal_error(&cm->error, AVM_CODEC_CORRUPT_FRAME,
"No trailing bits found in ITU-T T.35 metadata OBU");
}
// itu_t_t35_payload_bytes is byte aligned. Section 6.7.2 of the spec says:
// itu_t_t35_payload_bytes shall be bytes containing data registered as
// specified in Recommendation ITU-T T.35.
// Therefore the first trailing byte should be 0x80.
if (data[end_index] != 0x80) {
avm_internal_error(&cm->error, AVM_CODEC_CORRUPT_FRAME,
"The last nonzero byte of the ITU-T T.35 metadata OBU "
"is 0x%02x, should be 0x80.",
data[end_index]);
}
alloc_read_metadata(pbi, OBU_METADATA_TYPE_ITUT_T35, data, end_index,
AVM_MIF_ANY_FRAME);
}
// On success, returns the number of bytes read from 'data'. On failure, calls
// avm_internal_error() and does not return.
static size_t read_metadata_hdr_cll(AV2Decoder *const pbi, const uint8_t *data,
size_t sz) {
const size_t kHdrCllPayloadSize = 4;
AV2_COMMON *const cm = &pbi->common;
if (sz < kHdrCllPayloadSize) {
avm_internal_error(&cm->error, AVM_CODEC_CORRUPT_FRAME,
"Incorrect HDR CLL metadata payload size");
}
alloc_read_metadata(pbi, OBU_METADATA_TYPE_HDR_CLL, data, kHdrCllPayloadSize,
AVM_MIF_ANY_FRAME);
return kHdrCllPayloadSize;
}
// On success, returns the number of bytes read from 'data'. On failure, calls
// avm_internal_error() and does not return.
static size_t read_metadata_hdr_mdcv(AV2Decoder *const pbi, const uint8_t *data,
size_t sz) {
const size_t kMdcvPayloadSize = 24;
AV2_COMMON *const cm = &pbi->common;
if (sz < kMdcvPayloadSize) {
avm_internal_error(&cm->error, AVM_CODEC_CORRUPT_FRAME,
"Incorrect HDR MDCV metadata payload size");
}
alloc_read_metadata(pbi, OBU_METADATA_TYPE_HDR_MDCV, data, kMdcvPayloadSize,
AVM_MIF_ANY_FRAME);
return kMdcvPayloadSize;
}
// On success, returns the number of bytes read from 'data'. On failure, calls
// avm_internal_error() and does not return.
static size_t read_metadata_banding_hints(AV2Decoder *const pbi,
const uint8_t *data, size_t sz) {
AV2_COMMON *const cm = &pbi->common;
// Validate minimum payload size (at least 3 bits for basic flags)
if (sz == 0) {
avm_internal_error(&cm->error, AVM_CODEC_CORRUPT_FRAME,
"Empty banding hints metadata payload");
}
// Store the raw payload in the generic metadata array
alloc_read_metadata(pbi, OBU_METADATA_TYPE_BANDING_HINTS, data, sz,
AVM_MIF_ANY_FRAME);
return sz;
}
#if CONFIG_ICC_METADATA
// On success, returns the number of bytes read from 'data'. On failure, calls
// avm_internal_error() and does not return.
static size_t read_metadata_icc_profile(AV2Decoder *const pbi,
const uint8_t *data, size_t sz) {
const size_t kMinIccProfileHeaderSize = 128;
AV2_COMMON *const cm = &pbi->common;
if (sz < kMinIccProfileHeaderSize) {
avm_internal_error(&cm->error, AVM_CODEC_CORRUPT_FRAME,
"Incorrect ICC profile metadata payload size");
}
alloc_read_metadata(pbi, OBU_METADATA_TYPE_ICC_PROFILE, data, sz,
AVM_MIF_ANY_FRAME);
return sz;
}
#endif // CONFIG_ICC_METADATA
#if CONFIG_SCAN_TYPE_METADATA
// On success, returns the number of bytes read from 'data'. On failure, calls
// avm_internal_error() and does not return.
static void read_metadata_scan_type(AV2Decoder *const pbi,
struct avm_read_bit_buffer *rb) {
AV2_COMMON *const cm = &pbi->common;
cm->pic_struct_metadata_params.mps_pic_struct_type =
avm_rb_read_literal(rb, 5);
cm->pic_struct_metadata_params.mps_source_scan_type_idc =
avm_rb_read_literal(rb, 2);
cm->pic_struct_metadata_params.mps_duplicate_flag = avm_rb_read_bit(rb);
uint8_t payload[1];
payload[0] = (cm->pic_struct_metadata_params.mps_pic_struct_type << 3) |
(cm->pic_struct_metadata_params.mps_source_scan_type_idc << 1) |
cm->pic_struct_metadata_params.mps_duplicate_flag;
alloc_read_metadata(pbi, OBU_METADATA_TYPE_SCAN_TYPE, payload, 1,
AVM_MIF_ANY_FRAME);
}
#endif // CONFIG_SCAN_TYPE_METADATA
#if CONFIG_CWG_F430
// On success, returns the number of bytes read from 'data'. On failure, calls
// avm_internal_error() and does not return.
static void read_metadata_temporal_point_info(AV2Decoder *const pbi,
struct avm_read_bit_buffer *rb) {
AV2_COMMON *const cm = &pbi->common;
cm->temporal_point_info_metadata.mtpi_frame_presentation_length =
avm_rb_read_unsigned_literal(rb, 5) + 1;
int n = cm->temporal_point_info_metadata.mtpi_frame_presentation_length;
cm->temporal_point_info_metadata.mtpi_frame_presentation_time =
avm_rb_read_literal(rb, n);
#if CONFIG_METADATA
uint8_t payload[1];
payload[0] =
(cm->temporal_point_info_metadata.mtpi_frame_presentation_time & 0XFF);
alloc_read_metadata(pbi, OBU_METADATA_TYPE_TEMPORAL_POINT_INFO, payload, 1,
AVM_MIF_ANY_FRAME);
#endif // CONFIG_METADATA
}
#endif // CONFIG_CWG_F430
static int read_metadata_frame_hash(AV2Decoder *const pbi,
struct avm_read_bit_buffer *rb) {
AV2_COMMON *const cm = &pbi->common;
const unsigned hash_type = avm_rb_read_literal(rb, 4);
const unsigned per_plane = avm_rb_read_bit(rb);
const unsigned has_grain = avm_rb_read_bit(rb);
avm_rb_read_literal(rb, 2); // reserved
// If hash_type is reserved for future use, ignore the entire OBU
if (hash_type) return -1;
FrameHash *const frame_hash = has_grain ? &cm->cur_frame->grain_frame_hash
: &cm->cur_frame->raw_frame_hash;
memset(frame_hash, 0, sizeof(*frame_hash));
frame_hash->hash_type = hash_type;
frame_hash->per_plane = per_plane;
frame_hash->has_grain = has_grain;
if (per_plane) {
const int num_planes = av2_num_planes(cm);
for (int i = 0; i < num_planes; ++i) {
PlaneHash *plane = &frame_hash->plane[i];
for (size_t j = 0; j < 16; ++j)
plane->md5[j] = avm_rb_read_literal(rb, 8);
}
} else {
PlaneHash *plane = &frame_hash->plane[0];
for (size_t i = 0; i < 16; ++i) plane->md5[i] = avm_rb_read_literal(rb, 8);
}
frame_hash->is_present = 1;
return 0;
}
static void scalability_structure(struct avm_read_bit_buffer *rb) {
const int spatial_layers_cnt_minus_1 = avm_rb_read_literal(rb, 2);
const int spatial_layer_dimensions_present_flag = avm_rb_read_bit(rb);
const int spatial_layer_description_present_flag = avm_rb_read_bit(rb);
const int temporal_group_description_present_flag = avm_rb_read_bit(rb);
avm_rb_read_literal(rb, 3); // reserved
if (spatial_layer_dimensions_present_flag) {
for (int i = 0; i <= spatial_layers_cnt_minus_1; i++) {
avm_rb_read_literal(rb, 16);
avm_rb_read_literal(rb, 16);
}
}
if (spatial_layer_description_present_flag) {
for (int i = 0; i <= spatial_layers_cnt_minus_1; i++) {
avm_rb_read_literal(rb, 8);
}
}
if (temporal_group_description_present_flag) {
const int temporal_group_size = avm_rb_read_literal(rb, 8);
for (int i = 0; i < temporal_group_size; i++) {
avm_rb_read_literal(rb, 3);
avm_rb_read_bit(rb);
avm_rb_read_bit(rb);
const int temporal_group_ref_cnt = avm_rb_read_literal(rb, 3);
for (int j = 0; j < temporal_group_ref_cnt; j++) {
avm_rb_read_literal(rb, 8);
}
}
}
}
static void read_metadata_scalability(struct avm_read_bit_buffer *rb) {
const int scalability_mode_idc = avm_rb_read_literal(rb, 8);
if (scalability_mode_idc == SCALABILITY_SS) {
scalability_structure(rb);
}
}
static void read_metadata_timecode(struct avm_read_bit_buffer *rb) {
avm_rb_read_literal(rb, 5); // counting_type f(5)
const int full_timestamp_flag =
avm_rb_read_bit(rb); // full_timestamp_flag f(1)
avm_rb_read_bit(rb); // discontinuity_flag (f1)
avm_rb_read_bit(rb); // cnt_dropped_flag f(1)
avm_rb_read_literal(rb, 9); // n_frames f(9)
if (full_timestamp_flag) {
avm_rb_read_literal(rb, 6); // seconds_value f(6)
avm_rb_read_literal(rb, 6); // minutes_value f(6)
avm_rb_read_literal(rb, 5); // hours_value f(5)
} else {
const int seconds_flag = avm_rb_read_bit(rb); // seconds_flag f(1)
if (seconds_flag) {
avm_rb_read_literal(rb, 6); // seconds_value f(6)
const int minutes_flag = avm_rb_read_bit(rb); // minutes_flag f(1)
if (minutes_flag) {
avm_rb_read_literal(rb, 6); // minutes_value f(6)
const int hours_flag = avm_rb_read_bit(rb); // hours_flag f(1)
if (hours_flag) {
avm_rb_read_literal(rb, 5); // hours_value f(5)
}
}
}
}
// time_offset_length f(5)
const int time_offset_length = avm_rb_read_literal(rb, 5);
if (time_offset_length) {
// time_offset_value f(time_offset_length)
avm_rb_read_literal(rb, time_offset_length);
}
}
// Returns the last nonzero byte in 'data'. If there is no nonzero byte in
// 'data', returns 0.
//
// Call this function to check the following requirement in the spec:
// This implies that when any payload data is present for this OBU type, at
// least one byte of the payload data (including the trailing bit) shall not
// be equal to 0.
static uint8_t get_last_nonzero_byte(const uint8_t *data, size_t sz) {
// Scan backward and return on the first nonzero byte.
size_t i = sz;
while (i != 0) {
--i;
if (data[i] != 0) return data[i];
}
return 0;
}
// Checks the metadata for correct syntax but ignores the parsed metadata.
//
// On success, returns the number of bytes read from 'data'. On failure, sets
// pbi->common.error.error_code and returns 0, or calls avm_internal_error()
// and does not return.
#if CONFIG_METADATA
static size_t read_metadata_unit_payload(AV2Decoder *pbi, const uint8_t *data,
avm_metadata_t *metadata)
#else
static size_t read_metadata(AV2Decoder *pbi, const uint8_t *data, size_t sz)
#endif // CONFIG_METADATA
{
#if !CONFIG_METADATA
AV2_COMMON *const cm = &pbi->common;
size_t type_length;
uint64_t type_value;
if (avm_uleb_decode(data, sz, &type_value, &type_length) < 0) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
const OBU_METADATA_TYPE metadata_type = (OBU_METADATA_TYPE)type_value;
#else
size_t type_length = 0;
const OBU_METADATA_TYPE metadata_type = metadata->type;
const size_t sz = metadata->sz;
#endif // !CONFIG_METADATA
#if CONFIG_METADATA
int known_metadata_type = metadata_type >= OBU_METADATA_TYPE_HDR_CLL &&
metadata_type < NUM_OBU_METADATA_TYPES;
known_metadata_type |= metadata_type == OBU_METADATA_TYPE_ICC_PROFILE;
#if CONFIG_SCAN_TYPE_METADATA
known_metadata_type |= metadata_type == OBU_METADATA_TYPE_SCAN_TYPE;
#endif // CONFIG_SCAN_TYPE_METADATA
#if CONFIG_CWG_F430
known_metadata_type |= metadata_type == OBU_METADATA_TYPE_TEMPORAL_POINT_INFO;
#endif // CONFIG_CWG_F430
if (!known_metadata_type)
#else // CONFIG_ICC_METADATA
if (metadata_type == 0 || metadata_type >= 8)
#endif // CONFIG_ICC_METADATA
{
#if !CONFIG_METADATA
// If metadata_type is reserved for future use or a user private value,
// ignore the entire OBU and just check trailing bits.
if (get_last_nonzero_byte(data + type_length, sz - type_length) == 0) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
#endif // !CONFIG_METADATA
return sz;
}
if (metadata_type == OBU_METADATA_TYPE_ITUT_T35) {
#if !CONFIG_METADATA
// read_metadata_itut_t35() checks trailing bits.
#endif // !CONFIG_METADATA
read_metadata_itut_t35(pbi, data + type_length, sz - type_length);
return sz;
} else if (metadata_type == OBU_METADATA_TYPE_HDR_CLL) {
#if !CONFIG_METADATA
size_t bytes_read =
type_length +
#endif // !CONFIG_METADATA
read_metadata_hdr_cll(pbi, data + type_length, sz - type_length);
#if !CONFIG_METADATA
if (get_last_nonzero_byte(data + bytes_read, sz - bytes_read) != 0x80) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
#endif // !CONFIG_METADATA
return sz;
} else if (metadata_type == OBU_METADATA_TYPE_HDR_MDCV) {
#if !CONFIG_METADATA
size_t bytes_read =
type_length +
#endif // !CONFIG_METADATA
read_metadata_hdr_mdcv(pbi, data + type_length, sz - type_length);
#if !CONFIG_METADATA
if (get_last_nonzero_byte(data + bytes_read, sz - bytes_read) != 0x80) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
#endif // !CONFIG_METADATA
return sz;
} else if (metadata_type == OBU_METADATA_TYPE_BANDING_HINTS) {
#if !CONFIG_METADATA
size_t bytes_read =
type_length +
#endif // !CONFIG_METADATA
read_metadata_banding_hints(pbi, data + type_length, sz - type_length);
#if !CONFIG_METADATA
if (get_last_nonzero_byte(data + bytes_read, sz - bytes_read) != 0x80) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
return sz;
#endif // !CONFIG_METADATA
#if CONFIG_SCAN_TYPE_METADATA
} else if (metadata_type == OBU_METADATA_TYPE_SCAN_TYPE) {
struct avm_read_bit_buffer rb;
av2_init_read_bit_buffer(pbi, &rb, data + type_length, data + sz);
read_metadata_scan_type(pbi, &rb);
return sz;
#endif // CONFIG_SCAN_TYPE_METADATA
#if CONFIG_CWG_F430
} else if (metadata_type == OBU_METADATA_TYPE_TEMPORAL_POINT_INFO) {
struct avm_read_bit_buffer rb;
av2_init_read_bit_buffer(pbi, &rb, data + type_length, data + sz);
read_metadata_temporal_point_info(pbi, &rb);
return sz;
#endif // CONFIG_CWG_F430
#if CONFIG_METADATA
} else if (metadata_type == OBU_METADATA_TYPE_ICC_PROFILE) {
#if !CONFIG_METADATA
size_t bytes_read =
type_length +
#endif // !CONFIG_METADATA
read_metadata_icc_profile(pbi, data + type_length, sz - type_length);
#if !CONFIG_METADATA
if (get_last_nonzero_byte(data + bytes_read, sz - bytes_read) != 0x80) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
#endif // !CONFIG_METADATA
return sz;
#endif // CONFIG_ICC_METADATA
}
struct avm_read_bit_buffer rb;
av2_init_read_bit_buffer(pbi, &rb, data + type_length, data + sz);
if (metadata_type == OBU_METADATA_TYPE_SCALABILITY) {
read_metadata_scalability(&rb);
} else if (metadata_type == OBU_METADATA_TYPE_DECODED_FRAME_HASH) {
if (read_metadata_frame_hash(pbi, &rb)) {
#if !CONFIG_METADATA
// Unsupported Decoded Frame Hash metadata. Ignoring the entire OBU and
// just checking trailing bits
if (get_last_nonzero_byte(data + type_length, sz - type_length) == 0) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
#endif // !CONFIG_METADATA
return sz;
}
} else {
assert(metadata_type == OBU_METADATA_TYPE_TIMECODE);
read_metadata_timecode(&rb);
}
#if !CONFIG_METADATA
if (av2_check_trailing_bits(pbi, &rb) != 0) {
// cm->error.error_code is already set.
return 0;
}
#endif // !CONFIG_METADATA
assert((rb.bit_offset & 7) == 0);
return type_length + (rb.bit_offset >> 3);
}
#if CONFIG_METADATA
static size_t read_metadata_obsp(AV2Decoder *pbi, const uint8_t *data,
size_t sz,
avm_metadata_array_t *metadata_array,
avm_metadata_t *metadata_base,
int expected_suffix) {
AV2_COMMON *const cm = &pbi->common;
struct avm_read_bit_buffer rb;
av2_init_read_bit_buffer(pbi, &rb, data, data + sz);
metadata_base->is_suffix = avm_rb_read_literal(&rb, 1);
// Validate suffix bit if requested
if (expected_suffix >= 0 && metadata_base->is_suffix != expected_suffix) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
metadata_base->necessity_idc =
(avm_metadata_necessity_t)avm_rb_read_literal(&rb, 2);
metadata_base->application_id =
(avm_metadata_application_id_t)avm_rb_read_literal(&rb, 5);
const size_t bytes_read = avm_rb_bytes_read(&rb);
assert(bytes_read == 1);
size_t count_length;
uint64_t count_minus_1;
if (avm_uleb_decode(data + bytes_read, sz - bytes_read, &count_minus_1,
&count_length) < 0) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
metadata_array->sz = count_minus_1 + 1;
// Ensure metadata_unit_cnt doesn't exceed 2^14 (uleb128 <= 2 bytes)
if (metadata_array->sz > 16384) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
return bytes_read + count_length;
}
static size_t read_metadata_unit_header(AV2Decoder *pbi, const uint8_t *data,
size_t sz, avm_metadata_t *metadata,
const ObuHeader *obu_header) {
AV2_COMMON *const cm = &pbi->common;
size_t type_length;
uint64_t type_value;
if (avm_uleb_decode(data, sz, &type_value, &type_length) < 0) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
metadata->type = (uint32_t)type_value;
size_t bytes_read = type_length;
struct avm_read_bit_buffer rb;
av2_init_read_bit_buffer(pbi, &rb, data + bytes_read, data + sz);
const size_t muh_header_size = avm_rb_read_literal(&rb, 7);
metadata->cancel_flag = avm_rb_read_literal(&rb, 1);
assert(avm_rb_bytes_read(&rb) == 1);
bytes_read += avm_rb_bytes_read(&rb);
const size_t total_size = bytes_read + muh_header_size;
assert(total_size <= sz);
if (!metadata->cancel_flag) {
size_t size_length;
uint64_t size_value = 0;
if (avm_uleb_decode(data + bytes_read, sz - bytes_read, &size_value,
&size_length) < 0) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
metadata->sz = size_value;
bytes_read += size_length;
av2_init_read_bit_buffer(pbi, &rb, data + bytes_read, data + sz);
metadata->layer_idc = (avm_metadata_layer_t)avm_rb_read_literal(&rb, 3);
metadata->persistence_idc =
(avm_metadata_persistence_t)avm_rb_read_literal(&rb, 3);
metadata->priority = avm_rb_read_literal(&rb, 8);
avm_rb_read_literal(&rb, 2); // reserved bits
assert(avm_rb_bytes_read(&rb) == 2);
if (metadata->layer_idc == AVM_LAYER_VALUES) {
if (obu_header->obu_xlayer_id == 31) {
metadata->xlayer_map = avm_rb_read_unsigned_literal(&rb, 32);
assert((metadata->xlayer_map & (1u << 31)) == 0);
for (int n = 0; n < 31; n++) {
if (metadata->xlayer_map & (1u << n)) {
metadata->mlayer_map[n] = avm_rb_read_unsigned_literal(&rb, 8);
}
}
} else {
metadata->mlayer_map[obu_header->obu_xlayer_id] =
avm_rb_read_unsigned_literal(&rb, 8);
}
}
bytes_read += avm_rb_bytes_read(&rb);
}
assert(bytes_read <= total_size);
return total_size;
}
static size_t read_metadata_obu(AV2Decoder *pbi, const uint8_t *data, size_t sz,
ObuHeader *obu_header, int expected_suffix) {
AV2_COMMON *const cm = &pbi->common;
avm_metadata_array_t metadata_array = { 0 };
avm_metadata_t metadata_base;
memset(&metadata_base, 0, sizeof(metadata_base));
size_t bytes_read = read_metadata_obsp(pbi, data, sz, &metadata_array,
&metadata_base, expected_suffix);
for (uint32_t i = 0; i < metadata_array.sz; i++) {
avm_metadata_t metadata = { 0 };
// copy shared fields read in `read_metadata_obsp`
memcpy(&metadata, &metadata_base, sizeof(metadata));
const size_t muh_size = read_metadata_unit_header(
pbi, data + bytes_read, sz - bytes_read, &metadata, obu_header);
if (muh_size == 0) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
bytes_read += muh_size;
if (!metadata.cancel_flag) {
if (sz - bytes_read < metadata.sz) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
const size_t mup_size =
read_metadata_unit_payload(pbi, data + bytes_read, &metadata);
bytes_read += mup_size;
}
}
if (bytes_read >= sz || data[bytes_read] != 0x80) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
return bytes_read + 1;
}
#endif // CONFIG_METADATA
// Checks the metadata for correct syntax but ignores the parsed metadata.
//
// On success, returns the number of bytes read from 'data'. On failure, sets
// pbi->common.error.error_code and returns 0, or calls avm_internal_error()
// and does not return.
// expected_suffix: 0 for prefix metadata, 1 for suffix metadata, -1 for no
// validation
static size_t read_metadata_short(AV2Decoder *pbi, const uint8_t *data,
size_t sz, int expected_suffix) {
AV2_COMMON *const cm = &pbi->common;
size_t type_length;
uint64_t type_value;
struct avm_read_bit_buffer rb;
av2_init_read_bit_buffer(pbi, &rb, data, data + sz);
uint8_t metadata_is_suffix = avm_rb_read_bit(&rb);
// Validate suffix bit if requested
if (expected_suffix >= 0 && metadata_is_suffix != expected_suffix) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
uint8_t muh_layer_idc = avm_rb_read_literal(&rb, 3);
uint8_t muh_cancel_flag = avm_rb_read_bit(&rb);
uint8_t muh_persistence_idc = avm_rb_read_literal(&rb, 3);
if (avm_uleb_decode(
data + 1, // read type from the position data + 1
sz - 1, // one less bytes available due to extra parameters
&type_value, &type_length) < 0) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
const OBU_METADATA_TYPE metadata_type = (OBU_METADATA_TYPE)type_value;
// Increase the type_length by 1 byte since there is one prefix byte added
// before the type
++type_length;
if (muh_cancel_flag) return sz;
// Update the metadata with the header fields we read
if (pbi->metadata && pbi->metadata->sz > 0) {
avm_metadata_t *last_metadata =
pbi->metadata->metadata_array[pbi->metadata->sz - 1];
if (last_metadata && last_metadata->type == OBU_METADATA_TYPE_ITUT_T35) {
last_metadata->is_suffix = metadata_is_suffix;
last_metadata->layer_idc = muh_layer_idc;
last_metadata->cancel_flag = muh_cancel_flag;
last_metadata->persistence_idc = muh_persistence_idc;
}
}
const bool known_metadata_type =
(metadata_type > OBU_METADATA_TYPE_AVM_RESERVED_0) &&
(metadata_type < NUM_OBU_METADATA_TYPES);
if (!known_metadata_type) {
// If metadata_type is reserved for future use or a user private value,
// ignore the entire OBU and just check trailing bits.
if (get_last_nonzero_byte(data + type_length, sz - type_length) == 0) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
return sz;
}
if (metadata_type == OBU_METADATA_TYPE_ITUT_T35) {
// read_metadata_itut_t35() checks trailing bits.
read_metadata_itut_t35_short(pbi, data + type_length, sz - type_length);
// Update the metadata with the header fields we read
if (pbi->metadata && pbi->metadata->sz > 0) {
avm_metadata_t *last_metadata =
pbi->metadata->metadata_array[pbi->metadata->sz - 1];
if (last_metadata && last_metadata->type == OBU_METADATA_TYPE_ITUT_T35) {
last_metadata->is_suffix = metadata_is_suffix;
last_metadata->layer_idc = muh_layer_idc;
last_metadata->cancel_flag = muh_cancel_flag;
last_metadata->persistence_idc = muh_persistence_idc;
}
}
return sz;
} else if (metadata_type == OBU_METADATA_TYPE_HDR_CLL) {
size_t bytes_read =
type_length +
read_metadata_hdr_cll(pbi, data + type_length, sz - type_length);
if (get_last_nonzero_byte(data + bytes_read, sz - bytes_read) != 0x80) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
// Update the metadata with the header fields we read
if (pbi->metadata && pbi->metadata->sz > 0) {
avm_metadata_t *last_metadata =
pbi->metadata->metadata_array[pbi->metadata->sz - 1];
if (last_metadata && last_metadata->type == OBU_METADATA_TYPE_HDR_CLL) {
last_metadata->is_suffix = metadata_is_suffix;
last_metadata->layer_idc = muh_layer_idc;
last_metadata->cancel_flag = muh_cancel_flag;
last_metadata->persistence_idc = muh_persistence_idc;
}
}
return sz;
} else if (metadata_type == OBU_METADATA_TYPE_HDR_MDCV) {
size_t bytes_read =
type_length +
read_metadata_hdr_mdcv(pbi, data + type_length, sz - type_length);
if (get_last_nonzero_byte(data + bytes_read, sz - bytes_read) != 0x80) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
// Update the metadata with the header fields we read
if (pbi->metadata && pbi->metadata->sz > 0) {
avm_metadata_t *last_metadata =
pbi->metadata->metadata_array[pbi->metadata->sz - 1];
if (last_metadata && last_metadata->type == OBU_METADATA_TYPE_HDR_MDCV) {
last_metadata->is_suffix = metadata_is_suffix;
last_metadata->layer_idc = muh_layer_idc;
last_metadata->cancel_flag = muh_cancel_flag;
last_metadata->persistence_idc = muh_persistence_idc;
}
}
return sz;
} else if (metadata_type == OBU_METADATA_TYPE_BANDING_HINTS) {
size_t bytes_read =
type_length +
read_metadata_banding_hints(pbi, data + type_length, sz - type_length);
if (get_last_nonzero_byte(data + bytes_read, sz - bytes_read) != 0x80) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
return sz;
#if CONFIG_SCAN_TYPE_METADATA
} else if (metadata_type == OBU_METADATA_TYPE_SCAN_TYPE) {
const size_t kMinScanTypeHeaderSize = 1;
if (sz < kMinScanTypeHeaderSize) {
avm_internal_error(&cm->error, AVM_CODEC_CORRUPT_FRAME,
"Incorrect scan type metadata payload size");
}
av2_init_read_bit_buffer(pbi, &rb, data + type_length, data + sz);
read_metadata_scan_type(pbi, &rb);
return sz;
#endif // CONFIG_SCAN_TYPE_METADATA
#if CONFIG_CWG_F430
} else if (metadata_type == OBU_METADATA_TYPE_TEMPORAL_POINT_INFO) {
const size_t kMinTemporalPointInfoHeaderSize = 1;
if (sz < kMinTemporalPointInfoHeaderSize) {
avm_internal_error(&cm->error, AVM_CODEC_CORRUPT_FRAME,
"Incorrect temporal point info metadata payload size");
}
av2_init_read_bit_buffer(pbi, &rb, data + type_length, data + sz);
read_metadata_temporal_point_info(pbi, &rb);
return sz;
#endif // CONFIG_CWG_F430
}
av2_init_read_bit_buffer(pbi, &rb, data + type_length, data + sz);
if (metadata_type == OBU_METADATA_TYPE_SCALABILITY) {
read_metadata_scalability(&rb);
} else if (metadata_type == OBU_METADATA_TYPE_DECODED_FRAME_HASH) {
if (read_metadata_frame_hash(pbi, &rb)) {
// Unsupported Decoded Frame Hash metadata. Ignoring the entire OBU and
// just checking trailing bits
if (get_last_nonzero_byte(data + type_length, sz - type_length) == 0) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
return sz;
}
} else {
assert(metadata_type == OBU_METADATA_TYPE_TIMECODE);
read_metadata_timecode(&rb);
}
if (av2_check_trailing_bits(pbi, &rb) != 0) {
// cm->error.error_code is already set.
return 0;
}
assert((rb.bit_offset & 7) == 0);
return type_length + (rb.bit_offset >> 3);
}
// On success, returns 'sz'. On failure, sets pbi->common.error.error_code and
// returns 0.
static size_t read_padding(AV2_COMMON *const cm, const uint8_t *data,
size_t sz) {
// The spec allows a padding OBU to be header-only (i.e., obu_size = 0). So
// check trailing bits only if sz > 0.
if (sz > 0) {
// The payload of a padding OBU is byte aligned. Therefore the first
// trailing byte should be 0x80. See https://crbug.com/aomedia/2393.
const uint8_t last_nonzero_byte = get_last_nonzero_byte(data, sz);
if (last_nonzero_byte != 0x80) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return 0;
}
}
return sz;
}
// Check the obu type is a kind of coded frame
static int is_coded_frame(OBU_TYPE obu_type) {
#if CONFIG_F024_KEYOBU
return obu_type == OBU_REGULAR_SEF || obu_type == OBU_REGULAR_TIP ||
obu_type == OBU_SWITCH || obu_type == OBU_RAS_FRAME ||
obu_type == OBU_BRIDGE_FRAME || obu_type == OBU_REGULAR_TILE_GROUP ||
obu_type == OBU_LEADING_SEF || obu_type == OBU_LEADING_TIP ||
obu_type == OBU_LEADING_TILE_GROUP || obu_type == OBU_CLK ||
obu_type == OBU_OLK;
#else
return obu_type == OBU_SEF || obu_type == OBU_TIP || obu_type == OBU_SWITCH ||
obu_type == OBU_RAS_FRAME || obu_type == OBU_BRIDGE_FRAME ||
obu_type == OBU_TILE_GROUP;
#endif
}
// Check the obu type ordering within a temporal unit
// as a part of checking bitstream conformance.
// On success, return 0. If failed return 1.
#if OBU_ORDER_IN_TU
static int check_obu_order(OBU_TYPE prev_obu_type, OBU_TYPE curr_obu_type) {
// TODO: avm#1115 - Rewrite check_obu_order() to better express all OBU
// ordering constraints.
#if CONFIG_F153_FGM_OBU
if (curr_obu_type == OBU_FGM || prev_obu_type == OBU_FGM) {
return 0;
}
#endif // CONFIG_F153_FGM_OBU
#if CONFIG_F255_QMOBU
if (is_coded_frame(curr_obu_type) && prev_obu_type == OBU_QM) {
return 0;
} else if (curr_obu_type == OBU_QM) {
return 0;
} else
#endif
if ((prev_obu_type == OBU_TEMPORAL_DELIMITER) &&
(curr_obu_type == OBU_MSDO ||
curr_obu_type == OBU_LAYER_CONFIGURATION_RECORD ||
curr_obu_type == OBU_ATLAS_SEGMENT ||
curr_obu_type == OBU_OPERATING_POINT_SET ||
curr_obu_type == OBU_SEQUENCE_HEADER ||
#if CONFIG_CWG_F270_CI_OBU
curr_obu_type == OBU_CONTENT_INTERPRETATION ||
#endif // CONFIG_CWG_F270_CI_OBU
curr_obu_type == OBU_MULTI_FRAME_HEADER ||
is_coded_frame(curr_obu_type) || IS_METADATA_OBU(curr_obu_type))) {
return 0;
} else if ((prev_obu_type == OBU_MSDO) &&
(curr_obu_type == OBU_LAYER_CONFIGURATION_RECORD ||
curr_obu_type == OBU_ATLAS_SEGMENT ||
curr_obu_type == OBU_OPERATING_POINT_SET ||
curr_obu_type == OBU_SEQUENCE_HEADER ||
#if CONFIG_CWG_F270_CI_OBU
curr_obu_type == OBU_CONTENT_INTERPRETATION ||
#endif // CONFIG_CWG_F270_CI_OBU
curr_obu_type == OBU_MULTI_FRAME_HEADER ||
is_coded_frame(curr_obu_type) ||
IS_METADATA_OBU(curr_obu_type))) {
return 0;
} else if ((prev_obu_type == OBU_LAYER_CONFIGURATION_RECORD) &&
(curr_obu_type == OBU_LAYER_CONFIGURATION_RECORD ||
curr_obu_type == OBU_ATLAS_SEGMENT ||
curr_obu_type == OBU_OPERATING_POINT_SET ||
curr_obu_type == OBU_SEQUENCE_HEADER ||
#if CONFIG_CWG_F270_CI_OBU
curr_obu_type == OBU_CONTENT_INTERPRETATION ||
#endif // CONFIG_CWG_F270_CI_OBU
curr_obu_type == OBU_MULTI_FRAME_HEADER ||
is_coded_frame(curr_obu_type) ||
IS_METADATA_OBU(curr_obu_type))) {
return 0;
} else if ((prev_obu_type == OBU_OPERATING_POINT_SET) &&
(curr_obu_type == OBU_OPERATING_POINT_SET ||
curr_obu_type == OBU_ATLAS_SEGMENT ||
curr_obu_type == OBU_SEQUENCE_HEADER ||
#if CONFIG_CWG_F270_CI_OBU
curr_obu_type == OBU_CONTENT_INTERPRETATION ||
#endif // CONFIG_CWG_F270_CI_OBU
curr_obu_type == OBU_MULTI_FRAME_HEADER ||
is_coded_frame(curr_obu_type) ||
IS_METADATA_OBU(curr_obu_type))) {
return 0;
} else if ((prev_obu_type == OBU_ATLAS_SEGMENT) &&
(curr_obu_type == OBU_ATLAS_SEGMENT ||
curr_obu_type == OBU_SEQUENCE_HEADER ||
#if CONFIG_CWG_F270_CI_OBU
curr_obu_type == OBU_CONTENT_INTERPRETATION ||
#endif // CONFIG_CWG_F270_CI_OBU
curr_obu_type == OBU_MULTI_FRAME_HEADER ||
is_coded_frame(curr_obu_type) ||
IS_METADATA_OBU(curr_obu_type))) {
return 0;
} else if ((prev_obu_type == OBU_SEQUENCE_HEADER) &&
(curr_obu_type == OBU_SEQUENCE_HEADER ||
#if CONFIG_CWG_F270_CI_OBU
curr_obu_type == OBU_CONTENT_INTERPRETATION ||
#endif // CONFIG_CWG_F270_CI_OBU
curr_obu_type == OBU_MULTI_FRAME_HEADER ||
curr_obu_type == OBU_BUFFER_REMOVAL_TIMING ||
is_coded_frame(curr_obu_type) ||
IS_METADATA_OBU(curr_obu_type))) {
return 0;
#if CONFIG_CWG_F270_CI_OBU
} else if ((prev_obu_type == OBU_CONTENT_INTERPRETATION) &&
(curr_obu_type == OBU_MULTI_FRAME_HEADER ||
curr_obu_type == OBU_BUFFER_REMOVAL_TIMING ||
is_coded_frame(curr_obu_type) ||
IS_METADATA_OBU(curr_obu_type))) {
return 0;
#endif // CONFIG_CWG_F270_CI_OBU
} else if ((prev_obu_type == OBU_BUFFER_REMOVAL_TIMING) &&
(curr_obu_type == OBU_MULTI_FRAME_HEADER ||
is_coded_frame(curr_obu_type) ||
IS_METADATA_OBU(curr_obu_type))) {
return 0;
} else if ((prev_obu_type == OBU_MULTI_FRAME_HEADER) &&
(curr_obu_type == OBU_MULTI_FRAME_HEADER ||
is_coded_frame(curr_obu_type) ||
IS_METADATA_OBU(curr_obu_type))) {
return 0;
} else if ((IS_METADATA_OBU(prev_obu_type)) &&
(is_coded_frame(curr_obu_type) || IS_METADATA_OBU(curr_obu_type) ||
curr_obu_type == OBU_TEMPORAL_DELIMITER)) {
return 0;
} else if (prev_obu_type == OBU_TEMPORAL_DELIMITER ||
is_coded_frame(prev_obu_type) || prev_obu_type == OBU_PADDING) {
return 0;
}
return 1;
}
#endif // OBU_ORDER_IN_TU
#if CONFIG_F024_KEYOBU
int av2_ci_keyframe_in_temporal_unit(struct AV2Decoder *pbi,
const uint8_t *data, size_t data_sz) {
const uint8_t *data_read = data;
ObuHeader obu_header;
memset(&obu_header, 0, sizeof(obu_header));
int keyframe_present = 0;
int ci_present = 0;
while (data_read < data + data_sz) {
size_t payload_size = 0;
size_t bytes_read = 0;
avm_read_obu_header_and_size(data_read, data_sz, &obu_header, &payload_size,
&bytes_read);
keyframe_present =
(obu_header.type == OBU_CLK || obu_header.type == OBU_OLK);
ci_present = (obu_header.type == OBU_CONTENT_INTERPRETATION);
data_read += bytes_read + payload_size;
}
// * 0. CLK/OLK signalled without CI
// * 1. CI obu signalled without CLK/OLK
// * 2. CI obu signalled with CLK/OLK
if (!ci_present && keyframe_present)
pbi->ci_and_key_per_layer[obu_header.obu_mlayer_id] = 0;
else if (ci_present && !keyframe_present)
pbi->ci_and_key_per_layer[obu_header.obu_mlayer_id] = 1;
else if (ci_present && keyframe_present)
pbi->ci_and_key_per_layer[obu_header.obu_mlayer_id] = 2;
return 0;
}
#endif
#if CONFIG_F024_KEYOBU
int av2_is_random_accessed_temporal_unit(const uint8_t *data, size_t data_sz) {
const uint8_t *data_read = data;
ObuHeader obu_header;
memset(&obu_header, 0, sizeof(obu_header));
while (data_read < data + data_sz) {
size_t payload_size = 0;
size_t bytes_read = 0;
avm_read_obu_header_and_size(data_read, data_sz, &obu_header, &payload_size,
&bytes_read);
if (obu_header.type == OBU_CLK || obu_header.type == OBU_OLK) {
return 1;
}
data_read += bytes_read + payload_size;
data_sz -= bytes_read + payload_size;
}
return 0;
}
static int is_leading_vcl_obu(OBU_TYPE obu_type) {
return (obu_type == OBU_LEADING_TILE_GROUP || obu_type == OBU_LEADING_SEF ||
obu_type == OBU_LEADING_TIP);
}
#endif // CONFIG_F024_KEYOBU
// On success, sets *p_data_end and returns a boolean that indicates whether
// the decoding of the current frame is finished. On failure, sets
// cm->error.error_code and returns -1.
int avm_decode_frame_from_obus(struct AV2Decoder *pbi, const uint8_t *data,
const uint8_t *data_end,
const uint8_t **p_data_end) {
#if CONFIG_COLLECT_COMPONENT_TIMING
start_timing(pbi, avm_decode_frame_from_obus_time);
#endif
AV2_COMMON *const cm = &pbi->common;
int frame_decoding_finished = 0;
ObuHeader obu_header;
memset(&obu_header, 0, sizeof(obu_header));
pbi->seen_frame_header = 0;
pbi->next_start_tile = 0;
pbi->num_tile_groups = 0;
if (data_end < data) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return -1;
}
#if OBU_ORDER_IN_TU
OBU_TYPE prev_obu_type = 0;
OBU_TYPE curr_obu_type = 0;
int prev_obu_type_initialized = 0;
#endif // OBU_ORDER_IN_TU
#if CONFIG_F255_QMOBU
uint32_t acc_qm_id_bitmap = 0;
#endif
#if CONFIG_F153_FGM_OBU
// acc_fgm_id_bitmap accumulates fgm_id_bitmap in FGM OBU to check if film
// grain models signalled before a coded frame have the same fgm_id
uint32_t acc_fgm_id_bitmap = 0;
#endif // CONFIG_F153_FGM_OBU
#if CONFIG_CWG_F270_CI_OBU
av2_ci_keyframe_in_temporal_unit(pbi, data, data_end - data);
#endif // CONFIG_CWG_F270_CI_OBU
int prev_obu_xlayer_id = -1;
// decode frame as a series of OBUs
while (!frame_decoding_finished && cm->error.error_code == AVM_CODEC_OK) {
struct avm_read_bit_buffer rb;
size_t payload_size = 0;
size_t decoded_payload_size = 0;
size_t obu_payload_offset = 0;
size_t bytes_read = 0;
const size_t bytes_available = data_end - data;
if (bytes_available == 0 && !pbi->seen_frame_header) {
cm->error.error_code = AVM_CODEC_OK;
break;
}
avm_codec_err_t status = avm_read_obu_header_and_size(
data, bytes_available, &obu_header, &payload_size, &bytes_read);
if (status != AVM_CODEC_OK) {
cm->error.error_code = status;
return -1;
}
#if CONFIG_F024_KEYOBU
// Skip all obus till the random_accessed-th random access point
// Remove all leading_vcl obus
if (obu_header.type == OBU_LEADING_SEF ||
obu_header.type == OBU_LEADING_TIP ||
obu_header.type == OBU_LEADING_TILE_GROUP)
cm->is_leading_picture = 1;
else if (obu_header.type == OBU_REGULAR_SEF ||
obu_header.type == OBU_REGULAR_TIP ||
obu_header.type == OBU_REGULAR_TILE_GROUP ||
obu_header.type == OBU_BRIDGE_FRAME ||
obu_header.type == OBU_SWITCH || obu_header.type == OBU_RAS_FRAME)
cm->is_leading_picture = 0;
else
cm->is_leading_picture = -1;
if (obu_header.type == OBU_CLK || obu_header.type == OBU_OLK)
pbi->random_access_point_count++;
if (pbi->random_access_point_count < pbi->random_access_point_index) {
pbi->random_accessed = 0;
data += (bytes_read + payload_size);
continue;
} else {
if (obu_header.type == OBU_OLK || obu_header.type == OBU_CLK)
pbi->random_accessed = 1;
if ((obu_header.type == OBU_OLK || obu_header.type == OBU_CLK) &&
pbi->random_access_point_count != pbi->random_access_point_index)
pbi->random_accessed = 0;
if (pbi->random_accessed) {
// drop all leading vcl obus
if (is_leading_vcl_obu(obu_header.type)) {
data += (bytes_read + payload_size);
continue;
}
}
}
#endif
#if OBU_ORDER_IN_TU
curr_obu_type = obu_header.type;
if (prev_obu_type_initialized &&
check_obu_order(prev_obu_type, curr_obu_type)) {
avm_internal_error(&cm->error, AVM_CODEC_UNSUP_BITSTREAM,
"OBU order is incorrect in TU previous %s current %s",
avm_obu_type_to_string(prev_obu_type),
avm_obu_type_to_string(curr_obu_type));
}
prev_obu_type = curr_obu_type;
prev_obu_type_initialized = 1;
#endif // OBU_ORDER_IN_TU
if (obu_header.type == OBU_MSDO) {
if (obu_header.obu_tlayer_id != 0)
avm_internal_error(&cm->error, AVM_CODEC_UNSUP_BITSTREAM,
"Incorrect tlayer_id for MSDO: %d",
obu_header.obu_tlayer_id);
if (obu_header.obu_mlayer_id != 0)
avm_internal_error(&cm->error, AVM_CODEC_UNSUP_BITSTREAM,
"Incorrect obu_mlayer_id for MSDO: %d",
obu_header.obu_mlayer_id);
if (obu_header.obu_xlayer_id != GLOBAL_XLAYER_ID)
avm_internal_error(&cm->error, AVM_CODEC_UNSUP_BITSTREAM,
"Incorrect obu_xlayer_id for MSDO: %d",
obu_header.obu_xlayer_id);
}
// Record obu size header information.
pbi->obu_size_hdr.data = data + obu_header.size;
pbi->obu_size_hdr.size = bytes_read - obu_header.size;
pbi->obu_type = obu_header.type;
// Note: avm_read_obu_header_and_size() takes care of checking that this
// doesn't cause 'data' to advance past 'data_end'.
data += bytes_read;
if ((size_t)(data_end - data) < payload_size) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return -1;
}
cm->tlayer_id = obu_header.obu_tlayer_id;
cm->mlayer_id = obu_header.obu_mlayer_id;
if (obu_header.type == OBU_MSDO) {
cm->xlayer_id = obu_header.obu_xlayer_id;
} else {
if (cm->xlayer_id != obu_header.obu_xlayer_id) {
for (int i = 0; i < REF_FRAMES; i++) {
pbi->ref_frame_map_buf[cm->xlayer_id][i] = cm->ref_frame_map[i];
}
for (int i = 0; i < INTER_REFS_PER_FRAME; i++) {
pbi->remapped_ref_idx_buf[cm->xlayer_id][i] = cm->remapped_ref_idx[i];
}
pbi->seq_params_buf[cm->xlayer_id] = cm->seq_params;
for (int i = 0; i < MAX_MFH_NUM; i++) {
pbi->mfh_params_buf[cm->xlayer_id][i] = cm->mfh_params[i];
}
cm->xlayer_id = obu_header.obu_xlayer_id;
for (int i = 0; i < REF_FRAMES; i++) {
cm->ref_frame_map[i] = pbi->ref_frame_map_buf[cm->xlayer_id][i];
}
for (int i = 0; i < INTER_REFS_PER_FRAME; i++) {
cm->remapped_ref_idx[i] = pbi->remapped_ref_idx_buf[cm->xlayer_id][i];
}
cm->seq_params = pbi->seq_params_buf[cm->xlayer_id];
pbi->seq_params_buf[cm->xlayer_id] = cm->seq_params;
for (int i = 0; i < MAX_MFH_NUM; i++) {
cm->mfh_params[i] = pbi->mfh_params_buf[cm->xlayer_id][i];
}
pbi->stream_switched = 1;
}
if (obu_header.type == OBU_LEADING_TILE_GROUP ||
obu_header.type == OBU_REGULAR_TILE_GROUP) {
if (prev_obu_xlayer_id == -1) {
prev_obu_xlayer_id = obu_header.obu_xlayer_id;
} else {
if (prev_obu_xlayer_id >= 0 &&
obu_header.obu_xlayer_id != prev_obu_xlayer_id) {
avm_internal_error(&cm->error, AVM_CODEC_UNSUP_BITSTREAM,
"tile group OBUs with the same stream_id shall "
"be contiguous within a temporal unit");
}
}
}
}
// check bitstream conformance if sequence header is parsed
if (pbi->sequence_header_ready) {
// bitstream constraint for tlayer_id
if (cm->tlayer_id > cm->seq_params.max_tlayer_id) {
avm_internal_error(
&cm->error, AVM_CODEC_UNSUP_BITSTREAM,
"Inconsistent tlayer_id information: OBU header indicates "
"tlayer_id is "
"%d, yet max_tlayer_id in the sequence header is %d.",
cm->tlayer_id, cm->seq_params.max_tlayer_id);
}
// bitstream constraint for mlayer_id
if (cm->mlayer_id > cm->seq_params.max_mlayer_id) {
avm_internal_error(
&cm->error, AVM_CODEC_UNSUP_BITSTREAM,
"Inconsistent mlayer_id information: OBU header indicates "
"mlayer_id is "
"%d, yet max_mlayer_id in the sequence header is %d.",
cm->mlayer_id, cm->seq_params.max_mlayer_id);
}
}
// Set is_bridge_frame flag based on OBU type
if (obu_header.type == OBU_BRIDGE_FRAME) {
cm->bridge_frame_info.is_bridge_frame = 1;
} else {
cm->bridge_frame_info.is_bridge_frame = 0;
}
#if !CONFIG_CWG_F270_OPS
if (obu_header.type != OBU_TEMPORAL_DELIMITER &&
obu_header.type != OBU_SEQUENCE_HEADER) {
// don't decode obu if it's not in current operating mode
if (!is_obu_in_current_operating_point(pbi, obu_header)) {
data += payload_size;
continue;
}
}
#endif // !CONFIG_CWG_F270_OPS
av2_init_read_bit_buffer(pbi, &rb, data, data + payload_size);
switch (obu_header.type) {
case OBU_TEMPORAL_DELIMITER:
decoded_payload_size = read_temporal_delimiter_obu();
pbi->seen_frame_header = 0;
pbi->next_start_tile = 0;
break;
case OBU_MSDO:
decoded_payload_size =
read_multi_stream_decoder_operation_obu(pbi, &rb);
if (cm->error.error_code != AVM_CODEC_OK) return -1;
break;
case OBU_SEQUENCE_HEADER:
cm->xlayer_id = obu_header.obu_xlayer_id;
cm->seq_params = pbi->seq_params_buf[cm->xlayer_id];
pbi->stream_switched = 0;
decoded_payload_size = read_sequence_header_obu(pbi, &rb);
if (cm->error.error_code != AVM_CODEC_OK) return -1;
// The sequence header should not change in the middle of a frame.
if (pbi->sequence_header_changed && pbi->seen_frame_header) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return -1;
}
break;
case OBU_BUFFER_REMOVAL_TIMING:
decoded_payload_size =
av2_read_buffer_removal_timing_obu(pbi, &rb, cm->xlayer_id);
if (cm->error.error_code != AVM_CODEC_OK) return -1;
break;
case OBU_LAYER_CONFIGURATION_RECORD:
decoded_payload_size =
av2_read_layer_configuration_record_obu(pbi, cm->xlayer_id, &rb);
if (cm->error.error_code != AVM_CODEC_OK) return -1;
break;
case OBU_ATLAS_SEGMENT:
decoded_payload_size =
av2_read_atlas_segment_info_obu(pbi, cm->xlayer_id, &rb);
if (cm->error.error_code != AVM_CODEC_OK) return -1;
break;
case OBU_OPERATING_POINT_SET:
decoded_payload_size =
av2_read_operating_point_set_obu(pbi, cm->xlayer_id, &rb);
if (cm->error.error_code != AVM_CODEC_OK) return -1;
break;
#if CONFIG_CWG_F270_CI_OBU
case OBU_CONTENT_INTERPRETATION:
if (!pbi->sequence_header_ready) {
cm->error.error_code = AVM_CODEC_UNSUP_BITSTREAM;
return -1;
}
decoded_payload_size = av2_read_content_interpretation_obu(pbi, &rb);
if (cm->error.error_code != AVM_CODEC_OK) return -1;
break;
#endif // CONFIG_CWG_F270_CI_OBU
case OBU_MULTI_FRAME_HEADER:
decoded_payload_size = read_multi_frame_header_obu(pbi, &rb);
if (cm->error.error_code != AVM_CODEC_OK) return -1;
break;
#if CONFIG_F024_KEYOBU
case OBU_CLK:
case OBU_OLK:
case OBU_LEADING_TILE_GROUP:
case OBU_REGULAR_TILE_GROUP:
#else
case OBU_TILE_GROUP:
#endif // CONFIG_F024_KEYOBU
case OBU_SWITCH:
#if CONFIG_F024_KEYOBU
case OBU_LEADING_SEF:
case OBU_REGULAR_SEF:
#else
case OBU_SEF:
#endif // CONFIG_F024_KEYOBU
#if CONFIG_F024_KEYOBU
case OBU_LEADING_TIP:
case OBU_REGULAR_TIP:
#else
case OBU_TIP:
#endif // CONFIG_F024_KEYOBU
case OBU_RAS_FRAME:
case OBU_BRIDGE_FRAME:
#if CONFIG_F255_QMOBU
for (int i = 0; i < NUM_CUSTOM_QMS; i++) {
if (acc_qm_id_bitmap & (1 << i)) {
pbi->qm_protected[i] &=
(obu_header.type == OBU_CLK || obu_header.type == OBU_OLK);
}
}
// It is a requirement that if multiple QM OBUs are present
// consecutively prior to a coded frame, other than a QM OBU with
// qm_bit_map equal to 0, such QM OBUs will not set the same QM ID more
// than once.
acc_qm_id_bitmap = 0;
#endif
#if CONFIG_F153_FGM_OBU
// It is a requirement that if multiple FGM OBUs are present
// consecutively prior to a coded frame, such FGM OBUs will not set
// the same FGM ID more than once.
acc_fgm_id_bitmap = 0;
#endif // CONFIG_F153_FGM_OBU
decoded_payload_size =
read_tilegroup_obu(pbi, &rb, data, data + payload_size, p_data_end,
obu_header.type, &frame_decoding_finished);
if (cm->error.error_code != AVM_CODEC_OK) return -1;
if (cm->bru.frame_inactive_flag ||
cm->bridge_frame_info.is_bridge_frame) {
pbi->seen_frame_header = 0;
frame_decoding_finished = 1;
CommonTileParams *const tiles = &cm->tiles;
av2_get_tile_limits(&cm->tiles, cm->mi_params.mi_rows,
cm->mi_params.mi_cols, cm->mib_size_log2,
cm->seq_params.mib_size_log2);
tiles->uniform_spacing = 1;
tiles->log2_cols = 0;
av2_calculate_tile_cols(tiles);
tiles->log2_rows = 0;
av2_calculate_tile_rows(tiles);
const int num_tiles = cm->tiles.cols * cm->tiles.rows;
const int end_tile = num_tiles - 1;
// skip parsing and go directly to decode
av2_decode_tg_tiles_and_wrapup(pbi, data, data_end, p_data_end, 0,
end_tile, 0);
if (cm->bridge_frame_info.is_bridge_frame) {
*p_data_end = data + payload_size;
}
break;
}
if (obu_payload_offset > payload_size) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return -1;
}
if (cm->error.error_code != AVM_CODEC_OK) return -1;
if (frame_decoding_finished) pbi->seen_frame_header = 0;
pbi->num_tile_groups++;
break;
#if CONFIG_F255_QMOBU
case OBU_QM:
decoded_payload_size =
read_qm_obu(pbi, obu_header.obu_tlayer_id, obu_header.obu_mlayer_id,
&acc_qm_id_bitmap, &rb);
if (cm->error.error_code != AVM_CODEC_OK) return -1;
break;
#endif // CONFIG_F255_QMOBU
#if !CONFIG_METADATA
case OBU_METADATA:
decoded_payload_size = read_metadata(pbi, data, payload_size);
if (cm->error.error_code != AVM_CODEC_OK) return -1;
break;
#else
case OBU_METADATA_SHORT:
decoded_payload_size = read_metadata_short(pbi, data, payload_size, 0);
if (cm->error.error_code != AVM_CODEC_OK) return -1;
break;
case OBU_METADATA_GROUP:
decoded_payload_size =
read_metadata_obu(pbi, data, payload_size, &obu_header, 0);
if (cm->error.error_code != AVM_CODEC_OK) return -1;
break;
#endif // CONFIG_METADATA
#if CONFIG_F153_FGM_OBU
case OBU_FGM:
decoded_payload_size =
read_fgm_obu(pbi, obu_header.obu_tlayer_id,
obu_header.obu_mlayer_id, &acc_fgm_id_bitmap, &rb);
if (cm->error.error_code != AVM_CODEC_OK) return -1;
break;
#endif // CONFIG_F153_FGM_OBU
case OBU_PADDING:
decoded_payload_size = read_padding(cm, data, payload_size);
if (cm->error.error_code != AVM_CODEC_OK) return -1;
break;
default:
// Skip unrecognized OBUs
if (payload_size > 0 &&
get_last_nonzero_byte(data, payload_size) == 0) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return -1;
}
decoded_payload_size = payload_size;
break;
}
// Check that the signalled OBU size matches the actual amount of data read
if (decoded_payload_size > payload_size) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return -1;
}
// If there are extra padding bytes, they should all be zero
while (decoded_payload_size < payload_size) {
uint8_t padding_byte = data[decoded_payload_size++];
if (padding_byte != 0) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return -1;
}
}
data += payload_size;
}
#if CONFIG_METADATA
// check whether suffix metadata OBUs are present
while (cm->error.error_code == AVM_CODEC_OK && data < data_end) {
size_t payload_size = 0;
size_t decoded_payload_size = 0;
size_t bytes_read = 0;
const size_t bytes_available = data_end - data;
avm_codec_err_t status = avm_read_obu_header_and_size(
data, bytes_available, &obu_header, &payload_size, &bytes_read);
if (status != AVM_CODEC_OK) {
cm->error.error_code = status;
return -1;
}
// Accept both OBU_METADATA_SHORT and OBU_METADATA_GROUP for suffix metadata
if (!IS_METADATA_OBU(obu_header.type) || data + bytes_read >= data_end)
break;
// check whether it is a suffix metadata OBU
if (!(data[bytes_read] & 0x80)) break;
data += bytes_read;
// Call the appropriate read function based on OBU type
if (obu_header.type == OBU_METADATA_GROUP) {
decoded_payload_size =
read_metadata_obu(pbi, data, payload_size, &obu_header, 1);
} else {
decoded_payload_size = read_metadata_short(pbi, data, payload_size, 1);
}
if (cm->error.error_code != AVM_CODEC_OK) return -1;
// Check that the signalled OBU size matches the actual amount of data read
if (decoded_payload_size > payload_size) {
cm->error.error_code = AVM_CODEC_CORRUPT_FRAME;
return -1;
}
data += payload_size;
}
#endif // CONFIG_METADATA
if (cm->error.error_code != AVM_CODEC_OK) return -1;
*p_data_end = data;
#if CONFIG_COLLECT_COMPONENT_TIMING
end_timing(pbi, avm_decode_frame_from_obus_time);
// Print out timing information.
int i;
fprintf(stderr, "\n Frame number: %d, Frame type: %s, Show Frame: %d\n",
cm->current_frame.frame_number,
get_frame_type_enum(cm->current_frame.frame_type), cm->show_frame);
for (i = 0; i < kTimingComponents; i++) {
pbi->component_time[i] += pbi->frame_component_time[i];
fprintf(stderr, " %s: %" PRId64 " us (total: %" PRId64 " us)\n",
get_component_name(i), pbi->frame_component_time[i],
pbi->component_time[i]);
pbi->frame_component_time[i] = 0;
}
#endif
return frame_decoding_finished;
}