blob: e578ff3e9f8c8009162e616d1e405dee479094c7 [file]
/*
* 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 "av2/common/annexA.h"
#include "avm/internal/avm_codec_internal.h"
#include "config/avm_config.h"
#include "av2/common/av2_common_int.h"
#include "av2/common/blockd.h"
#include "av2/common/enums.h"
/* clang-format off */
/*
//===================================================================================
// Table A.1: AV2 Multi-Sequence Configurations
//===================================================================================
* ConfigurationID | Configuration Label | Toolset | BitDepth | Chroma Format
* ----------------|---------------------|---------|-------------|-------------------
* 0 | C_Main_420_10 | Main | 8, 10 | 4:0:0, 4:2:0
* 1 | C_Main_422_10 | Main | 8, 10 | 4:0:0, 4:2:0, 4:2:2
* 2 | C_Main_444_10 | Main | 8, 10 | 4:0:0, 4:2:0, 4:4:4
* 3-63 | Reserved | - | - |
*
* Notes:
* - ConfigurationID: Identifies the multi-sequence configuration (6-bit value)
* - Chroma Format: Supplrted bit depths for this configuration
* - Chroma Format: Support chroma subsampling formats
* - Resered: ConfigurationID valies 3-64 are reserved for future use
*/
/* clang-format on */
#if CONFIG_AV2_PROFILES
typedef enum {
C_MAIN_420_10 = 0, // Main toolset, 8/10-bit, 4:0:0/4:2:0
C_MAIN_422_10 = 1, // Main toolset, 8/10-bit, 4:0:0/4:2:0/4:2:2
C_MAIN_444_10 = 2, // Main toolset, 8/10-bit, 4:0:0/4:2:0/4:4:4
} AV2_CONFIGURATION_LABEL;
/* clang-format off */
/*=================================================================
// Table A.2: Allowed Values for Sub-Bitstream Syntax Elements
//=================================================================
*
* Table A.2: Allowed Values for Sub-Bitstream Syntax Elements Accoring to Multi-Sequence Configuration
*
* Configuration Label | seq_profile_idc | chroma_format_idc | bit_depth_idc
* ------------------------|----------------------|-------------------------|---------------
* C_Main_420_10 | 0..5 | 0 or 1 | 0 or 1
* C_Main_422_10 | 0..5 | 0, 1, 3 | 0 or 1
* C_Main_444_10 | 0..5 | 0, 1, 2 | 0 or 1
*
* Notes:
* - seq_profile_idc: Allowed profile values (0=MAIN_420_10_IP0, 1=MAIN_420_10_IP1, 2=MAIN_420_10_IP2, 3=Main_420_10,
* 4=MAIN_422_10, 5=MAIN_444_10)
* - bit_depth_idc: 0=8-bit, 1=10-bit
* - C_Main_420_10: Supports profiles 0-5, chroma 4:0:0 and 4:2:0, bit depths 8 and 10
* - C_Main_422_10: Supports profiles 0-5, chroma 4:0:0, 4:2:0 and 4:2:2, bit depth 8 and 10
* - C_Main_444_10: Supports profiles 0-5, chroma 4:0:0, 4:2:0, and 4:4:4, bit depth 8 and 10
*/
// Interoperability Point Table
// Number of interoperability points (0-15)
// INTEROP_0: Max 4 extended, 1 embedded, no combinations
// INTEROP_1: Max 4 extended, 2 embedded, no combinations
// INTEROP_2: Max 4 extended, 3 embedded, combinations allowed
// INTEROP_3-14: Reserved
// INTEROP_15: Max values, combinations allowed
/* clang-format on */
typedef enum {
INTEROP_0,
INTEROP_1,
INTEROP_2,
INTEROP_3,
NUM_INTEROP_POINTS = 16,
} INTEROP_POINTS;
static const int seq_profile_max_mlayer_cnt[MAX_PROFILES] = {
1,
2,
3,
MAX_NUM_MLAYERS,
MAX_NUM_MLAYERS,
MAX_NUM_MLAYERS,
#if CONFIG_TESTONLY_12BIT_SUPPORT
MAX_NUM_MLAYERS,
#endif // CONFIG_TESTONLY_12BIT_SUPPORT
};
/* clang-format off */
/* Table A4 Allowed values for sub-bitstream syntax elements to conform to a specific AV2 profile
* Profile Label | seq_profile_idc | chroma_format_idc | bit_depth_idc | max_mlayer_cnt
* -------------------------------------------------------------------------------------------------------------------
* Main_420_10_IP0 0 CHROMA_FORMAT_400 0 or 1 1
* CHROMA_FORMAT_420
* -------------------------------------------------------------------------------------------------------------------
* Main_420_10_IP1 1 CHROMA_FORMAT_400 0 or 1 2
* CHROMA_FORMAT_420
* --------------------------------------------------------------------------------------------------------------------
* Main_420_10_IP2 2 CHROMA_FORMAT_400 0 or 1 3
* CHROMA_FORMAT_420
* --------------------------------------------------------------------------------------------------------------------
* Main_420_10 3 CHROMA_FORMAT_400 0 or 1 -
* CHROMA_FORMAT_420
* ---------------------------------------------------------------------------------------------------------------------
* Main_422_10 4 CHROMA_FORMAT_400 0 or 1 -
* CHROMA_FORMAT_420
* CHROMA_FORMAT_422
* ---------------------------------------------------------------------------------------------------------------------
* Main_444_10 5 CHROMA_FORMAT_400 0 or 1 -
* CHROMA_FORMAT_420
* CHROMA_FORMAT_444
* ---------------------------------------------------------------------------------------------------------------------
* Reserved 6-31
* ---------------------------------------------------------------------------------------------------------------------
*/
/* clang-format on */
//=================================================================
// Profile Conformance Functions
//=================================================================
// Helper functions
// Get interoperability point from seq_profile_idc
// Return -1 for reserved seq_profile_idc values
static INLINE int av2_get_max_mlayer_cnt_from_profile(int seq_profile_idc) {
if (seq_profile_idc < 0 || seq_profile_idc >= MAX_PROFILES) return -1;
return seq_profile_max_mlayer_cnt[seq_profile_idc];
}
static int check_bit_depth_8_10(int bit_depth) {
if (bit_depth != AVM_BITS_8 && bit_depth != AVM_BITS_10) {
return 0;
}
return 1;
}
static avm_codec_err_t check_chroma_format(int monochrome, int is_420,
int is_422, int is_444,
int allow_420, int allow_422,
int allow_444) {
// Monochrome (4:0:0) is always allowed
if (monochrome) {
return AVM_CODEC_OK;
}
// Check if the current chroma format is allowed
if ((is_420 && allow_420) || (is_422 && allow_422) || (is_444 && allow_444)) {
return AVM_CODEC_OK;
}
return AVM_CODEC_UNSUP_BITSTREAM;
}
static avm_codec_err_t check_mlayer_count(int profile_idc, int seq_max_mcount) {
const int max_allowed_mcount =
av2_get_max_mlayer_cnt_from_profile(profile_idc);
if (max_allowed_mcount < 0 && seq_max_mcount > max_allowed_mcount) {
return AVM_CODEC_UNSUP_BITSTREAM;
}
return AVM_CODEC_OK;
}
// Checks the profile conformance -- Top-level function
int av2_check_profile_interop_conformance(
struct SequenceHeader *seq_params,
struct avm_internal_error_info *error_info, int is_decoder) {
const BITSTREAM_PROFILE profile = seq_params->seq_profile_idc;
const avm_bit_depth_t bit_depth = seq_params->bit_depth;
const uint8_t monochrome = seq_params->monochrome;
const int seq_max_mcount = seq_params->seq_max_mlayer_cnt_minus_1 + 1;
#if CONFIG_TESTONLY_12BIT_SUPPORT
if (profile == TEST_ONLY_12BIT_PROFILE && bit_depth == AVM_BITS_12) return 1;
#endif // CONFIG_TESTONLY_12BIT_SUPPORT
uint32_t chroma_format_idc = CHROMA_FORMAT_420;
avm_codec_err_t err = av2_get_chroma_format_idc(
seq_params->subsampling_x, seq_params->subsampling_y, monochrome,
&chroma_format_idc);
(void)err;
const int is_420 = (chroma_format_idc == CHROMA_FORMAT_420);
const int is_422 = (chroma_format_idc == CHROMA_FORMAT_422);
const int is_444 = (chroma_format_idc == CHROMA_FORMAT_444);
// All profiles support 8-bit and 10-bit only
int is_valid_bit_depth = check_bit_depth_8_10(bit_depth);
if (!is_valid_bit_depth) {
return 0;
}
switch (profile) {
case MAIN_420_10_IP0:
case MAIN_420_10_IP1:
case MAIN_420_10_IP2:
case MAIN_420_10:
// All 420 profiles: allow only 4:2:0 and monochrome
err = check_chroma_format(monochrome, is_420, is_422, is_444,
1 /* allow_420 */, 0 /* allow_422 */,
0 /* allow_444 */);
if (err != AVM_CODEC_OK) {
avm_internal_error(
error_info,
is_decoder ? AVM_CODEC_UNSUP_BITSTREAM : AVM_CODEC_INVALID_PARAM,
"Profile %d only supports YUV 4:0:0 and YUV 4:2:0 color formats, "
"but color format YUV %s was provided.",
(BITSTREAM_PROFILE)profile, is_422 ? "4:2:2" : "4:4:4");
}
break;
case MAIN_422_10:
// 422 profile: allow 4:2:0 and 4:2:2 and monochrome
err = check_chroma_format(monochrome, is_420, is_422, is_444,
1 /* allow_420 */, 1 /* allow_422 */,
0 /* allow_444 */);
if (err != AVM_CODEC_OK) {
avm_internal_error(
error_info,
is_decoder ? AVM_CODEC_UNSUP_BITSTREAM : AVM_CODEC_INVALID_PARAM,
"Profile %d only supports YUV 4:0:0, YUV 4:2:0 and YUV 4:2:2 color "
"formats, but color format YUV 4:4:4 was provided.",
(BITSTREAM_PROFILE)profile);
}
break;
case MAIN_444_10:
// 444 profile: allow 4:2:0, 4:2:2, 4:4:4 and monochrome
err = check_chroma_format(monochrome, is_420, is_422, is_444,
1 /* allow_420 */, 1 /* allow_422 */,
1 /* allow_444 */);
if (err != AVM_CODEC_OK) {
avm_internal_error(
error_info,
is_decoder ? AVM_CODEC_UNSUP_BITSTREAM : AVM_CODEC_INVALID_PARAM,
"Profile %d only supports YUV 4:0:0, YUV 4:2:0 and YUV 4:4:4 color "
"formats, but color format YUV 4:2:2 was provided.",
(BITSTREAM_PROFILE)profile);
}
break;
default:
// Profile 6+ - reserved/unsupported
return 0;
}
// Check if Max mlayer count is valid for IP profiles (seq_profile_idc <=2)
err = check_mlayer_count(profile, seq_max_mcount);
if (err != AVM_CODEC_OK) {
avm_internal_error(
error_info,
is_decoder ? AVM_CODEC_UNSUP_BITSTREAM : AVM_CODEC_INVALID_PARAM,
"Unsupported mlayer count present in the bitstream");
}
return 1;
}
/* clang-format off */
/*=================================================================
// Profile Scaling and Bitrate Functions
//=================================================================
* Table A.5: Definition of ProfileScalingFactor
* seq_profile_idc | bit_depth_idc | chroma_format_idc | ProfileScalingFactor
* ----------------------------------------------------------------------------------------------------
* (0, 1, 2, 3, 4, 5) (0, 1) CHROMA_FORMAT_400 0
* CHROMA_FORMAT_420
* ----------------------------------------------------------------------------------------------------
* 4 (0, 1) CHROMA_FORMAT_422 1
* ----------------------------------------------------------------------------------------------------
* 5 (0, 1) CHROMA_FORMAT_444 2
* ----------------------------------------------------------------------------------------------------
*/
/* clang-format on */
int get_profile_scaling_factor(int seq_profile_idc, int chroma_format_idc) {
// Table A.5: Definition of ProfileScalingFactor
// Note that the bit_depth_idx must be 0 or 1 for all valid combinations
// All profiles (0-5) with 400 or 420 chroma format
if (chroma_format_idc == CHROMA_FORMAT_400 ||
chroma_format_idc == CHROMA_FORMAT_420) {
return 0;
}
// Profile 4 with 422 chroma format
if (seq_profile_idc == MAIN_422_10 &&
chroma_format_idc == CHROMA_FORMAT_422) {
return 1;
}
// Profile 5 with 444 chroma format
if (seq_profile_idc == MAIN_444_10 &&
chroma_format_idc == CHROMA_FORMAT_444) {
return 2;
}
// Default for invalid combinations
return 0;
}
#endif // CONFIG_AV2_PROFILES