FFmpeg/libavcodec/evc_ps.c
Andreas Rheinhardt 790f793844 avutil/common: Don't auto-include mem.h
There are lots of files that don't need it: The number of object
files that actually need it went down from 2011 to 884 here.

Keep it for external users in order to not cause breakages.

Also improve the other headers a bit while just at it.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2024-03-31 00:08:43 +01:00

444 lines
16 KiB
C

/*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/mem.h"
#include "get_bits.h"
#include "golomb.h"
#include "evc.h"
#include "evc_ps.h"
#define EXTENDED_SAR 255
// @see ISO_IEC_23094-1 (7.3.7 Reference picture list structure syntax)
static int ref_pic_list_struct(const EVCParserSPS *sps, GetBitContext *gb, RefPicListStruct *rpl)
{
uint32_t delta_poc_st, strp_entry_sign_flag = 0;
rpl->ref_pic_num = get_ue_golomb_long(gb);
if ((unsigned)rpl->ref_pic_num > sps->sps_max_dec_pic_buffering_minus1)
return AVERROR_INVALIDDATA;
if (rpl->ref_pic_num > 0) {
delta_poc_st = get_ue_golomb_long(gb);
rpl->ref_pics[0] = delta_poc_st;
if (rpl->ref_pics[0] != 0) {
strp_entry_sign_flag = get_bits(gb, 1);
rpl->ref_pics[0] *= 1 - (strp_entry_sign_flag << 1);
}
}
for (int i = 1; i < rpl->ref_pic_num; ++i) {
delta_poc_st = get_ue_golomb_long(gb);
if (delta_poc_st != 0)
strp_entry_sign_flag = get_bits(gb, 1);
rpl->ref_pics[i] = rpl->ref_pics[i - 1] + delta_poc_st * (1 - (strp_entry_sign_flag << 1));
}
return 0;
}
// @see ISO_IEC_23094-1 (E.2.2 HRD parameters syntax)
static int hrd_parameters(GetBitContext *gb, HRDParameters *hrd)
{
hrd->cpb_cnt_minus1 = get_ue_golomb_31(gb);
if (hrd->cpb_cnt_minus1 >= FF_ARRAY_ELEMS(hrd->cpb_size_value_minus1))
return AVERROR_INVALIDDATA;
hrd->bit_rate_scale = get_bits(gb, 4);
hrd->cpb_size_scale = get_bits(gb, 4);
for (int SchedSelIdx = 0; SchedSelIdx <= hrd->cpb_cnt_minus1; SchedSelIdx++) {
hrd->bit_rate_value_minus1[SchedSelIdx] = get_ue_golomb_long(gb);
hrd->cpb_size_value_minus1[SchedSelIdx] = get_ue_golomb_long(gb);
hrd->cbr_flag[SchedSelIdx] = get_bits(gb, 1);
}
hrd->initial_cpb_removal_delay_length_minus1 = get_bits(gb, 5);
hrd->cpb_removal_delay_length_minus1 = get_bits(gb, 5);
hrd->cpb_removal_delay_length_minus1 = get_bits(gb, 5);
hrd->time_offset_length = get_bits(gb, 5);
return 0;
}
// @see ISO_IEC_23094-1 (E.2.1 VUI parameters syntax)
static int vui_parameters(GetBitContext *gb, VUIParameters *vui)
{
int ret;
vui->aspect_ratio_info_present_flag = get_bits(gb, 1);
if (vui->aspect_ratio_info_present_flag) {
vui->aspect_ratio_idc = get_bits(gb, 8);
if (vui->aspect_ratio_idc == EXTENDED_SAR) {
vui->sar_width = get_bits(gb, 16);
vui->sar_height = get_bits(gb, 16);
}
}
vui->overscan_info_present_flag = get_bits(gb, 1);
if (vui->overscan_info_present_flag)
vui->overscan_appropriate_flag = get_bits(gb, 1);
vui->video_signal_type_present_flag = get_bits(gb, 1);
if (vui->video_signal_type_present_flag) {
vui->video_format = get_bits(gb, 3);
vui->video_full_range_flag = get_bits(gb, 1);
vui->colour_description_present_flag = get_bits(gb, 1);
if (vui->colour_description_present_flag) {
vui->colour_primaries = get_bits(gb, 8);
vui->transfer_characteristics = get_bits(gb, 8);
vui->matrix_coefficients = get_bits(gb, 8);
}
}
vui->chroma_loc_info_present_flag = get_bits(gb, 1);
if (vui->chroma_loc_info_present_flag) {
vui->chroma_sample_loc_type_top_field = get_ue_golomb_31(gb);
vui->chroma_sample_loc_type_bottom_field = get_ue_golomb_31(gb);
}
vui->neutral_chroma_indication_flag = get_bits(gb, 1);
vui->field_seq_flag = get_bits(gb, 1);
vui->timing_info_present_flag = get_bits(gb, 1);
if (vui->timing_info_present_flag) {
vui->num_units_in_tick = get_bits_long(gb, 32);
vui->time_scale = get_bits_long(gb, 32);
vui->fixed_pic_rate_flag = get_bits(gb, 1);
}
vui->nal_hrd_parameters_present_flag = get_bits(gb, 1);
if (vui->nal_hrd_parameters_present_flag) {
ret = hrd_parameters(gb, &vui->hrd_parameters);
if (ret < 0)
return ret;
}
vui->vcl_hrd_parameters_present_flag = get_bits(gb, 1);
if (vui->vcl_hrd_parameters_present_flag) {
ret = hrd_parameters(gb, &vui->hrd_parameters);
if (ret < 0)
return ret;
}
if (vui->nal_hrd_parameters_present_flag || vui->vcl_hrd_parameters_present_flag)
vui->low_delay_hrd_flag = get_bits(gb, 1);
vui->pic_struct_present_flag = get_bits(gb, 1);
vui->bitstream_restriction_flag = get_bits(gb, 1);
if (vui->bitstream_restriction_flag) {
vui->motion_vectors_over_pic_boundaries_flag = get_bits(gb, 1);
vui->max_bytes_per_pic_denom = get_ue_golomb_31(gb);
vui->max_bits_per_mb_denom = get_ue_golomb_31(gb);
vui->log2_max_mv_length_horizontal = get_ue_golomb_31(gb);
vui->log2_max_mv_length_vertical = get_ue_golomb_31(gb);
vui->num_reorder_pics = get_ue_golomb_long(gb);
vui->max_dec_pic_buffering = get_ue_golomb_long(gb);
}
return 0;
}
// @see ISO_IEC_23094-1 (7.3.2.1 SPS RBSP syntax)
int ff_evc_parse_sps(GetBitContext *gb, EVCParamSets *ps)
{
EVCParserSPS *sps;
unsigned sps_seq_parameter_set_id;
int ret;
sps_seq_parameter_set_id = get_ue_golomb(gb);
if (sps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT)
return AVERROR_INVALIDDATA;
sps = av_mallocz(sizeof(*sps));
if (!sps)
return AVERROR(ENOMEM);
sps->sps_seq_parameter_set_id = sps_seq_parameter_set_id;
// the Baseline profile is indicated by profile_idc eqal to 0
// the Main profile is indicated by profile_idc eqal to 1
sps->profile_idc = get_bits(gb, 8);
sps->level_idc = get_bits(gb, 8);
skip_bits_long(gb, 32); /* skip toolset_idc_h */
skip_bits_long(gb, 32); /* skip toolset_idc_l */
// 0 - monochrome
// 1 - 4:2:0
// 2 - 4:2:2
// 3 - 4:4:4
sps->chroma_format_idc = get_ue_golomb_31(gb);
if (sps->chroma_format_idc > 3) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
sps->pic_width_in_luma_samples = get_ue_golomb_long(gb);
sps->pic_height_in_luma_samples = get_ue_golomb_long(gb);
sps->bit_depth_luma_minus8 = get_ue_golomb_31(gb);
sps->bit_depth_chroma_minus8 = get_ue_golomb_31(gb);
sps->sps_btt_flag = get_bits1(gb);
if (sps->sps_btt_flag) {
sps->log2_ctu_size_minus2 = get_ue_golomb_long(gb);
sps->log2_min_cb_size_minus2 = get_ue_golomb_long(gb);
sps->log2_diff_ctu_max_14_cb_size = get_ue_golomb_long(gb);
sps->log2_diff_ctu_max_tt_cb_size = get_ue_golomb_long(gb);
sps->log2_diff_min_cb_min_tt_cb_size_minus2 = get_ue_golomb_long(gb);
}
sps->sps_suco_flag = get_bits1(gb);
if (sps->sps_suco_flag) {
sps->log2_diff_ctu_size_max_suco_cb_size = get_ue_golomb_long(gb);
sps->log2_diff_max_suco_min_suco_cb_size = get_ue_golomb_long(gb);
}
sps->sps_admvp_flag = get_bits1(gb);
if (sps->sps_admvp_flag) {
sps->sps_affine_flag = get_bits1(gb);
sps->sps_amvr_flag = get_bits1(gb);
sps->sps_dmvr_flag = get_bits1(gb);
sps->sps_mmvd_flag = get_bits1(gb);
sps->sps_hmvp_flag = get_bits1(gb);
}
sps->sps_eipd_flag = get_bits1(gb);
if (sps->sps_eipd_flag) {
sps->sps_ibc_flag = get_bits1(gb);
if (sps->sps_ibc_flag)
sps->log2_max_ibc_cand_size_minus2 = get_ue_golomb(gb);
}
sps->sps_cm_init_flag = get_bits1(gb);
if (sps->sps_cm_init_flag)
sps->sps_adcc_flag = get_bits1(gb);
sps->sps_iqt_flag = get_bits1(gb);
if (sps->sps_iqt_flag)
sps->sps_ats_flag = get_bits1(gb);
sps->sps_addb_flag = get_bits1(gb);
sps->sps_alf_flag = get_bits1(gb);
sps->sps_htdf_flag = get_bits1(gb);
sps->sps_rpl_flag = get_bits1(gb);
sps->sps_pocs_flag = get_bits1(gb);
sps->sps_dquant_flag = get_bits1(gb);
sps->sps_dra_flag = get_bits1(gb);
if (sps->sps_pocs_flag) {
sps->log2_max_pic_order_cnt_lsb_minus4 = get_ue_golomb(gb);
if (sps->log2_max_pic_order_cnt_lsb_minus4 > 12U) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
}
if (!sps->sps_pocs_flag || !sps->sps_rpl_flag) {
sps->log2_sub_gop_length = get_ue_golomb(gb);
if (sps->log2_sub_gop_length > 5U) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
if (sps->log2_sub_gop_length == 0)
sps->log2_ref_pic_gap_length = get_ue_golomb(gb);
}
if (!sps->sps_rpl_flag)
sps->max_num_tid0_ref_pics = get_ue_golomb_31(gb);
else {
sps->sps_max_dec_pic_buffering_minus1 = get_ue_golomb_long(gb);
if ((unsigned)sps->sps_max_dec_pic_buffering_minus1 > 16 - 1) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
sps->long_term_ref_pic_flag = get_bits1(gb);
sps->rpl1_same_as_rpl0_flag = get_bits1(gb);
sps->num_ref_pic_list_in_sps[0] = get_ue_golomb(gb);
if ((unsigned)sps->num_ref_pic_list_in_sps[0] >= EVC_MAX_NUM_RPLS) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
for (int i = 0; i < sps->num_ref_pic_list_in_sps[0]; ++i) {
ret = ref_pic_list_struct(sps, gb, &sps->rpls[0][i]);
if (ret < 0)
goto fail;
}
if (!sps->rpl1_same_as_rpl0_flag) {
sps->num_ref_pic_list_in_sps[1] = get_ue_golomb(gb);
if ((unsigned)sps->num_ref_pic_list_in_sps[1] >= EVC_MAX_NUM_RPLS) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
for (int i = 0; i < sps->num_ref_pic_list_in_sps[1]; ++i) {
ret = ref_pic_list_struct(sps, gb, &sps->rpls[1][i]);
if (ret < 0)
goto fail;
}
}
}
sps->picture_cropping_flag = get_bits1(gb);
if (sps->picture_cropping_flag) {
sps->picture_crop_left_offset = get_ue_golomb_long(gb);
sps->picture_crop_right_offset = get_ue_golomb_long(gb);
sps->picture_crop_top_offset = get_ue_golomb_long(gb);
sps->picture_crop_bottom_offset = get_ue_golomb_long(gb);
}
if (sps->chroma_format_idc != 0) {
sps->chroma_qp_table_struct.chroma_qp_table_present_flag = get_bits1(gb);
if (sps->chroma_qp_table_struct.chroma_qp_table_present_flag) {
sps->chroma_qp_table_struct.same_qp_table_for_chroma = get_bits1(gb);
sps->chroma_qp_table_struct.global_offset_flag = get_bits1(gb);
for (int i = 0; i < (sps->chroma_qp_table_struct.same_qp_table_for_chroma ? 1 : 2); i++) {
sps->chroma_qp_table_struct.num_points_in_qp_table_minus1[i] = get_ue_golomb(gb);
if (sps->chroma_qp_table_struct.num_points_in_qp_table_minus1[i] >= EVC_MAX_QP_TABLE_SIZE) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
for (int j = 0; j <= sps->chroma_qp_table_struct.num_points_in_qp_table_minus1[i]; j++) {
sps->chroma_qp_table_struct.delta_qp_in_val_minus1[i][j] = get_bits(gb, 6);
sps->chroma_qp_table_struct.delta_qp_out_val[i][j] = get_se_golomb_long(gb);
}
}
}
}
sps->vui_parameters_present_flag = get_bits1(gb);
if (sps->vui_parameters_present_flag) {
ret = vui_parameters(gb, &(sps->vui_parameters));
if (ret < 0)
goto fail;
}
// @note
// If necessary, add the missing fields to the EVCParserSPS structure
// and then extend parser implementation
av_freep(&ps->sps[sps_seq_parameter_set_id]);
ps->sps[sps_seq_parameter_set_id] = sps;
return 0;
fail:
av_free(sps);
return ret;
}
// @see ISO_IEC_23094-1 (7.3.2.2 SPS RBSP syntax)
//
// @note
// The current implementation of parse_sps function doesn't handle VUI parameters parsing.
// If it will be needed, parse_sps function could be extended to handle VUI parameters parsing
// to initialize fields of the AVCodecContex i.e. color_primaries, color_trc,color_range
//
int ff_evc_parse_pps(GetBitContext *gb, EVCParamSets *ps)
{
EVCParserPPS *pps;
unsigned pps_pic_parameter_set_id;
int ret;
pps_pic_parameter_set_id = get_ue_golomb(gb);
if (pps_pic_parameter_set_id >= EVC_MAX_PPS_COUNT)
return AVERROR_INVALIDDATA;
pps = av_mallocz(sizeof(*pps));
if (!pps)
return AVERROR(ENOMEM);
pps->pps_pic_parameter_set_id = pps_pic_parameter_set_id;
pps->pps_seq_parameter_set_id = get_ue_golomb(gb);
if (pps->pps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
pps->num_ref_idx_default_active_minus1[0] = get_ue_golomb(gb);
pps->num_ref_idx_default_active_minus1[1] = get_ue_golomb(gb);
pps->additional_lt_poc_lsb_len = get_ue_golomb(gb);
pps->rpl1_idx_present_flag = get_bits1(gb);
pps->single_tile_in_pic_flag = get_bits1(gb);
if (!pps->single_tile_in_pic_flag) {
pps->num_tile_columns_minus1 = get_ue_golomb(gb);
pps->num_tile_rows_minus1 = get_ue_golomb(gb);
if (pps->num_tile_columns_minus1 >= EVC_MAX_TILE_COLUMNS ||
pps->num_tile_rows_minus1 >= EVC_MAX_TILE_ROWS) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
pps->uniform_tile_spacing_flag = get_bits1(gb);
if (!pps->uniform_tile_spacing_flag) {
for (int i = 0; i < pps->num_tile_columns_minus1; i++)
pps->tile_column_width_minus1[i] = get_ue_golomb(gb);
for (int i = 0; i < pps->num_tile_rows_minus1; i++)
pps->tile_row_height_minus1[i] = get_ue_golomb(gb);
}
pps->loop_filter_across_tiles_enabled_flag = get_bits1(gb);
pps->tile_offset_len_minus1 = get_ue_golomb(gb);
}
pps->tile_id_len_minus1 = get_ue_golomb(gb);
if (pps->tile_id_len_minus1 > 15U) {
ret = AVERROR_INVALIDDATA;
goto fail;
}
pps->explicit_tile_id_flag = get_bits1(gb);
if (pps->explicit_tile_id_flag) {
for (int i = 0; i <= pps->num_tile_rows_minus1; i++) {
for (int j = 0; j <= pps->num_tile_columns_minus1; j++)
pps->tile_id_val[i][j] = get_bits(gb, pps->tile_id_len_minus1 + 1);
}
}
pps->pic_dra_enabled_flag = 0;
pps->pic_dra_enabled_flag = get_bits1(gb);
if (pps->pic_dra_enabled_flag)
pps->pic_dra_aps_id = get_bits(gb, 5);
pps->arbitrary_slice_present_flag = get_bits1(gb);
pps->constrained_intra_pred_flag = get_bits1(gb);
pps->cu_qp_delta_enabled_flag = get_bits1(gb);
if (pps->cu_qp_delta_enabled_flag)
pps->log2_cu_qp_delta_area_minus6 = get_ue_golomb(gb);
av_freep(&ps->pps[pps_pic_parameter_set_id]);
ps->pps[pps_pic_parameter_set_id] = pps;
return 0;
fail:
av_free(pps);
return ret;
}
void ff_evc_ps_free(EVCParamSets *ps) {
for (int i = 0; i < EVC_MAX_SPS_COUNT; i++)
av_freep(&ps->sps[i]);
for (int i = 0; i < EVC_MAX_PPS_COUNT; i++)
av_freep(&ps->pps[i]);
}