blob: 11ff98b772d32e8c21605c7fc493836f0a1273ef [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_F153_FGM_OBU
void copy_fgm_from_list(AV1_COMMON *cm, aom_film_grain_t *pars,
const struct film_grain_model *fgm) {
const SequenceHeader *const seq_params = &cm->seq_params;
pars->bit_depth = seq_params->bit_depth;
#if CONFIG_CWG_F298_REC11
for (int c = 0; c < 3; c++) {
pars->fgm_points[c] = fgm->fgm_points[c];
}
for (int i = 0; i < 14; i++) {
for (int j = 0; j < 2; j++) {
pars->fgm_scaling_points_0[i][j] = fgm->fgm_scaling_points[0][i][j];
pars->fgm_scaling_points_1[i][j] = fgm->fgm_scaling_points[1][i][j];
pars->fgm_scaling_points_2[i][j] = fgm->fgm_scaling_points[2][i][j];
} // j
} // i
#else
for (int i = 0; i < 14; i++) {
pars->scaling_points_y[i][0] = fgm->scaling_points_y[i][0];
pars->scaling_points_y[i][1] = fgm->scaling_points_y[i][1];
}
pars->num_y_points = fgm->num_y_points; // value: 0..14
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 2; j++) {
pars->scaling_points_cb[i][j] = fgm->scaling_points_cb[i][j];
pars->scaling_points_cr[i][j] = fgm->scaling_points_cr[i][j];
}
}
pars->num_cb_points = fgm->num_cb_points;
pars->num_cr_points = fgm->num_cr_points;
#endif // CONFIG_CWG_F298_REC11
pars->scaling_shift = fgm->scaling_shift;
pars->ar_coeff_lag = fgm->ar_coeff_lag;
// 8 bit values
for (int i = 0; i < 24; i++) pars->ar_coeffs_y[i] = fgm->ar_coeffs_y[i];
for (int i = 0; i < 25; i++) {
pars->ar_coeffs_cb[i] = fgm->ar_coeffs_cb[i];
pars->ar_coeffs_cr[i] = fgm->ar_coeffs_cr[i];
}
pars->ar_coeff_shift = fgm->ar_coeff_shift;
pars->cb_mult = fgm->cb_mult;
pars->cb_luma_mult = fgm->cb_luma_mult;
pars->cb_offset = fgm->cb_offset;
pars->cr_mult = fgm->cr_mult;
pars->cr_luma_mult = fgm->cr_luma_mult;
pars->cr_offset = fgm->cr_offset;
pars->overlap_flag = fgm->overlap_flag;
pars->clip_to_restricted_range = fgm->clip_to_restricted_range;
#if CONFIG_CWG_F298_REC11
pars->fgm_scale_from_channel0_flag = fgm->fgm_scale_from_channel0_flag;
#else
pars->chroma_scaling_from_luma = fgm->chroma_scaling_from_luma;
#endif
pars->grain_scale_shift = fgm->grain_scale_shift;
pars->block_size = fgm->block_size;
}
static void read_film_grain_model(struct film_grain_model *fgm, int chroma_idc,
struct aom_read_bit_buffer *rb,
struct aom_internal_error_info *error_info) {
int monochrome = chroma_idc == CHROMA_FORMAT_400;
int subsampling_x = chroma_idc == CHROMA_FORMAT_444 ? 0 : 1;
int subsampling_y =
(chroma_idc == CHROMA_FORMAT_422 || chroma_idc == CHROMA_FORMAT_444) ? 0
: 1;
// Scaling functions parameters
#if CONFIG_CWG_F298_REC11
int fgmNumChannels = monochrome ? 1 : 3;
if (fgmNumChannels > 1) {
fgm->fgm_scale_from_channel0_flag = aom_rb_read_bit(rb);
} else {
fgm->fgm_scale_from_channel0_flag = 0;
}
int fgmNumScalingChannels =
fgm->fgm_scale_from_channel0_flag ? 1 : fgmNumChannels;
for (int c = 0; c < fgmNumScalingChannels; c++) {
fgm->fgm_points[c] = aom_rb_read_literal(rb, 4); // max 14
if (fgm->fgm_points[c] > 14) {
aom_internal_error(error_info, AOM_CODEC_UNSUP_BITSTREAM,
"Number of points for film grain %s scaling "
"function exceeds the maximum value.",
c == 0 ? "y"
: c == 1 ? "cb"
: "cr");
}
if (fgm->fgm_points[c]) {
int point_value_increment_bits_minus1 = aom_rb_read_literal(rb, 3);
int point_scaling_bits_minus5 = aom_rb_read_literal(rb, 2);
int bitsIncr = point_value_increment_bits_minus1 + 1;
int bitsScal = point_scaling_bits_minus5 + 5;
for (int i = 0; i < fgm->fgm_points[c]; i++) {
int fgm_value_increment = aom_rb_read_literal(rb, bitsIncr);
if (i == 0)
fgm->fgm_scaling_points[c][i][0] = fgm_value_increment;
else
fgm->fgm_scaling_points[c][i][0] =
fgm->fgm_scaling_points[c][i - 1][0] + fgm_value_increment;
if (i && fgm->fgm_scaling_points[c][i - 1][0] >=
fgm->fgm_scaling_points[c][i][0]) {
aom_internal_error(error_info, AOM_CODEC_UNSUP_BITSTREAM,
"First coordinate of the %s scaling function "
"points shall be increasing.",
c == 0 ? "y"
: c == 1 ? "cb"
: "cr");
}
fgm->fgm_scaling_points[c][i][1] = aom_rb_read_literal(rb, bitsScal);
}
}
} // c < fgmNumScalingChannels
// Initialize unsignaled values to zero
for (int c = fgmNumScalingChannels; c < 3; c++) fgm->fgm_points[c] = 0;
if ((subsampling_x == 1) && (subsampling_y == 1) &&
(((fgm->fgm_points[1] == 0) && (fgm->fgm_points[2] != 0)) ||
((fgm->fgm_points[1] != 0) && (fgm->fgm_points[2] == 0)))) {
aom_internal_error(error_info, AOM_CODEC_UNSUP_BITSTREAM,
"In YCbCr 4:2:0, film grain shall be applied "
"to both chroma components or neither.");
}
#else // CONFIG_CWG_F298_REC11
fgm->num_y_points = aom_rb_read_literal(rb, 4); // max 14
if (fgm->num_y_points > 14) {
aom_internal_error(error_info, AOM_CODEC_UNSUP_BITSTREAM,
"Number of points for film grain %s scaling "
"function exceeds the maximum value.",
"y");
}
if (fgm->num_y_points) {
int point_y_value_increment_bits_minus1 = aom_rb_read_literal(rb, 3);
int point_y_scaling_bits_minus5 = aom_rb_read_literal(rb, 2);
int bitsIncr = point_y_value_increment_bits_minus1 + 1;
int bitsScal = point_y_scaling_bits_minus5 + 5;
for (int i = 0; i < fgm->num_y_points; i++) {
fgm->scaling_points_y[i][0] = aom_rb_read_literal(rb, bitsIncr);
if (i && fgm->scaling_points_y[i - 1][0] >= fgm->scaling_points_y[i][0]) {
aom_internal_error(error_info, AOM_CODEC_UNSUP_BITSTREAM,
"First coordinate of the %s scaling function "
"points shall be increasing.",
"y");
}
fgm->scaling_points_y[i][1] = aom_rb_read_literal(rb, bitsScal);
}
}
if (!monochrome)
fgm->chroma_scaling_from_luma = aom_rb_read_bit(rb);
else
fgm->chroma_scaling_from_luma = 0;
if (monochrome || fgm->chroma_scaling_from_luma ||
((subsampling_x == 1) && (subsampling_y == 1) &&
(fgm->num_y_points == 0))) {
fgm->num_cb_points = 0;
fgm->num_cr_points = 0;
} else {
fgm->num_cb_points = aom_rb_read_literal(rb, 4); // max 10
if (fgm->num_cb_points > 10) {
aom_internal_error(error_info, AOM_CODEC_UNSUP_BITSTREAM,
"Number of points for film grain %s scaling "
"function exceeds the maximum value.",
"cb");
}
if (fgm->num_cb_points) {
int point_cb_value_increment_bits_minus1 = aom_rb_read_literal(rb, 3);
int point_cb_scaling_bits_minus5 = aom_rb_read_literal(rb, 2);
int bitsIncr = point_cb_value_increment_bits_minus1 + 1;
int bitsScal = point_cb_scaling_bits_minus5 + 5;
for (int i = 0; i < fgm->num_cb_points; i++) {
fgm->scaling_points_cb[i][0] = aom_rb_read_literal(rb, bitsIncr);
if (i &&
fgm->scaling_points_cb[i - 1][0] >= fgm->scaling_points_cb[i][0]) {
aom_internal_error(error_info, AOM_CODEC_UNSUP_BITSTREAM,
"First coordinate of the %s scaling function "
"points shall be increasing.",
"cb");
}
fgm->scaling_points_cb[i][1] = aom_rb_read_literal(rb, bitsScal);
}
}
fgm->num_cr_points = aom_rb_read_literal(rb, 4); // max 10
if (fgm->num_cr_points > 10) {
aom_internal_error(error_info, AOM_CODEC_UNSUP_BITSTREAM,
"Number of points for film grain %s scaling "
"function exceeds the maximum value.",
"cr");
}
if (fgm->num_cr_points) {
int point_cr_value_increment_bits_minus1 = aom_rb_read_literal(rb, 3);
int point_cr_scaling_bits_minus5 = aom_rb_read_literal(rb, 2);
int bitsIncr = point_cr_value_increment_bits_minus1 + 1;
int bitsScal = point_cr_scaling_bits_minus5 + 5;
for (int i = 0; i < fgm->num_cr_points; i++) {
fgm->scaling_points_cr[i][0] = aom_rb_read_literal(rb, bitsIncr);
if (i &&
fgm->scaling_points_cr[i - 1][0] >= fgm->scaling_points_cr[i][0]) {
aom_internal_error(error_info, AOM_CODEC_UNSUP_BITSTREAM,
"First coordinate of the %s scaling function "
"points shall be increasing.",
"cr");
}
fgm->scaling_points_cr[i][1] = aom_rb_read_literal(rb, bitsScal);
}
}
if ((subsampling_x == 1) && (subsampling_y == 1) &&
(((fgm->num_cb_points == 0) && (fgm->num_cr_points != 0)) ||
((fgm->num_cb_points != 0) && (fgm->num_cr_points == 0)))) {
aom_internal_error(error_info, AOM_CODEC_UNSUP_BITSTREAM,
"In YCbCr 4:2:0, film grain shall be applied "
"to both chroma components or neither.");
}
}
#endif // CONFIG_CWG_F298_REC11
fgm->scaling_shift = aom_rb_read_literal(rb, 2) + 8; // 8 + value
// AR coefficients
// Only sent if the corresponsing scaling function has
// more than 0 points
fgm->ar_coeff_lag = aom_rb_read_literal(rb, 2);
int num_pos_luma = 2 * fgm->ar_coeff_lag * (fgm->ar_coeff_lag + 1);
int num_pos_chroma = num_pos_luma;
#if CONFIG_CWG_F298_REC11
if (fgm->fgm_points[0])
#else
if (fgm->num_y_points)
#endif
{
++num_pos_chroma;
int bits_per_ar_coeff_y_minus5 = aom_rb_read_literal(rb, 2);
int BitsArY = bits_per_ar_coeff_y_minus5 + 5;
for (int i = 0; i < num_pos_luma; i++)
fgm->ar_coeffs_y[i] = aom_rb_read_literal(rb, BitsArY) - 128;
}
#if CONFIG_CWG_F298_REC11
if (fgm->fgm_points[1] || fgm->fgm_scale_from_channel0_flag)
#else
if (fgm->num_cb_points || fgm->chroma_scaling_from_luma)
#endif
{
int bits_per_ar_coeff_cb_minus5 = aom_rb_read_literal(rb, 2);
int BitsArCb = bits_per_ar_coeff_cb_minus5 + 5;
for (int i = 0; i < num_pos_chroma; i++)
fgm->ar_coeffs_cb[i] = aom_rb_read_literal(rb, BitsArCb) - 128;
}
#if CONFIG_CWG_F298_REC11
if (fgm->fgm_points[2] || fgm->fgm_scale_from_channel0_flag)
#else
if (fgm->num_cr_points || fgm->chroma_scaling_from_luma)
#endif
{
int bits_per_ar_coeff_cr_minus5 = aom_rb_read_literal(rb, 2);
int BitsArCr = bits_per_ar_coeff_cr_minus5 + 5;
for (int i = 0; i < num_pos_chroma; i++)
fgm->ar_coeffs_cr[i] = aom_rb_read_literal(rb, BitsArCr) - 128;
}
fgm->ar_coeff_shift = aom_rb_read_literal(rb, 2) + 6; // 6 + value
fgm->grain_scale_shift = aom_rb_read_literal(rb, 2);
#if CONFIG_CWG_F298_REC11
if (fgm->fgm_points[1] > 0)
#else
if (fgm->num_cb_points)
#endif
{
fgm->cb_mult = aom_rb_read_literal(rb, 8);
fgm->cb_luma_mult = aom_rb_read_literal(rb, 8);
fgm->cb_offset = aom_rb_read_literal(rb, 9);
}
#if CONFIG_CWG_F298_REC11
if (fgm->fgm_points[2] > 0)
#else
if (fgm->num_cr_points)
#endif
{
fgm->cr_mult = aom_rb_read_literal(rb, 8);
fgm->cr_luma_mult = aom_rb_read_literal(rb, 8);
fgm->cr_offset = aom_rb_read_literal(rb, 9);
}
fgm->overlap_flag = aom_rb_read_bit(rb);
fgm->clip_to_restricted_range = aom_rb_read_bit(rb);
fgm->block_size = aom_rb_read_bit(rb);
}
// acc_fgm_id_bitmap is an in/out parameter. The caller should set
// *acc_fgm_id_bitmap to 0 before the first call to read_fgm_obu(). Each
// read_fgm_obu() call updates *acc_fgm_id_bitmap by bitwise-ORing the
// fgm_bit_map from the FGM OBU with *acc_fgm_id_bitmap.
uint32_t read_fgm_obu(AV1Decoder *pbi, const int obu_tlayer_id,
const int obu_mlayer_id, uint32_t *acc_fgm_id_bitmap,
int fgm_seq_id_in_tu, struct aom_read_bit_buffer *rb) {
const uint32_t saved_bit_offset = rb->bit_offset;
int fgm_bit_map = aom_rb_read_literal(rb, MAX_FGM_NUM);
if (*acc_fgm_id_bitmap & (uint32_t)fgm_bit_map) {
aom_internal_error(
&pbi->common.error, AOM_CODEC_INVALID_PARAM,
"fgm_bit_map(%d) overlaps the accumulated fgm_bit_map(%d)", fgm_bit_map,
acc_fgm_id_bitmap);
} else {
*acc_fgm_id_bitmap |= fgm_bit_map;
}
int fgm_chroma_idc = aom_rb_read_uvlc(rb);
if (fgm_chroma_idc >= NUM_CHROMA_FORMATS) {
aom_internal_error(&pbi->common.error, AOM_CODEC_UNSUP_BITSTREAM,
"Invalid fgm_chroma_idc [%d].", fgm_chroma_idc);
}
for (int j = 0; j < MAX_FGM_NUM; j++) {
// This process overwrites the position(pbi->fg_list[fgm_id]) if the fgm_id
// is the same.
if (fgm_bit_map & (1 << j)) {
int fgm_id = j;
memset(&pbi->fgm_list[fgm_id], 0, sizeof(pbi->fgm_list[fgm_id]));
pbi->fgm_list[fgm_id].fgm_seq_id_in_tu = fgm_seq_id_in_tu;
pbi->fgm_list[fgm_id].fgm_id = fgm_id;
pbi->fgm_list[fgm_id].fgm_mlayer_id = obu_mlayer_id;
pbi->fgm_list[fgm_id].fgm_tlayer_id = obu_tlayer_id;
pbi->fgm_list[fgm_id].fgm_chroma_idc = fgm_chroma_idc;
read_film_grain_model(&pbi->fgm_list[fgm_id], fgm_chroma_idc, rb,
&pbi->common.error);
} // if
} // j
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_F153_FGM_OBU