blob: 975fe307cd8fdbd1da4daddc8a6cab27da33589d [file] [edit]
/*
* Copyright (c) 2026, 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 <cstring>
#include "third_party/googletest/src/googletest/include/gtest/gtest.h"
#include "av2/encoder/ops_syntax.h"
#include "av2/decoder/decoder.h"
#include "av2/decoder/decodeframe.h"
#include "avm_dsp/bitwriter_buffer.h"
#include "avm_dsp/bitreader_buffer.h"
#include "avm_mem/avm_mem.h"
// av2_set_ops_params is declared in bitstream.h which pulls in encoder.h.
// Forward-declare it here to avoid the ThreadData conflict.
extern "C" void av2_set_ops_params(struct OperatingPointSet *ops, int xlayer_id,
int ops_id, int ops_cnt);
namespace {
static void rb_error_handler(void *data, avm_codec_err_t error,
const char *detail) {
(void)data;
(void)error;
(void)detail;
}
// Write an OPS OBU: body (via av2_write_operating_point_set which includes
// extension flag) + trailing bits.
static uint32_t write_ops_obu(struct OperatingPointSet *ops, int xlayer_id,
uint8_t *dst) {
struct avm_write_bit_buffer wb = { dst, 0 };
av2_write_operating_point_set(ops, xlayer_id, &wb);
// trailing bits: stop bit + zero-padding to byte boundary
avm_wb_write_bit(&wb, 1);
int pad = (8 - wb.bit_offset % 8) % 8;
if (pad > 0) avm_wb_write_literal(&wb, 0, pad);
return avm_wb_bytes_written(&wb);
}
class OpsTest : public ::testing::Test {
protected:
void SetUp() override {
pbi_ = static_cast<AV2Decoder *>(avm_memalign(32, sizeof(AV2Decoder)));
ASSERT_NE(pbi_, nullptr);
memset(pbi_, 0, sizeof(*pbi_));
memset(buf_, 0, sizeof(buf_));
}
void TearDown() override { avm_free(pbi_); }
AV2Decoder *pbi_;
uint8_t buf_[8192];
};
TEST_F(OpsTest, LocalOpsRoundtrip) {
const int xlayer_id = 0;
OperatingPointSet src;
av2_set_ops_params(&src, xlayer_id, 0, 1);
src.ops_ptl_present_flag = 1;
OperatingPoint *op = &src.op[0];
op->ops_seq_profile_idc[xlayer_id] = 4;
op->ops_level_idx[xlayer_id] = 8;
op->ops_tier_flag[xlayer_id] = 1;
op->ops_mlayer_count[xlayer_id] = 2;
op->mlayer_info.ops_mlayer_map[xlayer_id] = 0x3; // mlayers 0,1
op->mlayer_info.ops_tlayer_map[xlayer_id][0] = 0x1;
op->mlayer_info.ops_tlayer_map[xlayer_id][1] = 0x1;
uint32_t written = write_ops_obu(&src, xlayer_id, buf_);
ASSERT_GT(written, 0u);
struct avm_read_bit_buffer rb = { buf_, buf_ + written, 0, nullptr,
rb_error_handler };
uint32_t read = av2_read_operating_point_set_obu(pbi_, xlayer_id, &rb);
ASSERT_EQ(read, written);
const OperatingPointSet *dst = &pbi_->ops_list[xlayer_id][0];
ASSERT_TRUE(dst->valid);
EXPECT_EQ(dst->ops_id, 0);
EXPECT_EQ(dst->ops_cnt, 1);
EXPECT_EQ(dst->ops_ptl_present_flag, 1);
const OperatingPoint *dop = &dst->op[0];
EXPECT_EQ(dop->ops_seq_profile_idc[xlayer_id], 4);
EXPECT_EQ(dop->ops_level_idx[xlayer_id], 8);
EXPECT_EQ(dop->ops_tier_flag[xlayer_id], 1);
EXPECT_EQ(dop->ops_mlayer_count[xlayer_id], 2);
EXPECT_EQ(dop->mlayer_info.ops_mlayer_map[xlayer_id], 0x3);
EXPECT_EQ(dop->mlayer_info.OPMLayerCount[xlayer_id], 2);
}
TEST_F(OpsTest, LocalOpsDefaultParams) {
const int xlayer_id = 0;
OperatingPointSet src;
av2_set_ops_params(&src, xlayer_id, 1, 1);
uint32_t written = write_ops_obu(&src, xlayer_id, buf_);
ASSERT_GT(written, 0u);
struct avm_read_bit_buffer rb = { buf_, buf_ + written, 0, nullptr,
rb_error_handler };
uint32_t read = av2_read_operating_point_set_obu(pbi_, xlayer_id, &rb);
ASSERT_EQ(read, written);
const OperatingPointSet *dst = &pbi_->ops_list[xlayer_id][1];
ASSERT_TRUE(dst->valid);
EXPECT_EQ(dst->ops_id, 1);
EXPECT_EQ(dst->ops_cnt, 1);
EXPECT_EQ(dst->ops_ptl_present_flag, 0);
EXPECT_EQ(dst->ops_color_info_present_flag, 0);
EXPECT_EQ(dst->op[0].ops_initial_display_delay, BUFFER_POOL_MAX_SIZE);
}
TEST_F(OpsTest, LocalOpsMultipleOperatingPoints) {
const int xlayer_id = 0;
OperatingPointSet src;
av2_set_ops_params(&src, xlayer_id, 0, 3);
for (int i = 0; i < 3; i++) {
src.op[i].mlayer_info.ops_mlayer_map[xlayer_id] = 1 << i;
src.op[i].mlayer_info.ops_tlayer_map[xlayer_id][i] = 0x1;
}
uint32_t written = write_ops_obu(&src, xlayer_id, buf_);
ASSERT_GT(written, 0u);
struct avm_read_bit_buffer rb = { buf_, buf_ + written, 0, nullptr,
rb_error_handler };
uint32_t read = av2_read_operating_point_set_obu(pbi_, xlayer_id, &rb);
ASSERT_EQ(read, written);
const OperatingPointSet *dst = &pbi_->ops_list[xlayer_id][0];
ASSERT_TRUE(dst->valid);
EXPECT_EQ(dst->ops_cnt, 3);
for (int i = 0; i < 3; i++) {
EXPECT_EQ(dst->op[i].mlayer_info.ops_mlayer_map[xlayer_id], 1 << i);
EXPECT_EQ(dst->op[i].mlayer_info.OPMLayerCount[xlayer_id], 1);
}
}
TEST_F(OpsTest, LocalOpsDisplayDelay) {
const int xlayer_id = 0;
OperatingPointSet src;
av2_set_ops_params(&src, xlayer_id, 0, 1);
src.op[0].ops_initial_display_delay = 4;
uint32_t written = write_ops_obu(&src, xlayer_id, buf_);
ASSERT_GT(written, 0u);
struct avm_read_bit_buffer rb = { buf_, buf_ + written, 0, nullptr,
rb_error_handler };
uint32_t read = av2_read_operating_point_set_obu(pbi_, xlayer_id, &rb);
ASSERT_EQ(read, written);
const OperatingPointSet *dst = &pbi_->ops_list[xlayer_id][0];
EXPECT_EQ(dst->op[0].ops_initial_display_delay, 4);
}
// reset_flag=0, cnt=0: clears targeted slot only.
TEST_F(OpsTest, OpsResetSlot) {
const int xlayer_id = 0;
OperatingPointSet src;
memset(&src, 0, sizeof(src));
src.valid = 1;
src.obu_xlayer_id = xlayer_id;
src.ops_id = 2;
src.ops_cnt = 0;
src.ops_reset_flag = 0;
uint32_t written = write_ops_obu(&src, xlayer_id, buf_);
ASSERT_GT(written, 0u);
// Pre-populate slot 2 to verify it gets cleared.
pbi_->ops_list[xlayer_id][2].valid = 1;
pbi_->ops_list[xlayer_id][2].ops_cnt = 5;
struct avm_read_bit_buffer rb = { buf_, buf_ + written, 0, nullptr,
rb_error_handler };
uint32_t read = av2_read_operating_point_set_obu(pbi_, xlayer_id, &rb);
ASSERT_EQ(read, written);
// Slot 2 should have been cleared.
EXPECT_EQ(pbi_->ops_list[xlayer_id][2].ops_cnt, 0);
}
TEST_F(OpsTest, GlobalOpsRoundtrip) {
const int xlayer_id = GLOBAL_XLAYER_ID;
OperatingPointSet src;
memset(&src, 0, sizeof(src));
src.valid = 1;
src.obu_xlayer_id = xlayer_id;
src.ops_id = 0;
src.ops_cnt = 1;
src.ops_ptl_present_flag = 1;
src.ops_mlayer_info_idc = 1;
OperatingPoint *op = &src.op[0];
op->ops_initial_display_delay = BUFFER_POOL_MAX_SIZE;
op->ops_config_idc = 3;
op->ops_aggregate_level_idx = 5;
op->ops_max_tier_flag = 1;
op->ops_max_interop = 2;
op->ops_xlayer_map = 0x3; // xlayers 0 and 1
op->ops_seq_profile_idc[0] = 4;
op->ops_level_idx[0] = 8;
op->ops_tier_flag[0] = 1;
op->ops_mlayer_count[0] = 2;
op->ops_seq_profile_idc[1] = 5;
op->ops_level_idx[1] = 10;
op->ops_tier_flag[1] = 0;
op->ops_mlayer_count[1] = 1;
op->mlayer_info.ops_mlayer_map[0] = 0x3;
op->mlayer_info.ops_tlayer_map[0][0] = 0x1;
op->mlayer_info.ops_tlayer_map[0][1] = 0x1;
op->mlayer_info.ops_mlayer_map[1] = 0x1;
op->mlayer_info.ops_tlayer_map[1][0] = 0x1;
uint32_t written = write_ops_obu(&src, xlayer_id, buf_);
ASSERT_GT(written, 0u);
struct avm_read_bit_buffer rb = { buf_, buf_ + written, 0, nullptr,
rb_error_handler };
uint32_t read = av2_read_operating_point_set_obu(pbi_, xlayer_id, &rb);
ASSERT_EQ(read, written);
const OperatingPointSet *dst = &pbi_->ops_list[xlayer_id][0];
ASSERT_TRUE(dst->valid);
EXPECT_EQ(dst->ops_cnt, 1);
EXPECT_EQ(dst->ops_mlayer_info_idc, 1);
const OperatingPoint *dop = &dst->op[0];
EXPECT_EQ(dop->ops_config_idc, 3);
EXPECT_EQ(dop->ops_aggregate_level_idx, 5);
EXPECT_EQ(dop->ops_max_tier_flag, 1);
EXPECT_EQ(dop->ops_max_interop, 2);
EXPECT_EQ(dop->ops_xlayer_map, 0x3);
EXPECT_EQ(dop->ops_seq_profile_idc[0], 4);
EXPECT_EQ(dop->ops_level_idx[0], 8);
EXPECT_EQ(dop->ops_seq_profile_idc[1], 5);
EXPECT_EQ(dop->ops_level_idx[1], 10);
EXPECT_EQ(dop->mlayer_info.ops_mlayer_map[0], 0x3);
EXPECT_EQ(dop->mlayer_info.OPMLayerCount[0], 2);
EXPECT_EQ(dop->mlayer_info.ops_mlayer_map[1], 0x1);
EXPECT_EQ(dop->mlayer_info.OPMLayerCount[1], 1);
}
TEST_F(OpsTest, OpsColorInfoRoundtrip) {
const int xlayer_id = 0;
OperatingPointSet src;
av2_set_ops_params(&src, xlayer_id, 0, 1);
src.ops_color_info_present_flag = 1;
OperatingPoint *op = &src.op[0];
op->color_info.ops_color_description_idc = 0; // explicit
op->color_info.ops_color_primaries = 1;
op->color_info.ops_transfer_characteristics = 13;
op->color_info.ops_matrix_coefficients = 6;
op->color_info.ops_full_range_flag = 1;
uint32_t written = write_ops_obu(&src, xlayer_id, buf_);
ASSERT_GT(written, 0u);
struct avm_read_bit_buffer rb = { buf_, buf_ + written, 0, nullptr,
rb_error_handler };
uint32_t read = av2_read_operating_point_set_obu(pbi_, xlayer_id, &rb);
ASSERT_EQ(read, written);
const OperatingPoint *dop = &pbi_->ops_list[xlayer_id][0].op[0];
EXPECT_EQ(dop->color_info.ops_color_description_idc, 0);
EXPECT_EQ(dop->color_info.ops_color_primaries, 1);
EXPECT_EQ(dop->color_info.ops_transfer_characteristics, 13);
EXPECT_EQ(dop->color_info.ops_matrix_coefficients, 6);
EXPECT_EQ(dop->color_info.ops_full_range_flag, 1);
}
TEST_F(OpsTest, OpsDecoderModelInfoRoundtrip) {
const int xlayer_id = 0;
OperatingPointSet src;
av2_set_ops_params(&src, xlayer_id, 0, 1);
OperatingPoint *op = &src.op[0];
op->ops_decoder_model_info_for_this_op_present_flag = 1;
op->decoder_model_info.ops_decoder_buffer_delay = 1000;
op->decoder_model_info.ops_encoder_buffer_delay = 2000;
op->decoder_model_info.ops_low_delay_mode_flag = 1;
uint32_t written = write_ops_obu(&src, xlayer_id, buf_);
ASSERT_GT(written, 0u);
struct avm_read_bit_buffer rb = { buf_, buf_ + written, 0, nullptr,
rb_error_handler };
uint32_t read = av2_read_operating_point_set_obu(pbi_, xlayer_id, &rb);
ASSERT_EQ(read, written);
const OperatingPoint *dop = &pbi_->ops_list[xlayer_id][0].op[0];
EXPECT_EQ(dop->ops_decoder_model_info_for_this_op_present_flag, 1);
EXPECT_EQ(dop->decoder_model_info.ops_decoder_buffer_delay, 1000u);
EXPECT_EQ(dop->decoder_model_info.ops_encoder_buffer_delay, 2000u);
EXPECT_EQ(dop->decoder_model_info.ops_low_delay_mode_flag, 1);
}
TEST_F(OpsTest, OpsResetAll) {
const int xlayer_id = 0;
// Pre-populate multiple slots.
pbi_->ops_list[xlayer_id][0].valid = 1;
pbi_->ops_list[xlayer_id][0].ops_cnt = 2;
pbi_->ops_list[xlayer_id][3].valid = 1;
pbi_->ops_list[xlayer_id][3].ops_cnt = 1;
// reset_flag=1, cnt=0: clears all slots for this xlayer.
OperatingPointSet src;
memset(&src, 0, sizeof(src));
src.valid = 1;
src.ops_id = 0;
src.ops_cnt = 0;
src.ops_reset_flag = 1;
uint32_t written = write_ops_obu(&src, xlayer_id, buf_);
ASSERT_GT(written, 0u);
struct avm_read_bit_buffer rb = { buf_, buf_ + written, 0, nullptr,
rb_error_handler };
uint32_t read = av2_read_operating_point_set_obu(pbi_, xlayer_id, &rb);
ASSERT_EQ(read, written);
// All slots for this xlayer should be cleared.
EXPECT_EQ(pbi_->ops_list[xlayer_id][0].ops_cnt, 0);
EXPECT_EQ(pbi_->ops_list[xlayer_id][3].ops_cnt, 0);
}
TEST_F(OpsTest, OpsResetAndDefine) {
const int xlayer_id = 0;
// Pre-populate slot 3.
pbi_->ops_list[xlayer_id][3].valid = 1;
pbi_->ops_list[xlayer_id][3].ops_cnt = 5;
// Write reset+define OBU: reset_flag=1, cnt=1 (Case 2).
OperatingPointSet src;
av2_set_ops_params(&src, xlayer_id, 0, 1);
src.ops_reset_flag = 1;
uint32_t written = write_ops_obu(&src, xlayer_id, buf_);
ASSERT_GT(written, 0u);
struct avm_read_bit_buffer rb = { buf_, buf_ + written, 0, nullptr,
rb_error_handler };
uint32_t read = av2_read_operating_point_set_obu(pbi_, xlayer_id, &rb);
ASSERT_EQ(read, written);
// Slot 3 should be cleared (reset all first).
EXPECT_EQ(pbi_->ops_list[xlayer_id][3].ops_cnt, 0);
// Slot 0 should have the new OPS.
EXPECT_TRUE(pbi_->ops_list[xlayer_id][0].valid);
EXPECT_EQ(pbi_->ops_list[xlayer_id][0].ops_cnt, 1);
}
TEST_F(OpsTest, OpsIntentPresent) {
const int xlayer_id = 0;
OperatingPointSet src;
av2_set_ops_params(&src, xlayer_id, 0, 1);
src.ops_intent_present_flag = 1;
src.op[0].ops_intent_op = 42;
uint32_t written = write_ops_obu(&src, xlayer_id, buf_);
ASSERT_GT(written, 0u);
struct avm_read_bit_buffer rb = { buf_, buf_ + written, 0, nullptr,
rb_error_handler };
uint32_t read = av2_read_operating_point_set_obu(pbi_, xlayer_id, &rb);
ASSERT_EQ(read, written);
EXPECT_EQ(pbi_->ops_list[xlayer_id][0].ops_intent_present_flag, 1);
EXPECT_EQ(pbi_->ops_list[xlayer_id][0].op[0].ops_intent_op, 42);
}
// color_info_present with idc > 0: no primaries written.
TEST_F(OpsTest, OpsColorInfoImplicit) {
const int xlayer_id = 0;
OperatingPointSet src;
av2_set_ops_params(&src, xlayer_id, 0, 1);
src.ops_color_info_present_flag = 1;
src.op[0].color_info.ops_color_description_idc = 1; // implicit
src.op[0].color_info.ops_full_range_flag = 0;
uint32_t written = write_ops_obu(&src, xlayer_id, buf_);
ASSERT_GT(written, 0u);
struct avm_read_bit_buffer rb = { buf_, buf_ + written, 0, nullptr,
rb_error_handler };
uint32_t read = av2_read_operating_point_set_obu(pbi_, xlayer_id, &rb);
ASSERT_EQ(read, written);
EXPECT_EQ(
pbi_->ops_list[xlayer_id][0].op[0].color_info.ops_color_description_idc,
1);
EXPECT_EQ(pbi_->ops_list[xlayer_id][0].op[0].color_info.ops_full_range_flag,
0);
}
TEST_F(OpsTest, OpsCntSweep) {
const int cnt_values[] = { 2, 5, 7 };
for (int ci = 0; ci < 3; ci++) {
int cnt = cnt_values[ci];
const int xlayer_id = 0;
OperatingPointSet src;
av2_set_ops_params(&src, xlayer_id, 0, cnt);
for (int i = 0; i < cnt; i++) {
src.op[i].mlayer_info.ops_mlayer_map[xlayer_id] = 1 << (i % 8);
src.op[i].mlayer_info.ops_tlayer_map[xlayer_id][i % 8] = 0x1;
}
memset(buf_, 0, sizeof(buf_));
uint32_t written = write_ops_obu(&src, xlayer_id, buf_);
ASSERT_GT(written, 0u) << "cnt=" << cnt;
memset(pbi_, 0, sizeof(*pbi_));
struct avm_read_bit_buffer rb = { buf_, buf_ + written, 0, nullptr,
rb_error_handler };
uint32_t read = av2_read_operating_point_set_obu(pbi_, xlayer_id, &rb);
ASSERT_EQ(read, written) << "cnt=" << cnt;
EXPECT_EQ(pbi_->ops_list[xlayer_id][0].ops_cnt, cnt);
for (int i = 0; i < cnt; i++) {
EXPECT_EQ(pbi_->ops_list[xlayer_id][0]
.op[i]
.mlayer_info.ops_mlayer_map[xlayer_id],
1 << (i % 8))
<< "cnt=" << cnt << " op=" << i;
}
}
}
TEST_F(OpsTest, GlobalOpsNoMlayerInfo) {
const int xlayer_id = GLOBAL_XLAYER_ID;
OperatingPointSet src;
memset(&src, 0, sizeof(src));
src.valid = 1;
src.obu_xlayer_id = xlayer_id;
src.ops_id = 0;
src.ops_cnt = 1;
src.ops_mlayer_info_idc = 0;
src.op[0].ops_initial_display_delay = BUFFER_POOL_MAX_SIZE;
src.op[0].ops_xlayer_map = 0x1;
uint32_t written = write_ops_obu(&src, xlayer_id, buf_);
ASSERT_GT(written, 0u);
struct avm_read_bit_buffer rb = { buf_, buf_ + written, 0, nullptr,
rb_error_handler };
uint32_t read = av2_read_operating_point_set_obu(pbi_, xlayer_id, &rb);
ASSERT_EQ(read, written);
EXPECT_EQ(pbi_->ops_list[xlayer_id][0].ops_mlayer_info_idc, 0);
EXPECT_EQ(pbi_->ops_list[xlayer_id][0].op[0].ops_xlayer_map, 0x1);
}
TEST_F(OpsTest, GlobalOpsEmbeddedReference) {
const int xlayer_id = GLOBAL_XLAYER_ID;
// Pre-populate a referenced OPS (ops_id=1, op_index=0) in the decoder
// so the embedded reference can inherit mlayer_info from it.
OperatingPointSet *ref_ops = &pbi_->ops_list[xlayer_id][1];
ref_ops->valid = 1;
ref_ops->ops_cnt = 1;
ref_ops->op[0].mlayer_info.ops_mlayer_map[0] = 0x3;
ref_ops->op[0].mlayer_info.OPMLayerCount[0] = 2;
ref_ops->op[0].mlayer_info.ops_tlayer_map[0][0] = 0x1;
ref_ops->op[0].mlayer_info.ops_tlayer_map[0][1] = 0x1;
ref_ops->op[0].mlayer_info.OPTLayerCount[0][0] = 1;
ref_ops->op[0].mlayer_info.OPTLayerCount[0][1] = 1;
// Write an OPS with idc=2: xlayer 0 uses embedded reference to ops_id=1,
// op_index=0.
OperatingPointSet src;
memset(&src, 0, sizeof(src));
src.valid = 1;
src.obu_xlayer_id = xlayer_id;
src.ops_id = 0;
src.ops_cnt = 1;
src.ops_mlayer_info_idc = 2;
OperatingPoint *op = &src.op[0];
op->ops_initial_display_delay = BUFFER_POOL_MAX_SIZE;
op->ops_xlayer_map = 0x1; // xlayer 0
op->ops_mlayer_explicit_info_flag[0] = 0; // use reference
op->ops_embedded_ops_id[0] = 1;
op->ops_embedded_op_index[0] = 0;
uint32_t written = write_ops_obu(&src, xlayer_id, buf_);
ASSERT_GT(written, 0u);
struct avm_read_bit_buffer rb = { buf_, buf_ + written, 0, nullptr,
rb_error_handler };
uint32_t read = av2_read_operating_point_set_obu(pbi_, xlayer_id, &rb);
ASSERT_EQ(read, written);
const OperatingPointSet *dst = &pbi_->ops_list[xlayer_id][0];
ASSERT_TRUE(dst->valid);
EXPECT_EQ(dst->ops_mlayer_info_idc, 2);
// The decoder should have inherited mlayer_info from the referenced OPS.
EXPECT_EQ(dst->op[0].mlayer_info.ops_mlayer_map[0], 0x3);
EXPECT_EQ(dst->op[0].mlayer_info.OPMLayerCount[0], 2);
}
TEST_F(OpsTest, OpsColorIdcHighValues) {
const int idc_values[] = { 0, 1, 4, 8, 20 };
for (int ci = 0; ci < 5; ci++) {
const int xlayer_id = 0;
OperatingPointSet src;
av2_set_ops_params(&src, xlayer_id, 0, 1);
src.ops_color_info_present_flag = 1;
src.op[0].color_info.ops_color_description_idc = idc_values[ci];
if (idc_values[ci] == 0) {
src.op[0].color_info.ops_color_primaries = 9;
src.op[0].color_info.ops_transfer_characteristics = 16;
src.op[0].color_info.ops_matrix_coefficients = 9;
}
memset(buf_, 0, sizeof(buf_));
uint32_t written = write_ops_obu(&src, xlayer_id, buf_);
ASSERT_GT(written, 0u) << "idc=" << idc_values[ci];
memset(pbi_, 0, sizeof(*pbi_));
struct avm_read_bit_buffer rb = { buf_, buf_ + written, 0, nullptr,
rb_error_handler };
uint32_t read = av2_read_operating_point_set_obu(pbi_, xlayer_id, &rb);
ASSERT_EQ(read, written) << "idc=" << idc_values[ci];
EXPECT_EQ(
pbi_->ops_list[xlayer_id][0].op[0].color_info.ops_color_description_idc,
idc_values[ci]);
}
}
TEST_F(OpsTest, OpsFieldBoundarySweep) {
struct {
int ops_id;
int priority;
int intent;
int intent_op;
} params[] = {
{ 0, 0, 0, 0 },
{ 8, 8, 64, 64 },
{ 15, 15, 127, 127 },
};
for (int pi = 0; pi < 3; pi++) {
const int xlayer_id = 0;
OperatingPointSet src;
av2_set_ops_params(&src, xlayer_id, params[pi].ops_id, 1);
src.ops_priority = params[pi].priority;
src.ops_intent = params[pi].intent;
src.ops_intent_present_flag = 1;
src.op[0].ops_intent_op = params[pi].intent_op;
memset(buf_, 0, sizeof(buf_));
uint32_t written = write_ops_obu(&src, xlayer_id, buf_);
ASSERT_GT(written, 0u) << "pi=" << pi;
memset(pbi_, 0, sizeof(*pbi_));
struct avm_read_bit_buffer rb = { buf_, buf_ + written, 0, nullptr,
rb_error_handler };
uint32_t read = av2_read_operating_point_set_obu(pbi_, xlayer_id, &rb);
ASSERT_EQ(read, written) << "pi=" << pi;
const OperatingPointSet *dst =
&pbi_->ops_list[xlayer_id][params[pi].ops_id];
EXPECT_EQ(dst->ops_priority, params[pi].priority);
EXPECT_EQ(dst->ops_intent, params[pi].intent);
EXPECT_EQ(dst->op[0].ops_intent_op, params[pi].intent_op);
}
}
TEST_F(OpsTest, DecoderModelInfoExtremes) {
const uint32_t delays[] = { 0, 1, 100000 };
for (int di = 0; di < 3; di++) {
const int xlayer_id = 0;
OperatingPointSet src;
av2_set_ops_params(&src, xlayer_id, 0, 1);
src.op[0].ops_decoder_model_info_for_this_op_present_flag = 1;
src.op[0].decoder_model_info.ops_decoder_buffer_delay = delays[di];
src.op[0].decoder_model_info.ops_encoder_buffer_delay = delays[di];
memset(buf_, 0, sizeof(buf_));
uint32_t written = write_ops_obu(&src, xlayer_id, buf_);
ASSERT_GT(written, 0u) << "delay=" << delays[di];
memset(pbi_, 0, sizeof(*pbi_));
struct avm_read_bit_buffer rb = { buf_, buf_ + written, 0, nullptr,
rb_error_handler };
uint32_t read = av2_read_operating_point_set_obu(pbi_, xlayer_id, &rb);
ASSERT_EQ(read, written) << "delay=" << delays[di];
EXPECT_EQ(pbi_->ops_list[xlayer_id][0]
.op[0]
.decoder_model_info.ops_decoder_buffer_delay,
delays[di]);
EXPECT_EQ(pbi_->ops_list[xlayer_id][0]
.op[0]
.decoder_model_info.ops_encoder_buffer_delay,
delays[di]);
}
}
TEST_F(OpsTest, GlobalOpsNonContiguousXlayerMap) {
const int xlayer_id = GLOBAL_XLAYER_ID;
OperatingPointSet src;
memset(&src, 0, sizeof(src));
src.valid = 1;
src.obu_xlayer_id = xlayer_id;
src.ops_id = 0;
src.ops_cnt = 1;
src.ops_mlayer_info_idc = 1;
OperatingPoint *op = &src.op[0];
op->ops_initial_display_delay = BUFFER_POOL_MAX_SIZE;
op->ops_xlayer_map = 0x15; // xlayers 0, 2, 4 (non-contiguous)
op->mlayer_info.ops_mlayer_map[0] = 0x1;
op->mlayer_info.ops_tlayer_map[0][0] = 0x1;
op->mlayer_info.ops_mlayer_map[2] = 0x1;
op->mlayer_info.ops_tlayer_map[2][0] = 0x1;
op->mlayer_info.ops_mlayer_map[4] = 0x1;
op->mlayer_info.ops_tlayer_map[4][0] = 0x1;
uint32_t written = write_ops_obu(&src, xlayer_id, buf_);
ASSERT_GT(written, 0u);
struct avm_read_bit_buffer rb = { buf_, buf_ + written, 0, nullptr,
rb_error_handler };
uint32_t read = av2_read_operating_point_set_obu(pbi_, xlayer_id, &rb);
ASSERT_EQ(read, written);
const OperatingPoint *dop = &pbi_->ops_list[xlayer_id][0].op[0];
EXPECT_EQ(dop->ops_xlayer_map, 0x15);
EXPECT_EQ(dop->XCount, 3);
EXPECT_EQ(dop->mlayer_info.OPMLayerCount[0], 1);
EXPECT_EQ(dop->mlayer_info.OPMLayerCount[2], 1);
EXPECT_EQ(dop->mlayer_info.OPMLayerCount[4], 1);
}
} // namespace