blob: 083902a833eefeffb22c1987d7332d5eb176f557 [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/avm_config.h"
#include "avm_dsp/bitreader_buffer.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"
static uint32_t read_ats_region_info(struct AV2Decoder *pbi,
struct AtlasRegionInfo *atlas_reg_params,
struct avm_read_bit_buffer *rb) {
atlas_reg_params->ats_num_region_columns_minus_1 = avm_rb_read_uvlc(rb);
const int num_regions_column =
atlas_reg_params->ats_num_region_columns_minus_1 + 1;
if (num_regions_column > MAX_ATLAS_REGIONS) {
avm_internal_error(&pbi->common.error, AVM_CODEC_UNSUP_BITSTREAM,
"The value of ats_num_region_columns_minus_1 "
"shall be in the range of 0 to %d, inclusive.",
(MAX_ATLAS_REGIONS - 1));
}
atlas_reg_params->ats_num_region_rows_minus_1 = avm_rb_read_uvlc(rb);
const int num_regions_row = atlas_reg_params->ats_num_region_rows_minus_1 + 1;
if (num_regions_row > MAX_ATLAS_REGIONS) {
avm_internal_error(&pbi->common.error, AVM_CODEC_UNSUP_BITSTREAM,
"The value of ats_num_region_rows_minus_1[%d][%d] shall "
"be in the range of 0 to %d, inclusive.",
(MAX_ATLAS_REGIONS - 1));
}
atlas_reg_params->ats_uniform_spacing_flag = avm_rb_read_bit(rb);
if (!atlas_reg_params->ats_uniform_spacing_flag) {
for (int i = 0; i < num_regions_column; i++) {
atlas_reg_params->ats_column_width_minus_1[i] = avm_rb_read_uvlc(rb);
atlas_reg_params->AtlasWidth +=
(atlas_reg_params->ats_column_width_minus_1[i] + 1);
}
for (int i = 0; i < num_regions_row; i++) {
atlas_reg_params->ats_row_height_minus_1[i] = avm_rb_read_uvlc(rb);
atlas_reg_params->AtlasHeight +=
(atlas_reg_params->ats_row_height_minus_1[i] + 1);
}
} else {
atlas_reg_params->ats_region_width_minus_1 = avm_rb_read_uvlc(rb);
atlas_reg_params->ats_region_height_minus_1 = avm_rb_read_uvlc(rb);
atlas_reg_params->AtlasWidth =
(atlas_reg_params->ats_region_width_minus_1 + 1) * num_regions_column;
atlas_reg_params->AtlasHeight =
(atlas_reg_params->ats_region_height_minus_1 + 1) * num_regions_row;
}
atlas_reg_params->NumRegionsInAtlas = num_regions_column * num_regions_row;
return 0;
}
static uint32_t read_ats_basic_info(struct AV2Decoder *pbi,
struct AtlasBasicInfo *ats_basic_info,
struct avm_read_bit_buffer *rb) {
ats_basic_info->ats_stream_id_present = avm_rb_read_bit(rb);
ats_basic_info->ats_atlas_width = avm_rb_read_uvlc(rb);
ats_basic_info->ats_atlas_height = avm_rb_read_uvlc(rb);
ats_basic_info->ats_num_atlas_segments_minus_1 = avm_rb_read_uvlc(rb);
ats_basic_info->AtlasWidth = ats_basic_info->ats_atlas_width;
ats_basic_info->AtlasHeight = ats_basic_info->ats_atlas_height;
int NumSegments = ats_basic_info->ats_num_atlas_segments_minus_1 + 1;
if (NumSegments > MAX_NUM_ATLAS_SEGMENTS) {
avm_internal_error(&pbi->common.error, AVM_CODEC_UNSUP_BITSTREAM,
"The value of ats_num_atlas_segments_minus_1 "
"shall be in the range of 0 to %d, inclusive.",
(MAX_NUM_ATLAS_SEGMENTS - 1));
}
for (int i = 0; i < NumSegments; i++) {
if (ats_basic_info->ats_stream_id_present) {
ats_basic_info->ats_input_stream_id[i] = avm_rb_read_literal(rb, 5);
}
ats_basic_info->ats_segment_top_left_pos_x[i] = avm_rb_read_uvlc(rb);
ats_basic_info->ats_segment_top_left_pos_y[i] = avm_rb_read_uvlc(rb);
ats_basic_info->ats_segment_width[i] = avm_rb_read_uvlc(rb);
ats_basic_info->ats_segment_height[i] = avm_rb_read_uvlc(rb);
}
return 0;
}
static uint32_t read_ats_region_to_segment_mapping(
struct AV2Decoder *pbi, struct AtlasRegionToSegmentMapping *ats_reg_seg_map,
int obu_xLayer_id, int xAId, int NumRegionsInAtlas,
struct avm_read_bit_buffer *rb) {
ats_reg_seg_map->ats_single_region_per_atlas_segment_flag =
avm_rb_read_bit(rb);
if (!ats_reg_seg_map->ats_single_region_per_atlas_segment_flag) {
ats_reg_seg_map->ats_num_atlas_segments_minus_1 = avm_rb_read_uvlc(rb);
int NumSegments = ats_reg_seg_map->ats_num_atlas_segments_minus_1 + 1;
if (NumSegments > MAX_NUM_ATLAS_SEGMENTS) {
avm_internal_error(&pbi->common.error, AVM_CODEC_UNSUP_BITSTREAM,
"The value of ats_num_atlas_segments_minus_1 "
"shall be in the range of 0 to %d, inclusive.",
(MAX_NUM_ATLAS_SEGMENTS - 1));
}
for (int i = 0; i < NumSegments; i++) {
// read top-left row and column
ats_reg_seg_map->ats_top_left_region_column[i] = avm_rb_read_uvlc(rb);
ats_reg_seg_map->ats_top_left_region_row[i] = avm_rb_read_uvlc(rb);
// read row and column offsets
ats_reg_seg_map->ats_bottom_right_region_column_offset[i] =
avm_rb_read_uvlc(rb);
ats_reg_seg_map->ats_bottom_right_region_row_offset[i] =
avm_rb_read_uvlc(rb);
// derive ats_bottom_right_region_column
ats_reg_seg_map->ats_bottom_right_region_column[i] =
ats_reg_seg_map->ats_top_left_region_column[i] +
ats_reg_seg_map->ats_bottom_right_region_column_offset[i];
// derive ats_bottom_right_region_row
ats_reg_seg_map->ats_bottom_right_region_row[i] =
ats_reg_seg_map->ats_top_left_region_row[i] +
ats_reg_seg_map->ats_bottom_right_region_row_offset[i];
}
} else {
if (NumRegionsInAtlas > MAX_NUM_ATLAS_SEGMENTS) {
avm_internal_error(
&pbi->common.error, AVM_CODEC_UNSUP_BITSTREAM,
"If ats_single_region_per_atlas_segment_flag[%d][%d] is enabled, "
"NumRegionsInAtlas shall not be larger than %d.",
obu_xLayer_id, xAId, MAX_NUM_ATLAS_SEGMENTS);
}
ats_reg_seg_map->ats_num_atlas_segments_minus_1 = NumRegionsInAtlas - 1;
}
return 0;
}
static uint32_t read_ats_label_segment_info(
struct AV2Decoder *pbi, struct AtlasSegmentInfo *atlas_params,
int NumSegments, struct avm_read_bit_buffer *rb) {
assert(NumSegments >= 0);
(void)pbi;
struct AtlasLabelSegmentInfo *ats_label = &atlas_params->ats_label_seg;
ats_label->ats_signalled_atlas_segment_ids_flag = avm_rb_read_bit(rb);
if (ats_label->ats_signalled_atlas_segment_ids_flag) {
for (int i = 0; i < NumSegments; i++) {
ats_label->ats_atlas_segment_id[i] =
avm_rb_read_literal(rb, ATLAS_LABEL_SEG_ID_BITS);
ats_label->AtlasSegmentIDToIndex[ats_label->ats_atlas_segment_id[i]] = i;
ats_label->AtlasSegmentIndexToID[i] = ats_label->ats_atlas_segment_id[i];
}
} else {
for (int i = 0; i < NumSegments; i++) {
ats_label->ats_atlas_segment_id[i] = i;
ats_label->AtlasSegmentIDToIndex[i] = i;
ats_label->AtlasSegmentIndexToID[i] = i;
}
}
return 0;
}
static uint32_t read_ats_multistream_alpha_atlas_info(
struct AV2Decoder *pbi, struct AtlasBasicInfo *ats_basic_info,
struct avm_read_bit_buffer *rb) {
ats_basic_info->ats_atlas_width = avm_rb_read_uvlc(rb);
ats_basic_info->ats_atlas_height = avm_rb_read_uvlc(rb);
ats_basic_info->ats_num_atlas_segments_minus_1 = avm_rb_read_uvlc(rb);
int NumSegments = ats_basic_info->ats_num_atlas_segments_minus_1 + 1;
if (NumSegments > MAX_NUM_ATLAS_SEGMENTS) {
avm_internal_error(&pbi->common.error, AVM_CODEC_UNSUP_BITSTREAM,
"The value of ats_num_atlas_segments_minus_1 "
"shall be in the range of 0 to %d, inclusive.",
(MAX_NUM_ATLAS_SEGMENTS - 1));
}
ats_basic_info->AtlasWidth = ats_basic_info->ats_atlas_width;
ats_basic_info->AtlasHeight = ats_basic_info->ats_atlas_height;
ats_basic_info->ats_alpha_segments_present_flag = avm_rb_read_bit(rb);
ats_basic_info->ats_background_info_present_flag = avm_rb_read_bit(rb);
if (ats_basic_info->ats_background_info_present_flag == 1) {
ats_basic_info->ats_background_red_value = avm_rb_read_literal(rb, 8);
ats_basic_info->ats_background_green_value = avm_rb_read_literal(rb, 8);
ats_basic_info->ats_background_blue_value = avm_rb_read_literal(rb, 8);
}
for (int i = 0; i < NumSegments; i++) {
ats_basic_info->ats_input_stream_id[i] = avm_rb_read_literal(rb, 5);
ats_basic_info->ats_segment_top_left_pos_x[i] = avm_rb_read_uvlc(rb);
ats_basic_info->ats_segment_top_left_pos_y[i] = avm_rb_read_uvlc(rb);
ats_basic_info->ats_segment_width[i] = avm_rb_read_uvlc(rb);
ats_basic_info->ats_segment_height[i] = avm_rb_read_uvlc(rb);
if (ats_basic_info->ats_alpha_segments_present_flag == 1 &&
i < NumSegments - 1)
ats_basic_info->ats_alpha_segment_flag[i] = avm_rb_read_bit(rb);
}
return 0;
}
static uint32_t read_ats_multistream_atlas_info(
struct AV2Decoder *pbi, struct AtlasBasicInfo *ats_basic_info,
int obu_xLayer_id, int xAId, struct avm_read_bit_buffer *rb) {
ats_basic_info->ats_atlas_width = avm_rb_read_uvlc(rb);
ats_basic_info->ats_atlas_height = avm_rb_read_uvlc(rb);
ats_basic_info->ats_num_atlas_segments_minus_1 = avm_rb_read_uvlc(rb);
int NumSegments = ats_basic_info->ats_num_atlas_segments_minus_1 + 1;
if (NumSegments > MAX_NUM_ATLAS_SEGMENTS) {
avm_internal_error(&pbi->common.error, AVM_CODEC_UNSUP_BITSTREAM,
"The value of ats_num_atlas_segments_minus_1 "
"shall be in the range of 0 to %d, inclusive.",
obu_xLayer_id, xAId, (MAX_NUM_ATLAS_SEGMENTS - 1));
}
ats_basic_info->AtlasWidth = ats_basic_info->ats_atlas_width;
ats_basic_info->AtlasHeight = ats_basic_info->ats_atlas_height;
ats_basic_info->ats_background_info_present_flag = avm_rb_read_bit(rb);
if (ats_basic_info->ats_background_info_present_flag == 1) {
ats_basic_info->ats_background_red_value = avm_rb_read_literal(rb, 8);
ats_basic_info->ats_background_green_value = avm_rb_read_literal(rb, 8);
ats_basic_info->ats_background_blue_value = avm_rb_read_literal(rb, 8);
}
for (int i = 0; i < NumSegments; i++) {
ats_basic_info->ats_input_stream_id[i] = avm_rb_read_literal(rb, 5);
ats_basic_info->ats_segment_top_left_pos_x[i] = avm_rb_read_uvlc(rb);
ats_basic_info->ats_segment_top_left_pos_y[i] = avm_rb_read_uvlc(rb);
ats_basic_info->ats_segment_width[i] = avm_rb_read_uvlc(rb);
ats_basic_info->ats_segment_height[i] = avm_rb_read_uvlc(rb);
}
return 0;
}
uint32_t av2_read_atlas_segment_info_obu(struct AV2Decoder *pbi,
int obu_xLayer_id,
struct avm_read_bit_buffer *rb) {
const uint32_t saved_bit_offset = rb->bit_offset;
assert(rb->error_handler);
int atlas_segment_id = avm_rb_read_literal(rb, ATLAS_SEG_ID_BITS);
struct AtlasSegmentInfo *atlas_params = NULL;
int atlas_pos = -1;
for (int i = 0; i < pbi->atlas_counter; i++) {
if (pbi->atlas_list[obu_xLayer_id][i].atlas_segment_id ==
atlas_segment_id) {
atlas_pos = i;
break;
}
}
if (atlas_pos != -1) {
atlas_params = &pbi->atlas_list[obu_xLayer_id][atlas_pos];
} else {
const int idx = AVMMIN(pbi->atlas_counter, MAX_NUM_ATLAS_SEG_ID - 1);
atlas_params = &pbi->atlas_list[obu_xLayer_id][idx];
pbi->atlas_counter = AVMMIN(pbi->atlas_counter + 1, MAX_NUM_ATLAS_SEG_ID);
atlas_params->ats_basic_info = &atlas_params->ats_basic_info_s;
}
atlas_params->valid = 1;
atlas_params->obu_xlayer_id = obu_xLayer_id;
atlas_params->atlas_segment_id = atlas_segment_id;
int xAId = atlas_params->atlas_segment_id;
atlas_params->atlas_segment_mode_idc = avm_rb_read_uvlc(rb);
if (atlas_params->atlas_segment_mode_idc >= ATLAS_TYPES) {
avm_internal_error(&pbi->common.error, AVM_CODEC_ERROR,
"Unsupported atlas_segment_mode_idc, whose value should "
"be smaller than ATLAS_TYPES");
}
int num_segments = -1; // invalid
if (atlas_params->atlas_segment_mode_idc == ENHANCED_ATLAS) {
read_ats_region_info(pbi, &atlas_params->ats_reg_params, rb);
read_ats_region_to_segment_mapping(
pbi, &atlas_params->ats_reg_seg_map, obu_xLayer_id, xAId,
atlas_params->ats_reg_params.NumRegionsInAtlas, rb);
num_segments =
atlas_params->ats_reg_seg_map.ats_num_atlas_segments_minus_1 + 1;
} else if (atlas_params->atlas_segment_mode_idc == BASIC_ATLAS) {
read_ats_basic_info(pbi, atlas_params->ats_basic_info, rb);
num_segments =
atlas_params->ats_basic_info->ats_num_atlas_segments_minus_1 + 1;
} else if (atlas_params->atlas_segment_mode_idc == SINGLE_ATLAS) {
atlas_params->ats_reg_seg_map.ats_num_atlas_segments_minus_1 = 0;
num_segments = 1; // equivalent to (ats_num_atlas_segments_minus_1 + 1)
atlas_params->ats_nominal_width_minus1 = avm_rb_read_uvlc(rb);
atlas_params->ats_nominal_height_minus1 = avm_rb_read_uvlc(rb);
} else if (atlas_params->atlas_segment_mode_idc == MULTISTREAM_ATLAS) {
read_ats_multistream_atlas_info(pbi, atlas_params->ats_basic_info,
obu_xLayer_id, xAId, rb);
num_segments =
atlas_params->ats_basic_info->ats_num_atlas_segments_minus_1 + 1;
} else if (atlas_params->atlas_segment_mode_idc == MULTISTREAM_ALPHA_ATLAS) {
read_ats_multistream_alpha_atlas_info(pbi, atlas_params->ats_basic_info,
rb);
num_segments =
atlas_params->ats_basic_info->ats_num_atlas_segments_minus_1 + 1;
}
// Label each atlas segment
read_ats_label_segment_info(pbi, atlas_params, num_segments, rb);
#if CONFIG_F414_OBU_EXTENSION
size_t bits_before_ext = rb->bit_offset - saved_bit_offset;
atlas_params->ats_extension_present_flag = avm_rb_read_bit(rb);
if (atlas_params->ats_extension_present_flag) {
// Extension data bits = total - bits_read_before_extension -1 (ext flag) -
// trailing bits
int extension_bits = read_obu_extension_bits(
rb->bit_buffer, rb->bit_buffer_end - rb->bit_buffer, bits_before_ext,
&pbi->common.error);
if (extension_bits > 0) {
// skip over the extension bits
rb->bit_offset += extension_bits;
} else {
// No extension data present
}
}
#endif // CONFIG_F414_OBU_EXTENSION
if (av2_check_trailing_bits(pbi, rb) != 0) {
return 0;
}
return ((rb->bit_offset - saved_bit_offset + 7) >> 3);
}