blob: 4affb29f0f8ea8469386a7d51487801accfba501 [file] [log] [blame] [edit]
/*
* Copyright (c) 2025, 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/aom_config.h"
#include "config/aom_scale_rtcd.h"
#include "aom/aom_codec.h"
#include "aom_dsp/bitreader_buffer.h"
#include "aom_ports/mem_ops.h"
#include "av1/common/common.h"
#include "av1/common/obu_util.h"
#include "av1/common/timing.h"
#include "av1/decoder/decoder.h"
#include "av1/decoder/decodeframe.h"
#include "av1/decoder/obu.h"
#if CONFIG_CWG_F293_BUFFER_REMOVAL_TIMING
uint32_t av1_read_buffer_removal_timing_obu(struct AV1Decoder *pbi,
struct aom_read_bit_buffer *rb,
int xlayer_id) {
AV1_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);
BufferRemovalTimingInfo btr = cm->brt_info;
BufferRemovalTimingInfo *const brt_info = &btr;
brt_info->obu_xlayer_id = xlayer_id;
// br_ops_id
brt_info->br_ops_id[xlayer_id] = aom_rb_read_literal(rb, 4);
int ops_id = brt_info->br_ops_id[xlayer_id];
// Find the corresponding OPS in pbi->ops_list where
// ops_id[xlayer_id] == br_ops_id[xlayer_id].
// It is a requirement of bitstream conformance that if a buffer removal time
// OBU with a buffer br_ops_id[obu_xlayer_id] is present in the bitstream, an
// operating point set OBU shall also be present in the bitstream with a value
// of ops_id[obu_xlayer_id] equal to br_ops_id[obu_xlayer_id]."
struct OperatingPointSet *matched_ops = NULL;
for (int i = 0; i < pbi->ops_counter; i++) {
if (pbi->ops_list[i].ops_id[xlayer_id] == ops_id) {
matched_ops = &pbi->ops_list[i];
break;
}
}
if (matched_ops == NULL) {
aom_internal_error(
&cm->error, AOM_CODEC_UNSUP_BITSTREAM,
"No matching operating point set OBU found for br_ops_id[%d] = %d. "
"Bitstream conformance requires an OPS OBU with ops_id[%d] = %d.",
xlayer_id, ops_id, xlayer_id, ops_id);
}
// br_ops_cnt
brt_info->br_ops_cnt[xlayer_id][ops_id] = aom_rb_read_literal(rb, 3);
int ops_cnt = brt_info->br_ops_cnt[xlayer_id][ops_id];
// It is a requirement of bitstream conformance that br_ops_cnt[xlayer_id]
// [opsId], when present shall be equal to the value of
// ops_cnt[xlayerId][ops_id] of the corresponding operating point set OBU.
if (brt_info->br_ops_cnt[xlayer_id][ops_id] !=
matched_ops->ops_cnt[xlayer_id][ops_id]) {
aom_internal_error(&cm->error, AOM_CODEC_UNSUP_BITSTREAM,
"Inconsistent values for the operating point count"
"Buffer timing and OPS counts. The bitstream constraint "
"does not allow different values.");
}
// decoder model
int br_decoder_model_present_op_present_flag = 0;
for (int i = 0; i < ops_cnt; i++) {
brt_info->br_decoder_model_present_op_flag[xlayer_id][ops_id][i] =
aom_rb_read_bit(rb);
br_decoder_model_present_op_present_flag =
brt_info->br_decoder_model_present_op_flag[xlayer_id][ops_id][i];
if (br_decoder_model_present_op_present_flag)
brt_info->br_buffer_removal_time[xlayer_id][ops_id][i] =
aom_rb_read_uvlc(rb);
}
if (av1_check_trailing_bits(pbi, rb) != 0) {
// cm->error.error_code is already set.
return 0;
}
return ((rb->bit_offset - saved_bit_offset + 7) >> 3);
}
#endif // CONFIG_CWG_F293_BUFFER_REMOVAL_TIMING