diff mbox series

[FFmpeg-devel,04/10] avcodec/evc_parse: split off Parameter Set parsing into its own file

Message ID 20230617220015.12669-1-jamrial@gmail.com
State New
Headers show
Series [FFmpeg-devel,1/3] avcodec/evc_frame_merge: use av_fast_realloc() | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 fail Make fate failed
andriy/make_x86 success Make finished
andriy/make_fate_x86 fail Make fate failed

Commit Message

James Almer June 17, 2023, 10 p.m. UTC
Signed-off-by: James Almer <jamrial@gmail.com>
---
 libavcodec/Makefile              |   2 +-
 libavcodec/evc_frame_merge_bsf.c |   4 +-
 libavcodec/evc_parse.c           | 371 +-----------------------------
 libavcodec/evc_parse.h           | 198 +---------------
 libavcodec/evc_parser.c          |   2 +-
 libavcodec/evc_ps.c              | 381 +++++++++++++++++++++++++++++++
 libavcodec/evc_ps.h              | 228 ++++++++++++++++++
 7 files changed, 621 insertions(+), 565 deletions(-)
 create mode 100644 libavcodec/evc_ps.c
 create mode 100644 libavcodec/evc_ps.h

Comments

Dawid Kozinski June 20, 2023, 7:37 a.m. UTC | #1
Why have you split off the parameter set parsing into its own file? Just
asking what's the reason.



> -----Original Message-----
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of James
> Almer
> Sent: niedziela, 18 czerwca 2023 00:00
> To: ffmpeg-devel@ffmpeg.org
> Subject: [FFmpeg-devel] [PATCH 04/10] avcodec/evc_parse: split off
Parameter
> Set parsing into its own file
> 
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
>  libavcodec/Makefile              |   2 +-
>  libavcodec/evc_frame_merge_bsf.c |   4 +-
>  libavcodec/evc_parse.c           | 371 +-----------------------------
>  libavcodec/evc_parse.h           | 198 +---------------
>  libavcodec/evc_parser.c          |   2 +-
>  libavcodec/evc_ps.c              | 381 +++++++++++++++++++++++++++++++
>  libavcodec/evc_ps.h              | 228 ++++++++++++++++++
>  7 files changed, 621 insertions(+), 565 deletions(-)
>  create mode 100644 libavcodec/evc_ps.c
>  create mode 100644 libavcodec/evc_ps.h
> 
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index 0ce8fe5b9c..723bfa25c7 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -84,7 +84,7 @@ OBJS-$(CONFIG_DCT)                     += dct.o
dct32_fixed.o
> dct32_float.o
>  OBJS-$(CONFIG_DEFLATE_WRAPPER)         += zlib_wrapper.o
>  OBJS-$(CONFIG_DOVI_RPU)                += dovi_rpu.o
>  OBJS-$(CONFIG_ERROR_RESILIENCE)        += error_resilience.o
> -OBJS-$(CONFIG_EVCPARSE)                += evc_parse.o
> +OBJS-$(CONFIG_EVCPARSE)                += evc_parse.o evc_ps.o
>  OBJS-$(CONFIG_EXIF)                    += exif.o tiff_common.o
>  OBJS-$(CONFIG_FAANDCT)                 += faandct.o
>  OBJS-$(CONFIG_FAANIDCT)                += faanidct.o
> diff --git a/libavcodec/evc_frame_merge_bsf.c
> b/libavcodec/evc_frame_merge_bsf.c
> index 540bb63631..f497780afb 100644
> --- a/libavcodec/evc_frame_merge_bsf.c
> +++ b/libavcodec/evc_frame_merge_bsf.c
> @@ -58,7 +58,7 @@ static void evc_frame_merge_flush(AVBSFContext *bsf)
>  {
>      EVCFMergeContext *ctx = bsf->priv_data;
> 
> -    ff_evc_parse_free(&ctx->parser_ctx);
> +    ff_evc_ps_free(&ctx->parser_ctx.ps);
>      av_packet_unref(ctx->in);
>      ctx->au_buffer.data_size = 0;
>  }
> @@ -147,7 +147,7 @@ static void evc_frame_merge_close(AVBSFContext *bsf)
>      EVCFMergeContext *ctx = bsf->priv_data;
> 
>      av_packet_free(&ctx->in);
> -    ff_evc_parse_free(&ctx->parser_ctx);
> +    ff_evc_ps_free(&ctx->parser_ctx.ps);
> 
>      ctx->au_buffer.capacity = 0;
>      av_freep(&ctx->au_buffer.data);
> diff --git a/libavcodec/evc_parse.c b/libavcodec/evc_parse.c
> index 44be5c5291..a8e6356b96 100644
> --- a/libavcodec/evc_parse.c
> +++ b/libavcodec/evc_parse.c
> @@ -21,8 +21,6 @@
>  #include "evc.h"
>  #include "evc_parse.h"
> 
> -#define EXTENDED_SAR            255
> -
>  #define NUM_CHROMA_FORMATS      4   // @see ISO_IEC_23094-1 section 6.2
> table 2
> 
>  static const enum AVPixelFormat pix_fmts_8bit[NUM_CHROMA_FORMATS] = {
> @@ -71,355 +69,6 @@ int ff_evc_get_temporal_id(const uint8_t *bits, int
> bits_size, void *logctx)
>      return temporal_id;
>  }
> 
> -// @see ISO_IEC_23094-1 (7.3.7 Reference picture list structure syntax)
> -static int ref_pic_list_struct(GetBitContext *gb, RefPicListStruct *rpl)
> -{
> -    uint32_t delta_poc_st, strp_entry_sign_flag = 0;
> -    rpl->ref_pic_num = get_ue_golomb(gb);
> -    if (rpl->ref_pic_num > 0) {
> -        delta_poc_st = get_ue_golomb(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(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(gb);
> -    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(gb);
> -        hrd->cpb_size_value_minus1[SchedSelIdx] = get_ue_golomb(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)
> -{
> -    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(gb);
> -        vui->chroma_sample_loc_type_bottom_field = get_ue_golomb(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(gb, 32);
> -        vui->time_scale = get_bits(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)
> -        hrd_parameters(gb, &vui->hrd_parameters);
> -    vui->vcl_hrd_parameters_present_flag = get_bits(gb, 1);
> -    if (vui->vcl_hrd_parameters_present_flag)
> -        hrd_parameters(gb, &vui->hrd_parameters);
> -    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(gb);
> -        vui->max_bits_per_mb_denom = get_ue_golomb(gb);
> -        vui->log2_max_mv_length_horizontal = get_ue_golomb(gb);
> -        vui->log2_max_mv_length_vertical = get_ue_golomb(gb);
> -        vui->num_reorder_pics = get_ue_golomb(gb);
> -        vui->max_dec_pic_buffering = get_ue_golomb(gb);
> -    }
> -
> -    return 0;
> -}
> -
> -// @see ISO_IEC_23094-1 (7.3.2.1 SPS RBSP syntax)
> -EVCParserSPS *ff_evc_parse_sps(EVCParserContext *ctx, const uint8_t *bs,
int
> bs_size)
> -{
> -    GetBitContext gb;
> -    EVCParserSPS *sps;
> -    int sps_seq_parameter_set_id;
> -
> -    if (init_get_bits8(&gb, bs, bs_size) < 0)
> -        return NULL;
> -
> -    sps_seq_parameter_set_id = get_ue_golomb(&gb);
> -
> -    if (sps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT)
> -        return NULL;
> -
> -    if(!ctx->sps[sps_seq_parameter_set_id]) {
> -        if((ctx->sps[sps_seq_parameter_set_id] =
av_malloc(sizeof(EVCParserSPS)))
> == NULL)
> -            return NULL;
> -    }
> -
> -    sps = ctx->sps[sps_seq_parameter_set_id];
> -    memset(sps, 0, sizeof(*sps));
> -
> -    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(&gb);
> -
> -    sps->pic_width_in_luma_samples = get_ue_golomb(&gb);
> -    sps->pic_height_in_luma_samples = get_ue_golomb(&gb);
> -
> -    sps->bit_depth_luma_minus8 = get_ue_golomb(&gb);
> -    sps->bit_depth_chroma_minus8 = get_ue_golomb(&gb);
> -
> -    sps->sps_btt_flag = get_bits(&gb, 1);
> -    if (sps->sps_btt_flag) {
> -        sps->log2_ctu_size_minus5 = get_ue_golomb(&gb);
> -        sps->log2_min_cb_size_minus2 = get_ue_golomb(&gb);
> -        sps->log2_diff_ctu_max_14_cb_size = get_ue_golomb(&gb);
> -        sps->log2_diff_ctu_max_tt_cb_size = get_ue_golomb(&gb);
> -        sps->log2_diff_min_cb_min_tt_cb_size_minus2 = get_ue_golomb(&gb);
> -    }
> -
> -    sps->sps_suco_flag = get_bits(&gb, 1);
> -    if (sps->sps_suco_flag) {
> -        sps->log2_diff_ctu_size_max_suco_cb_size = get_ue_golomb(&gb);
> -        sps->log2_diff_max_suco_min_suco_cb_size = get_ue_golomb(&gb);
> -    }
> -
> -    sps->sps_admvp_flag = get_bits(&gb, 1);
> -    if (sps->sps_admvp_flag) {
> -        sps->sps_affine_flag = get_bits(&gb, 1);
> -        sps->sps_amvr_flag = get_bits(&gb, 1);
> -        sps->sps_dmvr_flag = get_bits(&gb, 1);
> -        sps->sps_mmvd_flag = get_bits(&gb, 1);
> -        sps->sps_hmvp_flag = get_bits(&gb, 1);
> -    }
> -
> -    sps->sps_eipd_flag =  get_bits(&gb, 1);
> -    if (sps->sps_eipd_flag) {
> -        sps->sps_ibc_flag = get_bits(&gb, 1);
> -        if (sps->sps_ibc_flag)
> -            sps->log2_max_ibc_cand_size_minus2 = get_ue_golomb(&gb);
> -    }
> -
> -    sps->sps_cm_init_flag = get_bits(&gb, 1);
> -    if (sps->sps_cm_init_flag)
> -        sps->sps_adcc_flag = get_bits(&gb, 1);
> -
> -    sps->sps_iqt_flag = get_bits(&gb, 1);
> -    if (sps->sps_iqt_flag)
> -        sps->sps_ats_flag = get_bits(&gb, 1);
> -
> -    sps->sps_addb_flag = get_bits(&gb, 1);
> -    sps->sps_alf_flag = get_bits(&gb, 1);
> -    sps->sps_htdf_flag = get_bits(&gb, 1);
> -    sps->sps_rpl_flag = get_bits(&gb, 1);
> -    sps->sps_pocs_flag = get_bits(&gb, 1);
> -    sps->sps_dquant_flag = get_bits(&gb, 1);
> -    sps->sps_dra_flag = get_bits(&gb, 1);
> -
> -    if (sps->sps_pocs_flag)
> -        sps->log2_max_pic_order_cnt_lsb_minus4 = get_ue_golomb(&gb);
> -
> -    if (!sps->sps_pocs_flag || !sps->sps_rpl_flag) {
> -        sps->log2_sub_gop_length = get_ue_golomb(&gb);
> -        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(&gb);
> -    else {
> -        sps->sps_max_dec_pic_buffering_minus1 = get_ue_golomb(&gb);
> -        sps->long_term_ref_pic_flag = get_bits(&gb, 1);
> -        sps->rpl1_same_as_rpl0_flag = get_bits(&gb, 1);
> -        sps->num_ref_pic_list_in_sps[0] = get_ue_golomb(&gb);
> -
> -        for (int i = 0; i < sps->num_ref_pic_list_in_sps[0]; ++i)
> -            ref_pic_list_struct(&gb, &sps->rpls[0][i]);
> -
> -        if (!sps->rpl1_same_as_rpl0_flag) {
> -            sps->num_ref_pic_list_in_sps[1] = get_ue_golomb(&gb);
> -            for (int i = 0; i < sps->num_ref_pic_list_in_sps[1]; ++i)
> -                ref_pic_list_struct(&gb, &sps->rpls[1][i]);
> -        }
> -    }
> -
> -    sps->picture_cropping_flag = get_bits(&gb, 1);
> -
> -    if (sps->picture_cropping_flag) {
> -        sps->picture_crop_left_offset = get_ue_golomb(&gb);
> -        sps->picture_crop_right_offset = get_ue_golomb(&gb);
> -        sps->picture_crop_top_offset = get_ue_golomb(&gb);
> -        sps->picture_crop_bottom_offset = get_ue_golomb(&gb);
> -    }
> -
> -    if (sps->chroma_format_idc != 0) {
> -        sps->chroma_qp_table_struct.chroma_qp_table_present_flag =
> get_bits(&gb, 1);
> -
> -        if (sps->chroma_qp_table_struct.chroma_qp_table_present_flag) {
> -            sps->chroma_qp_table_struct.same_qp_table_for_chroma =
> get_bits(&gb, 1);
> -            sps->chroma_qp_table_struct.global_offset_flag =
get_bits(&gb, 1);
> -            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);;
> -                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(&gb);
> -                }
> -            }
> -        }
> -    }
> -
> -    sps->vui_parameters_present_flag = get_bits(&gb, 1);
> -    if (sps->vui_parameters_present_flag)
> -        vui_parameters(&gb, &(sps->vui_parameters));
> -
> -    // @note
> -    // If necessary, add the missing fields to the EVCParserSPS structure
> -    // and then extend parser implementation
> -
> -    return sps;
> -}
> -
> -// @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
> -//
> -EVCParserPPS *ff_evc_parse_pps(EVCParserContext *ctx, const uint8_t *bs,
int
> bs_size)
> -{
> -    GetBitContext gb;
> -    EVCParserPPS *pps;
> -
> -    int pps_pic_parameter_set_id;
> -
> -    if (init_get_bits8(&gb, bs, bs_size) < 0)
> -        return NULL;
> -
> -    pps_pic_parameter_set_id = get_ue_golomb(&gb);
> -    if (pps_pic_parameter_set_id > EVC_MAX_PPS_COUNT)
> -        return NULL;
> -
> -    if(!ctx->pps[pps_pic_parameter_set_id]) {
> -        if ((ctx->pps[pps_pic_parameter_set_id] =
> av_malloc(sizeof(EVCParserPPS))) == NULL)
> -            return NULL;
> -    }
> -
> -    pps = ctx->pps[pps_pic_parameter_set_id];
> -    memset(pps, 0, sizeof(*pps));
> -
> -    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) {
> -        av_freep(&ctx->pps[pps_pic_parameter_set_id]);
> -        return NULL;
> -    }
> -
> -    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_bits(&gb, 1);
> -    pps->single_tile_in_pic_flag = get_bits(&gb, 1);
> -
> -    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);
> -        pps->uniform_tile_spacing_flag = get_bits(&gb, 1);
> -
> -        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_bits(&gb, 1);
> -        pps->tile_offset_len_minus1 = get_ue_golomb(&gb);
> -    }
> -
> -    pps->tile_id_len_minus1 = get_ue_golomb(&gb);
> -    pps->explicit_tile_id_flag = get_bits(&gb, 1);
> -
> -    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_bits(&gb, 1);
> -
> -    if (pps->pic_dra_enabled_flag)
> -        pps->pic_dra_aps_id = get_bits(&gb, 5);
> -
> -    pps->arbitrary_slice_present_flag = get_bits(&gb, 1);
> -    pps->constrained_intra_pred_flag = get_bits(&gb, 1);
> -    pps->cu_qp_delta_enabled_flag = get_bits(&gb, 1);
> -
> -    if (pps->cu_qp_delta_enabled_flag)
> -        pps->log2_cu_qp_delta_area_minus6 = get_ue_golomb(&gb);
> -
> -    return pps;
> -}
> -
>  // @see ISO_IEC_23094-1 (7.3.2.6 Slice layer RBSP syntax)
>  static int evc_parse_slice_header(EVCParserContext *ctx,
> EVCParserSliceHeader *sh, const uint8_t *bs, int bs_size)
>  {
> @@ -439,11 +88,11 @@ static int evc_parse_slice_header(EVCParserContext
> *ctx, EVCParserSliceHeader *s
>      if (slice_pic_parameter_set_id < 0 || slice_pic_parameter_set_id >=
> EVC_MAX_PPS_COUNT)
>          return AVERROR_INVALIDDATA;
> 
> -    pps = ctx->pps[slice_pic_parameter_set_id];
> +    pps = ctx->ps.pps[slice_pic_parameter_set_id];
>      if(!pps)
>          return AVERROR_INVALIDDATA;
> 
> -    sps = ctx->sps[pps->pps_seq_parameter_set_id];
> +    sps = ctx->ps.sps[pps->pps_seq_parameter_set_id];
>      if(!sps)
>          return AVERROR_INVALIDDATA;
> 
> @@ -579,7 +228,7 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const
> uint8_t *buf, int buf_siz
>          int SubGopLength;
>          int bit_depth;
> 
> -        sps = ff_evc_parse_sps(ctx, data, nalu_size);
> +        sps = ff_evc_parse_sps(&ctx->ps, data, nalu_size);
>          if (!sps) {
>              av_log(logctx, AV_LOG_ERROR, "SPS parsing error\n");
>              return AVERROR_INVALIDDATA;
> @@ -642,7 +291,7 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const
> uint8_t *buf, int buf_siz
>      case EVC_PPS_NUT: {
>          EVCParserPPS *pps;
> 
> -        pps = ff_evc_parse_pps(ctx, data, nalu_size);
> +        pps = ff_evc_parse_pps(&ctx->ps, data, nalu_size);
>          if (!pps) {
>              av_log(logctx, AV_LOG_ERROR, "PPS parsing error\n");
>              return AVERROR_INVALIDDATA;
> @@ -688,8 +337,8 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx, const
> uint8_t *buf, int buf_siz
> 
>          // POC (picture order count of the current picture) derivation
>          // @see ISO/IEC 23094-1:2020(E) 8.3.1 Decoding process for
picture order
> count
> -        pps = ctx->pps[sh.slice_pic_parameter_set_id];
> -        sps = ctx->sps[pps->pps_seq_parameter_set_id];
> +        pps = ctx->ps.pps[sh.slice_pic_parameter_set_id];
> +        sps = ctx->ps.sps[pps->pps_seq_parameter_set_id];
>          av_assert0(sps && pps);
> 
>          if (sps->sps_pocs_flag) {
> @@ -764,11 +413,3 @@ int ff_evc_parse_nal_unit(EVCParserContext *ctx,
> const uint8_t *buf, int buf_siz
> 
>      return 0;
>  }
> -
> -void ff_evc_parse_free(EVCParserContext *ctx) {
> -    for (int i = 0; i < EVC_MAX_SPS_COUNT; i++)
> -        av_freep(&ctx->sps[i]);
> -
> -    for (int i = 0; i < EVC_MAX_PPS_COUNT; i++)
> -        av_freep(&ctx->pps[i]);
> -}
> diff --git a/libavcodec/evc_parse.h b/libavcodec/evc_parse.h
> index ee4b6c5708..b5462f5711 100644
> --- a/libavcodec/evc_parse.h
> +++ b/libavcodec/evc_parse.h
> @@ -30,190 +30,7 @@
>  #include "libavutil/log.h"
>  #include "libavutil/rational.h"
>  #include "evc.h"
> -
> -#define EVC_MAX_QP_TABLE_SIZE   58
> -#define NUM_CPB                 32
> -
> -// rpl structure
> -typedef struct RefPicListStruct {
> -    int poc;
> -    int tid;
> -    int ref_pic_num;
> -    int ref_pic_active_num;
> -    int ref_pics[EVC_MAX_NUM_REF_PICS];
> -    char pic_type;
> -
> -} RefPicListStruct;
> -
> -// chromaQP table structure to be signalled in SPS
> -typedef struct ChromaQpTable {
> -    int chroma_qp_table_present_flag;       // u(1)
> -    int same_qp_table_for_chroma;           // u(1)
> -    int global_offset_flag;                 // u(1)
> -    int num_points_in_qp_table_minus1[2];   // ue(v)
> -    int delta_qp_in_val_minus1[2][EVC_MAX_QP_TABLE_SIZE];   // u(6)
> -    int delta_qp_out_val[2][EVC_MAX_QP_TABLE_SIZE];         // se(v)
> -} ChromaQpTable;
> -
> -// Hypothetical Reference Decoder (HRD) parameters, part of VUI
> -typedef struct HRDParameters {
> -    int cpb_cnt_minus1;                             // ue(v)
> -    int bit_rate_scale;                             // u(4)
> -    int cpb_size_scale;                             // u(4)
> -    int bit_rate_value_minus1[NUM_CPB];             // ue(v)
> -    int cpb_size_value_minus1[NUM_CPB];             // ue(v)
> -    int cbr_flag[NUM_CPB];                          // u(1)
> -    int initial_cpb_removal_delay_length_minus1;    // u(5)
> -    int cpb_removal_delay_length_minus1;            // u(5)
> -    int dpb_output_delay_length_minus1;             // u(5)
> -    int time_offset_length;                         // u(5)
> -} HRDParameters;
> -
> -// video usability information (VUI) part of SPS
> -typedef struct VUIParameters {
> -    int aspect_ratio_info_present_flag;             // u(1)
> -    int aspect_ratio_idc;                           // u(8)
> -    int sar_width;                                  // u(16)
> -    int sar_height;                                 // u(16)
> -    int overscan_info_present_flag;                 // u(1)
> -    int overscan_appropriate_flag;                  // u(1)
> -    int video_signal_type_present_flag;             // u(1)
> -    int video_format;                               // u(3)
> -    int video_full_range_flag;                      // u(1)
> -    int colour_description_present_flag;            // u(1)
> -    int colour_primaries;                           // u(8)
> -    int transfer_characteristics;                   // u(8)
> -    int matrix_coefficients;                        // u(8)
> -    int chroma_loc_info_present_flag;               // u(1)
> -    int chroma_sample_loc_type_top_field;           // ue(v)
> -    int chroma_sample_loc_type_bottom_field;        // ue(v)
> -    int neutral_chroma_indication_flag;             // u(1)
> -    int field_seq_flag;                             // u(1)
> -    int timing_info_present_flag;                   // u(1)
> -    int num_units_in_tick;                          // u(32)
> -    int time_scale;                                 // u(32)
> -    int fixed_pic_rate_flag;                        // u(1)
> -    int nal_hrd_parameters_present_flag;            // u(1)
> -    int vcl_hrd_parameters_present_flag;            // u(1)
> -    int low_delay_hrd_flag;                         // u(1)
> -    int pic_struct_present_flag;                    // u(1)
> -    int bitstream_restriction_flag;                 // u(1)
> -    int motion_vectors_over_pic_boundaries_flag;    // u(1)
> -    int max_bytes_per_pic_denom;                    // ue(v)
> -    int max_bits_per_mb_denom;                      // ue(v)
> -    int log2_max_mv_length_horizontal;              // ue(v)
> -    int log2_max_mv_length_vertical;                // ue(v)
> -    int num_reorder_pics;                           // ue(v)
> -    int max_dec_pic_buffering;                      // ue(v)
> -
> -    HRDParameters hrd_parameters;
> -} VUIParameters;
> -
> -// The sturcture reflects SPS RBSP(raw byte sequence payload) layout
> -// @see ISO_IEC_23094-1 section 7.3.2.1
> -//
> -// The following descriptors specify the parsing process of each element
> -// u(n) - unsigned integer using n bits
> -// ue(v) - unsigned integer 0-th order Exp_Golomb-coded syntax element
with
> the left bit first
> -typedef struct EVCParserSPS {
> -    int sps_seq_parameter_set_id;   // ue(v)
> -    int profile_idc;                // u(8)
> -    int level_idc;                  // u(8)
> -    int toolset_idc_h;              // u(32)
> -    int toolset_idc_l;              // u(32)
> -    int chroma_format_idc;          // ue(v)
> -    int pic_width_in_luma_samples;  // ue(v)
> -    int pic_height_in_luma_samples; // ue(v)
> -    int bit_depth_luma_minus8;      // ue(v)
> -    int bit_depth_chroma_minus8;    // ue(v)
> -
> -    int sps_btt_flag;                           // u(1)
> -    int log2_ctu_size_minus5;                   // ue(v)
> -    int log2_min_cb_size_minus2;                // ue(v)
> -    int log2_diff_ctu_max_14_cb_size;           // ue(v)
> -    int log2_diff_ctu_max_tt_cb_size;           // ue(v)
> -    int log2_diff_min_cb_min_tt_cb_size_minus2; // ue(v)
> -
> -    int sps_suco_flag;                       // u(1)
> -    int log2_diff_ctu_size_max_suco_cb_size; // ue(v)
> -    int log2_diff_max_suco_min_suco_cb_size; // ue(v)
> -
> -    int sps_admvp_flag;     // u(1)
> -    int sps_affine_flag;    // u(1)
> -    int sps_amvr_flag;      // u(1)
> -    int sps_dmvr_flag;      // u(1)
> -    int sps_mmvd_flag;      // u(1)
> -    int sps_hmvp_flag;      // u(1)
> -
> -    int sps_eipd_flag;                 // u(1)
> -    int sps_ibc_flag;                  // u(1)
> -    int log2_max_ibc_cand_size_minus2; // ue(v)
> -
> -    int sps_cm_init_flag; // u(1)
> -    int sps_adcc_flag;    // u(1)
> -
> -    int sps_iqt_flag; // u(1)
> -    int sps_ats_flag; // u(1)
> -
> -    int sps_addb_flag;   // u(1)
> -    int sps_alf_flag;    // u(1)
> -    int sps_htdf_flag;   // u(1)
> -    int sps_rpl_flag;    // u(1)
> -    int sps_pocs_flag;   // u(1)
> -    int sps_dquant_flag; // u(1)
> -    int sps_dra_flag;    // u(1)
> -
> -    int log2_max_pic_order_cnt_lsb_minus4; // ue(v)
> -    int log2_sub_gop_length;               // ue(v)
> -    int log2_ref_pic_gap_length;           // ue(v)
> -
> -    int max_num_tid0_ref_pics; // ue(v)
> -
> -    int sps_max_dec_pic_buffering_minus1; // ue(v)
> -    int long_term_ref_pic_flag;           // u(1)
> -    int rpl1_same_as_rpl0_flag;           // u(1)
> -    int num_ref_pic_list_in_sps[2];       // ue(v)
> -    struct RefPicListStruct rpls[2][EVC_MAX_NUM_RPLS];
> -
> -    int picture_cropping_flag;      // u(1)
> -    int picture_crop_left_offset;   // ue(v)
> -    int picture_crop_right_offset;  // ue(v)
> -    int picture_crop_top_offset;    // ue(v)
> -    int picture_crop_bottom_offset; // ue(v)
> -
> -    struct ChromaQpTable chroma_qp_table_struct;
> -
> -    int vui_parameters_present_flag;    // u(1)
> -
> -    struct VUIParameters vui_parameters;
> -
> -} EVCParserSPS;
> -
> -typedef struct EVCParserPPS {
> -    int pps_pic_parameter_set_id;                           // ue(v)
> -    int pps_seq_parameter_set_id;                           // ue(v)
> -    int num_ref_idx_default_active_minus1[2];               // ue(v)
> -    int additional_lt_poc_lsb_len;                          // ue(v)
> -    int rpl1_idx_present_flag;                              // u(1)
> -    int single_tile_in_pic_flag;                            // u(1)
> -    int num_tile_columns_minus1;                            // ue(v)
> -    int num_tile_rows_minus1;                               // ue(v)
> -    int uniform_tile_spacing_flag;                          // u(1)
> -    int tile_column_width_minus1[EVC_MAX_TILE_ROWS];        // ue(v)
> -    int tile_row_height_minus1[EVC_MAX_TILE_COLUMNS];          // ue(v)
> -    int loop_filter_across_tiles_enabled_flag;              // u(1)
> -    int tile_offset_len_minus1;                             // ue(v)
> -    int tile_id_len_minus1;                                 // ue(v)
> -    int explicit_tile_id_flag;                              // u(1)
> -    int tile_id_val[EVC_MAX_TILE_ROWS][EVC_MAX_TILE_COLUMNS];  // u(v)
> -    int pic_dra_enabled_flag;                               // u(1)
> -    int pic_dra_aps_id;                                     // u(5)
> -    int arbitrary_slice_present_flag;                       // u(1)
> -    int constrained_intra_pred_flag;                        // u(1)
> -    int cu_qp_delta_enabled_flag;                           // u(1)
> -    int log2_cu_qp_delta_area_minus6;                       // ue(v)
> -
> -} EVCParserPPS;
> +#include "evc_ps.h"
> 
>  // The sturcture reflects Slice Header RBSP(raw byte sequence payload)
layout
>  // @see ISO_IEC_23094-1 section 7.3.2.6
> @@ -265,10 +82,7 @@ typedef struct EVCParserPoc {
>  } EVCParserPoc;
> 
>  typedef struct EVCParserContext {
> -    //ParseContext pc;
> -    EVCParserSPS *sps[EVC_MAX_SPS_COUNT];
> -    EVCParserPPS *pps[EVC_MAX_PPS_COUNT];
> -
> +    EVCParamSets ps;
>      EVCParserPoc poc;
> 
>      int nuh_temporal_id;            // the value of TemporalId (shall be
the same for
> all VCL NAL units of an Access Unit)
> @@ -349,14 +163,6 @@ static inline uint32_t evc_read_nal_unit_length(const
> uint8_t *bits, int bits_si
>  // nuh_temporal_id specifies a temporal identifier for the NAL unit
>  int ff_evc_get_temporal_id(const uint8_t *bits, int bits_size, void
*logctx);
> 
> -// @see ISO_IEC_23094-1 (7.3.2.1 SPS RBSP syntax)
> -EVCParserSPS *ff_evc_parse_sps(EVCParserContext *ctx, const uint8_t *bs,
int
> bs_size);
> -
> -// @see ISO_IEC_23094-1 (7.3.2.2 SPS RBSP syntax)
> -EVCParserPPS *ff_evc_parse_pps(EVCParserContext *ctx, const uint8_t *bs,
int
> bs_size);
> -
>  int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int
> buf_size, void *logctx);
> 
> -void ff_evc_parse_free(EVCParserContext *ctx);
> -
>  #endif /* AVCODEC_EVC_PARSE_H */
> diff --git a/libavcodec/evc_parser.c b/libavcodec/evc_parser.c
> index c85b8f89e7..1fd8aac1dc 100644
> --- a/libavcodec/evc_parser.c
> +++ b/libavcodec/evc_parser.c
> @@ -202,7 +202,7 @@ static void evc_parser_close(AVCodecParserContext *s)
>  {
>      EVCParserContext *ctx = s->priv_data;
> 
> -    ff_evc_parse_free(ctx);
> +    ff_evc_ps_free(&ctx->ps);
>  }
> 
>  const AVCodecParser ff_evc_parser = {
> diff --git a/libavcodec/evc_ps.c b/libavcodec/evc_ps.c
> new file mode 100644
> index 0000000000..af74ba46b0
> --- /dev/null
> +++ b/libavcodec/evc_ps.c
> @@ -0,0 +1,381 @@
> +/*
> + * 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 "golomb.h"
> +#include "parser.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(GetBitContext *gb, RefPicListStruct *rpl)
> +{
> +    uint32_t delta_poc_st, strp_entry_sign_flag = 0;
> +    rpl->ref_pic_num = get_ue_golomb(gb);
> +    if (rpl->ref_pic_num > 0) {
> +        delta_poc_st = get_ue_golomb(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(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(gb);
> +    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(gb);
> +        hrd->cpb_size_value_minus1[SchedSelIdx] = get_ue_golomb(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)
> +{
> +    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(gb);
> +        vui->chroma_sample_loc_type_bottom_field = get_ue_golomb(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(gb, 32);
> +        vui->time_scale = get_bits(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)
> +        hrd_parameters(gb, &vui->hrd_parameters);
> +    vui->vcl_hrd_parameters_present_flag = get_bits(gb, 1);
> +    if (vui->vcl_hrd_parameters_present_flag)
> +        hrd_parameters(gb, &vui->hrd_parameters);
> +    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(gb);
> +        vui->max_bits_per_mb_denom = get_ue_golomb(gb);
> +        vui->log2_max_mv_length_horizontal = get_ue_golomb(gb);
> +        vui->log2_max_mv_length_vertical = get_ue_golomb(gb);
> +        vui->num_reorder_pics = get_ue_golomb(gb);
> +        vui->max_dec_pic_buffering = get_ue_golomb(gb);
> +    }
> +
> +    return 0;
> +}
> +
> +// @see ISO_IEC_23094-1 (7.3.2.1 SPS RBSP syntax)
> +EVCParserSPS *ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int
> bs_size)
> +{
> +    GetBitContext gb;
> +    EVCParserSPS *sps;
> +    int sps_seq_parameter_set_id;
> +
> +    if (init_get_bits8(&gb, bs, bs_size) < 0)
> +        return NULL;
> +
> +    sps_seq_parameter_set_id = get_ue_golomb(&gb);
> +
> +    if (sps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT)
> +        return NULL;
> +
> +    if(!ps->sps[sps_seq_parameter_set_id]) {
> +        if((ps->sps[sps_seq_parameter_set_id] =
av_malloc(sizeof(EVCParserSPS)))
> == NULL)
> +            return NULL;
> +    }
> +
> +    sps = ps->sps[sps_seq_parameter_set_id];
> +    memset(sps, 0, sizeof(*sps));
> +
> +    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(&gb);
> +
> +    sps->pic_width_in_luma_samples = get_ue_golomb(&gb);
> +    sps->pic_height_in_luma_samples = get_ue_golomb(&gb);
> +
> +    sps->bit_depth_luma_minus8 = get_ue_golomb(&gb);
> +    sps->bit_depth_chroma_minus8 = get_ue_golomb(&gb);
> +
> +    sps->sps_btt_flag = get_bits(&gb, 1);
> +    if (sps->sps_btt_flag) {
> +        sps->log2_ctu_size_minus5 = get_ue_golomb(&gb);
> +        sps->log2_min_cb_size_minus2 = get_ue_golomb(&gb);
> +        sps->log2_diff_ctu_max_14_cb_size = get_ue_golomb(&gb);
> +        sps->log2_diff_ctu_max_tt_cb_size = get_ue_golomb(&gb);
> +        sps->log2_diff_min_cb_min_tt_cb_size_minus2 = get_ue_golomb(&gb);
> +    }
> +
> +    sps->sps_suco_flag = get_bits(&gb, 1);
> +    if (sps->sps_suco_flag) {
> +        sps->log2_diff_ctu_size_max_suco_cb_size = get_ue_golomb(&gb);
> +        sps->log2_diff_max_suco_min_suco_cb_size = get_ue_golomb(&gb);
> +    }
> +
> +    sps->sps_admvp_flag = get_bits(&gb, 1);
> +    if (sps->sps_admvp_flag) {
> +        sps->sps_affine_flag = get_bits(&gb, 1);
> +        sps->sps_amvr_flag = get_bits(&gb, 1);
> +        sps->sps_dmvr_flag = get_bits(&gb, 1);
> +        sps->sps_mmvd_flag = get_bits(&gb, 1);
> +        sps->sps_hmvp_flag = get_bits(&gb, 1);
> +    }
> +
> +    sps->sps_eipd_flag =  get_bits(&gb, 1);
> +    if (sps->sps_eipd_flag) {
> +        sps->sps_ibc_flag = get_bits(&gb, 1);
> +        if (sps->sps_ibc_flag)
> +            sps->log2_max_ibc_cand_size_minus2 = get_ue_golomb(&gb);
> +    }
> +
> +    sps->sps_cm_init_flag = get_bits(&gb, 1);
> +    if (sps->sps_cm_init_flag)
> +        sps->sps_adcc_flag = get_bits(&gb, 1);
> +
> +    sps->sps_iqt_flag = get_bits(&gb, 1);
> +    if (sps->sps_iqt_flag)
> +        sps->sps_ats_flag = get_bits(&gb, 1);
> +
> +    sps->sps_addb_flag = get_bits(&gb, 1);
> +    sps->sps_alf_flag = get_bits(&gb, 1);
> +    sps->sps_htdf_flag = get_bits(&gb, 1);
> +    sps->sps_rpl_flag = get_bits(&gb, 1);
> +    sps->sps_pocs_flag = get_bits(&gb, 1);
> +    sps->sps_dquant_flag = get_bits(&gb, 1);
> +    sps->sps_dra_flag = get_bits(&gb, 1);
> +
> +    if (sps->sps_pocs_flag)
> +        sps->log2_max_pic_order_cnt_lsb_minus4 = get_ue_golomb(&gb);
> +
> +    if (!sps->sps_pocs_flag || !sps->sps_rpl_flag) {
> +        sps->log2_sub_gop_length = get_ue_golomb(&gb);
> +        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(&gb);
> +    else {
> +        sps->sps_max_dec_pic_buffering_minus1 = get_ue_golomb(&gb);
> +        sps->long_term_ref_pic_flag = get_bits(&gb, 1);
> +        sps->rpl1_same_as_rpl0_flag = get_bits(&gb, 1);
> +        sps->num_ref_pic_list_in_sps[0] = get_ue_golomb(&gb);
> +
> +        for (int i = 0; i < sps->num_ref_pic_list_in_sps[0]; ++i)
> +            ref_pic_list_struct(&gb, &sps->rpls[0][i]);
> +
> +        if (!sps->rpl1_same_as_rpl0_flag) {
> +            sps->num_ref_pic_list_in_sps[1] = get_ue_golomb(&gb);
> +            for (int i = 0; i < sps->num_ref_pic_list_in_sps[1]; ++i)
> +                ref_pic_list_struct(&gb, &sps->rpls[1][i]);
> +        }
> +    }
> +
> +    sps->picture_cropping_flag = get_bits(&gb, 1);
> +
> +    if (sps->picture_cropping_flag) {
> +        sps->picture_crop_left_offset = get_ue_golomb(&gb);
> +        sps->picture_crop_right_offset = get_ue_golomb(&gb);
> +        sps->picture_crop_top_offset = get_ue_golomb(&gb);
> +        sps->picture_crop_bottom_offset = get_ue_golomb(&gb);
> +    }
> +
> +    if (sps->chroma_format_idc != 0) {
> +        sps->chroma_qp_table_struct.chroma_qp_table_present_flag =
> get_bits(&gb, 1);
> +
> +        if (sps->chroma_qp_table_struct.chroma_qp_table_present_flag) {
> +            sps->chroma_qp_table_struct.same_qp_table_for_chroma =
> get_bits(&gb, 1);
> +            sps->chroma_qp_table_struct.global_offset_flag =
get_bits(&gb, 1);
> +            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);;
> +                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(&gb);
> +                }
> +            }
> +        }
> +    }
> +
> +    sps->vui_parameters_present_flag = get_bits(&gb, 1);
> +    if (sps->vui_parameters_present_flag)
> +        vui_parameters(&gb, &(sps->vui_parameters));
> +
> +    // @note
> +    // If necessary, add the missing fields to the EVCParserSPS structure
> +    // and then extend parser implementation
> +
> +    return sps;
> +}
> +
> +// @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
> +//
> +EVCParserPPS *ff_evc_parse_pps(EVCParamSets *ps, const uint8_t *bs, int
> bs_size)
> +{
> +    GetBitContext gb;
> +    EVCParserPPS *pps;
> +
> +    int pps_pic_parameter_set_id;
> +
> +    if (init_get_bits8(&gb, bs, bs_size) < 0)
> +        return NULL;
> +
> +    pps_pic_parameter_set_id = get_ue_golomb(&gb);
> +    if (pps_pic_parameter_set_id > EVC_MAX_PPS_COUNT)
> +        return NULL;
> +
> +    if(!ps->pps[pps_pic_parameter_set_id]) {
> +        if ((ps->pps[pps_pic_parameter_set_id] =
av_malloc(sizeof(EVCParserPPS)))
> == NULL)
> +            return NULL;
> +    }
> +
> +    pps = ps->pps[pps_pic_parameter_set_id];
> +    memset(pps, 0, sizeof(*pps));
> +
> +    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) {
> +        av_freep(&ps->pps[pps_pic_parameter_set_id]);
> +        return NULL;
> +    }
> +
> +    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_bits(&gb, 1);
> +    pps->single_tile_in_pic_flag = get_bits(&gb, 1);
> +
> +    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);
> +        pps->uniform_tile_spacing_flag = get_bits(&gb, 1);
> +
> +        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_bits(&gb, 1);
> +        pps->tile_offset_len_minus1 = get_ue_golomb(&gb);
> +    }
> +
> +    pps->tile_id_len_minus1 = get_ue_golomb(&gb);
> +    pps->explicit_tile_id_flag = get_bits(&gb, 1);
> +
> +    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_bits(&gb, 1);
> +
> +    if (pps->pic_dra_enabled_flag)
> +        pps->pic_dra_aps_id = get_bits(&gb, 5);
> +
> +    pps->arbitrary_slice_present_flag = get_bits(&gb, 1);
> +    pps->constrained_intra_pred_flag = get_bits(&gb, 1);
> +    pps->cu_qp_delta_enabled_flag = get_bits(&gb, 1);
> +
> +    if (pps->cu_qp_delta_enabled_flag)
> +        pps->log2_cu_qp_delta_area_minus6 = get_ue_golomb(&gb);
> +
> +    return pps;
> +}
> +
> +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]);
> +}
> diff --git a/libavcodec/evc_ps.h b/libavcodec/evc_ps.h
> new file mode 100644
> index 0000000000..989336079f
> --- /dev/null
> +++ b/libavcodec/evc_ps.h
> @@ -0,0 +1,228 @@
> +/*
> + * 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
> + */
> +
> +/**
> + * @file
> + * EVC decoder/parser shared code
> + */
> +
> +#ifndef AVCODEC_EVC_PS_H
> +#define AVCODEC_EVC_PS_H
> +
> +#include <stdint.h>
> +
> +#include "evc.h"
> +
> +#define EVC_MAX_QP_TABLE_SIZE   58
> +#define NUM_CPB                 32
> +
> +// rpl structure
> +typedef struct RefPicListStruct {
> +    int poc;
> +    int tid;
> +    int ref_pic_num;
> +    int ref_pic_active_num;
> +    int ref_pics[EVC_MAX_NUM_REF_PICS];
> +    char pic_type;
> +
> +} RefPicListStruct;
> +
> +// chromaQP table structure to be signalled in SPS
> +typedef struct ChromaQpTable {
> +    int chroma_qp_table_present_flag;       // u(1)
> +    int same_qp_table_for_chroma;           // u(1)
> +    int global_offset_flag;                 // u(1)
> +    int num_points_in_qp_table_minus1[2];   // ue(v)
> +    int delta_qp_in_val_minus1[2][EVC_MAX_QP_TABLE_SIZE];   // u(6)
> +    int delta_qp_out_val[2][EVC_MAX_QP_TABLE_SIZE];         // se(v)
> +} ChromaQpTable;
> +
> +// Hypothetical Reference Decoder (HRD) parameters, part of VUI
> +typedef struct HRDParameters {
> +    int cpb_cnt_minus1;                             // ue(v)
> +    int bit_rate_scale;                             // u(4)
> +    int cpb_size_scale;                             // u(4)
> +    int bit_rate_value_minus1[NUM_CPB];             // ue(v)
> +    int cpb_size_value_minus1[NUM_CPB];             // ue(v)
> +    int cbr_flag[NUM_CPB];                          // u(1)
> +    int initial_cpb_removal_delay_length_minus1;    // u(5)
> +    int cpb_removal_delay_length_minus1;            // u(5)
> +    int dpb_output_delay_length_minus1;             // u(5)
> +    int time_offset_length;                         // u(5)
> +} HRDParameters;
> +
> +// video usability information (VUI) part of SPS
> +typedef struct VUIParameters {
> +    int aspect_ratio_info_present_flag;             // u(1)
> +    int aspect_ratio_idc;                           // u(8)
> +    int sar_width;                                  // u(16)
> +    int sar_height;                                 // u(16)
> +    int overscan_info_present_flag;                 // u(1)
> +    int overscan_appropriate_flag;                  // u(1)
> +    int video_signal_type_present_flag;             // u(1)
> +    int video_format;                               // u(3)
> +    int video_full_range_flag;                      // u(1)
> +    int colour_description_present_flag;            // u(1)
> +    int colour_primaries;                           // u(8)
> +    int transfer_characteristics;                   // u(8)
> +    int matrix_coefficients;                        // u(8)
> +    int chroma_loc_info_present_flag;               // u(1)
> +    int chroma_sample_loc_type_top_field;           // ue(v)
> +    int chroma_sample_loc_type_bottom_field;        // ue(v)
> +    int neutral_chroma_indication_flag;             // u(1)
> +    int field_seq_flag;                             // u(1)
> +    int timing_info_present_flag;                   // u(1)
> +    int num_units_in_tick;                          // u(32)
> +    int time_scale;                                 // u(32)
> +    int fixed_pic_rate_flag;                        // u(1)
> +    int nal_hrd_parameters_present_flag;            // u(1)
> +    int vcl_hrd_parameters_present_flag;            // u(1)
> +    int low_delay_hrd_flag;                         // u(1)
> +    int pic_struct_present_flag;                    // u(1)
> +    int bitstream_restriction_flag;                 // u(1)
> +    int motion_vectors_over_pic_boundaries_flag;    // u(1)
> +    int max_bytes_per_pic_denom;                    // ue(v)
> +    int max_bits_per_mb_denom;                      // ue(v)
> +    int log2_max_mv_length_horizontal;              // ue(v)
> +    int log2_max_mv_length_vertical;                // ue(v)
> +    int num_reorder_pics;                           // ue(v)
> +    int max_dec_pic_buffering;                      // ue(v)
> +
> +    HRDParameters hrd_parameters;
> +} VUIParameters;
> +
> +// The sturcture reflects SPS RBSP(raw byte sequence payload) layout
> +// @see ISO_IEC_23094-1 section 7.3.2.1
> +//
> +// The following descriptors specify the parsing process of each element
> +// u(n) - unsigned integer using n bits
> +// ue(v) - unsigned integer 0-th order Exp_Golomb-coded syntax element
with
> the left bit first
> +typedef struct EVCParserSPS {
> +    int sps_seq_parameter_set_id;   // ue(v)
> +    int profile_idc;                // u(8)
> +    int level_idc;                  // u(8)
> +    int toolset_idc_h;              // u(32)
> +    int toolset_idc_l;              // u(32)
> +    int chroma_format_idc;          // ue(v)
> +    int pic_width_in_luma_samples;  // ue(v)
> +    int pic_height_in_luma_samples; // ue(v)
> +    int bit_depth_luma_minus8;      // ue(v)
> +    int bit_depth_chroma_minus8;    // ue(v)
> +
> +    int sps_btt_flag;                           // u(1)
> +    int log2_ctu_size_minus5;                   // ue(v)
> +    int log2_min_cb_size_minus2;                // ue(v)
> +    int log2_diff_ctu_max_14_cb_size;           // ue(v)
> +    int log2_diff_ctu_max_tt_cb_size;           // ue(v)
> +    int log2_diff_min_cb_min_tt_cb_size_minus2; // ue(v)
> +
> +    int sps_suco_flag;                       // u(1)
> +    int log2_diff_ctu_size_max_suco_cb_size; // ue(v)
> +    int log2_diff_max_suco_min_suco_cb_size; // ue(v)
> +
> +    int sps_admvp_flag;     // u(1)
> +    int sps_affine_flag;    // u(1)
> +    int sps_amvr_flag;      // u(1)
> +    int sps_dmvr_flag;      // u(1)
> +    int sps_mmvd_flag;      // u(1)
> +    int sps_hmvp_flag;      // u(1)
> +
> +    int sps_eipd_flag;                 // u(1)
> +    int sps_ibc_flag;                  // u(1)
> +    int log2_max_ibc_cand_size_minus2; // ue(v)
> +
> +    int sps_cm_init_flag; // u(1)
> +    int sps_adcc_flag;    // u(1)
> +
> +    int sps_iqt_flag; // u(1)
> +    int sps_ats_flag; // u(1)
> +
> +    int sps_addb_flag;   // u(1)
> +    int sps_alf_flag;    // u(1)
> +    int sps_htdf_flag;   // u(1)
> +    int sps_rpl_flag;    // u(1)
> +    int sps_pocs_flag;   // u(1)
> +    int sps_dquant_flag; // u(1)
> +    int sps_dra_flag;    // u(1)
> +
> +    int log2_max_pic_order_cnt_lsb_minus4; // ue(v)
> +    int log2_sub_gop_length;               // ue(v)
> +    int log2_ref_pic_gap_length;           // ue(v)
> +
> +    int max_num_tid0_ref_pics; // ue(v)
> +
> +    int sps_max_dec_pic_buffering_minus1; // ue(v)
> +    int long_term_ref_pic_flag;           // u(1)
> +    int rpl1_same_as_rpl0_flag;           // u(1)
> +    int num_ref_pic_list_in_sps[2];       // ue(v)
> +    struct RefPicListStruct rpls[2][EVC_MAX_NUM_RPLS];
> +
> +    int picture_cropping_flag;      // u(1)
> +    int picture_crop_left_offset;   // ue(v)
> +    int picture_crop_right_offset;  // ue(v)
> +    int picture_crop_top_offset;    // ue(v)
> +    int picture_crop_bottom_offset; // ue(v)
> +
> +    struct ChromaQpTable chroma_qp_table_struct;
> +
> +    int vui_parameters_present_flag;    // u(1)
> +
> +    struct VUIParameters vui_parameters;
> +
> +} EVCParserSPS;
> +
> +typedef struct EVCParserPPS {
> +    int pps_pic_parameter_set_id;                           // ue(v)
> +    int pps_seq_parameter_set_id;                           // ue(v)
> +    int num_ref_idx_default_active_minus1[2];               // ue(v)
> +    int additional_lt_poc_lsb_len;                          // ue(v)
> +    int rpl1_idx_present_flag;                              // u(1)
> +    int single_tile_in_pic_flag;                            // u(1)
> +    int num_tile_columns_minus1;                            // ue(v)
> +    int num_tile_rows_minus1;                               // ue(v)
> +    int uniform_tile_spacing_flag;                          // u(1)
> +    int tile_column_width_minus1[EVC_MAX_TILE_ROWS];        // ue(v)
> +    int tile_row_height_minus1[EVC_MAX_TILE_COLUMNS];          // ue(v)
> +    int loop_filter_across_tiles_enabled_flag;              // u(1)
> +    int tile_offset_len_minus1;                             // ue(v)
> +    int tile_id_len_minus1;                                 // ue(v)
> +    int explicit_tile_id_flag;                              // u(1)
> +    int tile_id_val[EVC_MAX_TILE_ROWS][EVC_MAX_TILE_COLUMNS];  // u(v)
> +    int pic_dra_enabled_flag;                               // u(1)
> +    int pic_dra_aps_id;                                     // u(5)
> +    int arbitrary_slice_present_flag;                       // u(1)
> +    int constrained_intra_pred_flag;                        // u(1)
> +    int cu_qp_delta_enabled_flag;                           // u(1)
> +    int log2_cu_qp_delta_area_minus6;                       // ue(v)
> +
> +} EVCParserPPS;
> +
> +typedef struct EVCParamSets {
> +    EVCParserSPS *sps[EVC_MAX_SPS_COUNT];
> +    EVCParserPPS *pps[EVC_MAX_PPS_COUNT];
> +} EVCParamSets;
> +
> +// @see ISO_IEC_23094-1 (7.3.2.1 SPS RBSP syntax)
> +EVCParserSPS *ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int
> bs_size);
> +
> +// @see ISO_IEC_23094-1 (7.3.2.2 SPS RBSP syntax)
> +EVCParserPPS *ff_evc_parse_pps(EVCParamSets *ps, const uint8_t *bs, int
> bs_size);
> +
> +void ff_evc_ps_free(EVCParamSets *ps);
> +
> +#endif /* AVCODEC_EVC_PS_H */
> --
> 2.41.0
> 
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://protect2.fireeye.com/v1/url?k=8708fc5b-d894d571-87097714-
> 000babe598f7-a29b47b5c273342b&q=1&e=f39a2fa5-9fa0-43a4-8767-
> 4e4532bab712&u=https%3A%2F%2Fffmpeg.org%2Fmailman%2Flistinfo%2Fffmp
> eg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
James Almer June 20, 2023, 11:37 a.m. UTC | #2
On 6/20/2023 4:37 AM, Dawid Kozinski/Multimedia (PLT) /SRPOL/Staff 
Engineer/Samsung Electronics wrote:
> Why have you split off the parameter set parsing into its own file? Just
> asking what's the reason.
I copied the design from h264. Smaller source files are better than 
monolith ones. And an eventual native decoder will benefit from this 
being already in place.
diff mbox series

Patch

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 0ce8fe5b9c..723bfa25c7 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -84,7 +84,7 @@  OBJS-$(CONFIG_DCT)                     += dct.o dct32_fixed.o dct32_float.o
 OBJS-$(CONFIG_DEFLATE_WRAPPER)         += zlib_wrapper.o
 OBJS-$(CONFIG_DOVI_RPU)                += dovi_rpu.o
 OBJS-$(CONFIG_ERROR_RESILIENCE)        += error_resilience.o
-OBJS-$(CONFIG_EVCPARSE)                += evc_parse.o
+OBJS-$(CONFIG_EVCPARSE)                += evc_parse.o evc_ps.o
 OBJS-$(CONFIG_EXIF)                    += exif.o tiff_common.o
 OBJS-$(CONFIG_FAANDCT)                 += faandct.o
 OBJS-$(CONFIG_FAANIDCT)                += faanidct.o
diff --git a/libavcodec/evc_frame_merge_bsf.c b/libavcodec/evc_frame_merge_bsf.c
index 540bb63631..f497780afb 100644
--- a/libavcodec/evc_frame_merge_bsf.c
+++ b/libavcodec/evc_frame_merge_bsf.c
@@ -58,7 +58,7 @@  static void evc_frame_merge_flush(AVBSFContext *bsf)
 {
     EVCFMergeContext *ctx = bsf->priv_data;
 
-    ff_evc_parse_free(&ctx->parser_ctx);
+    ff_evc_ps_free(&ctx->parser_ctx.ps);
     av_packet_unref(ctx->in);
     ctx->au_buffer.data_size = 0;
 }
@@ -147,7 +147,7 @@  static void evc_frame_merge_close(AVBSFContext *bsf)
     EVCFMergeContext *ctx = bsf->priv_data;
 
     av_packet_free(&ctx->in);
-    ff_evc_parse_free(&ctx->parser_ctx);
+    ff_evc_ps_free(&ctx->parser_ctx.ps);
 
     ctx->au_buffer.capacity = 0;
     av_freep(&ctx->au_buffer.data);
diff --git a/libavcodec/evc_parse.c b/libavcodec/evc_parse.c
index 44be5c5291..a8e6356b96 100644
--- a/libavcodec/evc_parse.c
+++ b/libavcodec/evc_parse.c
@@ -21,8 +21,6 @@ 
 #include "evc.h"
 #include "evc_parse.h"
 
-#define EXTENDED_SAR            255
-
 #define NUM_CHROMA_FORMATS      4   // @see ISO_IEC_23094-1 section 6.2 table 2
 
 static const enum AVPixelFormat pix_fmts_8bit[NUM_CHROMA_FORMATS] = {
@@ -71,355 +69,6 @@  int ff_evc_get_temporal_id(const uint8_t *bits, int bits_size, void *logctx)
     return temporal_id;
 }
 
-// @see ISO_IEC_23094-1 (7.3.7 Reference picture list structure syntax)
-static int ref_pic_list_struct(GetBitContext *gb, RefPicListStruct *rpl)
-{
-    uint32_t delta_poc_st, strp_entry_sign_flag = 0;
-    rpl->ref_pic_num = get_ue_golomb(gb);
-    if (rpl->ref_pic_num > 0) {
-        delta_poc_st = get_ue_golomb(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(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(gb);
-    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(gb);
-        hrd->cpb_size_value_minus1[SchedSelIdx] = get_ue_golomb(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)
-{
-    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(gb);
-        vui->chroma_sample_loc_type_bottom_field = get_ue_golomb(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(gb, 32);
-        vui->time_scale = get_bits(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)
-        hrd_parameters(gb, &vui->hrd_parameters);
-    vui->vcl_hrd_parameters_present_flag = get_bits(gb, 1);
-    if (vui->vcl_hrd_parameters_present_flag)
-        hrd_parameters(gb, &vui->hrd_parameters);
-    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(gb);
-        vui->max_bits_per_mb_denom = get_ue_golomb(gb);
-        vui->log2_max_mv_length_horizontal = get_ue_golomb(gb);
-        vui->log2_max_mv_length_vertical = get_ue_golomb(gb);
-        vui->num_reorder_pics = get_ue_golomb(gb);
-        vui->max_dec_pic_buffering = get_ue_golomb(gb);
-    }
-
-    return 0;
-}
-
-// @see ISO_IEC_23094-1 (7.3.2.1 SPS RBSP syntax)
-EVCParserSPS *ff_evc_parse_sps(EVCParserContext *ctx, const uint8_t *bs, int bs_size)
-{
-    GetBitContext gb;
-    EVCParserSPS *sps;
-    int sps_seq_parameter_set_id;
-
-    if (init_get_bits8(&gb, bs, bs_size) < 0)
-        return NULL;
-
-    sps_seq_parameter_set_id = get_ue_golomb(&gb);
-
-    if (sps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT)
-        return NULL;
-
-    if(!ctx->sps[sps_seq_parameter_set_id]) {
-        if((ctx->sps[sps_seq_parameter_set_id] = av_malloc(sizeof(EVCParserSPS))) == NULL)
-            return NULL;
-    }
-
-    sps = ctx->sps[sps_seq_parameter_set_id];
-    memset(sps, 0, sizeof(*sps));
-
-    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(&gb);
-
-    sps->pic_width_in_luma_samples = get_ue_golomb(&gb);
-    sps->pic_height_in_luma_samples = get_ue_golomb(&gb);
-
-    sps->bit_depth_luma_minus8 = get_ue_golomb(&gb);
-    sps->bit_depth_chroma_minus8 = get_ue_golomb(&gb);
-
-    sps->sps_btt_flag = get_bits(&gb, 1);
-    if (sps->sps_btt_flag) {
-        sps->log2_ctu_size_minus5 = get_ue_golomb(&gb);
-        sps->log2_min_cb_size_minus2 = get_ue_golomb(&gb);
-        sps->log2_diff_ctu_max_14_cb_size = get_ue_golomb(&gb);
-        sps->log2_diff_ctu_max_tt_cb_size = get_ue_golomb(&gb);
-        sps->log2_diff_min_cb_min_tt_cb_size_minus2 = get_ue_golomb(&gb);
-    }
-
-    sps->sps_suco_flag = get_bits(&gb, 1);
-    if (sps->sps_suco_flag) {
-        sps->log2_diff_ctu_size_max_suco_cb_size = get_ue_golomb(&gb);
-        sps->log2_diff_max_suco_min_suco_cb_size = get_ue_golomb(&gb);
-    }
-
-    sps->sps_admvp_flag = get_bits(&gb, 1);
-    if (sps->sps_admvp_flag) {
-        sps->sps_affine_flag = get_bits(&gb, 1);
-        sps->sps_amvr_flag = get_bits(&gb, 1);
-        sps->sps_dmvr_flag = get_bits(&gb, 1);
-        sps->sps_mmvd_flag = get_bits(&gb, 1);
-        sps->sps_hmvp_flag = get_bits(&gb, 1);
-    }
-
-    sps->sps_eipd_flag =  get_bits(&gb, 1);
-    if (sps->sps_eipd_flag) {
-        sps->sps_ibc_flag = get_bits(&gb, 1);
-        if (sps->sps_ibc_flag)
-            sps->log2_max_ibc_cand_size_minus2 = get_ue_golomb(&gb);
-    }
-
-    sps->sps_cm_init_flag = get_bits(&gb, 1);
-    if (sps->sps_cm_init_flag)
-        sps->sps_adcc_flag = get_bits(&gb, 1);
-
-    sps->sps_iqt_flag = get_bits(&gb, 1);
-    if (sps->sps_iqt_flag)
-        sps->sps_ats_flag = get_bits(&gb, 1);
-
-    sps->sps_addb_flag = get_bits(&gb, 1);
-    sps->sps_alf_flag = get_bits(&gb, 1);
-    sps->sps_htdf_flag = get_bits(&gb, 1);
-    sps->sps_rpl_flag = get_bits(&gb, 1);
-    sps->sps_pocs_flag = get_bits(&gb, 1);
-    sps->sps_dquant_flag = get_bits(&gb, 1);
-    sps->sps_dra_flag = get_bits(&gb, 1);
-
-    if (sps->sps_pocs_flag)
-        sps->log2_max_pic_order_cnt_lsb_minus4 = get_ue_golomb(&gb);
-
-    if (!sps->sps_pocs_flag || !sps->sps_rpl_flag) {
-        sps->log2_sub_gop_length = get_ue_golomb(&gb);
-        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(&gb);
-    else {
-        sps->sps_max_dec_pic_buffering_minus1 = get_ue_golomb(&gb);
-        sps->long_term_ref_pic_flag = get_bits(&gb, 1);
-        sps->rpl1_same_as_rpl0_flag = get_bits(&gb, 1);
-        sps->num_ref_pic_list_in_sps[0] = get_ue_golomb(&gb);
-
-        for (int i = 0; i < sps->num_ref_pic_list_in_sps[0]; ++i)
-            ref_pic_list_struct(&gb, &sps->rpls[0][i]);
-
-        if (!sps->rpl1_same_as_rpl0_flag) {
-            sps->num_ref_pic_list_in_sps[1] = get_ue_golomb(&gb);
-            for (int i = 0; i < sps->num_ref_pic_list_in_sps[1]; ++i)
-                ref_pic_list_struct(&gb, &sps->rpls[1][i]);
-        }
-    }
-
-    sps->picture_cropping_flag = get_bits(&gb, 1);
-
-    if (sps->picture_cropping_flag) {
-        sps->picture_crop_left_offset = get_ue_golomb(&gb);
-        sps->picture_crop_right_offset = get_ue_golomb(&gb);
-        sps->picture_crop_top_offset = get_ue_golomb(&gb);
-        sps->picture_crop_bottom_offset = get_ue_golomb(&gb);
-    }
-
-    if (sps->chroma_format_idc != 0) {
-        sps->chroma_qp_table_struct.chroma_qp_table_present_flag = get_bits(&gb, 1);
-
-        if (sps->chroma_qp_table_struct.chroma_qp_table_present_flag) {
-            sps->chroma_qp_table_struct.same_qp_table_for_chroma = get_bits(&gb, 1);
-            sps->chroma_qp_table_struct.global_offset_flag = get_bits(&gb, 1);
-            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);;
-                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(&gb);
-                }
-            }
-        }
-    }
-
-    sps->vui_parameters_present_flag = get_bits(&gb, 1);
-    if (sps->vui_parameters_present_flag)
-        vui_parameters(&gb, &(sps->vui_parameters));
-
-    // @note
-    // If necessary, add the missing fields to the EVCParserSPS structure
-    // and then extend parser implementation
-
-    return sps;
-}
-
-// @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
-//
-EVCParserPPS *ff_evc_parse_pps(EVCParserContext *ctx, const uint8_t *bs, int bs_size)
-{
-    GetBitContext gb;
-    EVCParserPPS *pps;
-
-    int pps_pic_parameter_set_id;
-
-    if (init_get_bits8(&gb, bs, bs_size) < 0)
-        return NULL;
-
-    pps_pic_parameter_set_id = get_ue_golomb(&gb);
-    if (pps_pic_parameter_set_id > EVC_MAX_PPS_COUNT)
-        return NULL;
-
-    if(!ctx->pps[pps_pic_parameter_set_id]) {
-        if ((ctx->pps[pps_pic_parameter_set_id] = av_malloc(sizeof(EVCParserPPS))) == NULL)
-            return NULL;
-    }
-
-    pps = ctx->pps[pps_pic_parameter_set_id];
-    memset(pps, 0, sizeof(*pps));
-
-    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) {
-        av_freep(&ctx->pps[pps_pic_parameter_set_id]);
-        return NULL;
-    }
-
-    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_bits(&gb, 1);
-    pps->single_tile_in_pic_flag = get_bits(&gb, 1);
-
-    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);
-        pps->uniform_tile_spacing_flag = get_bits(&gb, 1);
-
-        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_bits(&gb, 1);
-        pps->tile_offset_len_minus1 = get_ue_golomb(&gb);
-    }
-
-    pps->tile_id_len_minus1 = get_ue_golomb(&gb);
-    pps->explicit_tile_id_flag = get_bits(&gb, 1);
-
-    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_bits(&gb, 1);
-
-    if (pps->pic_dra_enabled_flag)
-        pps->pic_dra_aps_id = get_bits(&gb, 5);
-
-    pps->arbitrary_slice_present_flag = get_bits(&gb, 1);
-    pps->constrained_intra_pred_flag = get_bits(&gb, 1);
-    pps->cu_qp_delta_enabled_flag = get_bits(&gb, 1);
-
-    if (pps->cu_qp_delta_enabled_flag)
-        pps->log2_cu_qp_delta_area_minus6 = get_ue_golomb(&gb);
-
-    return pps;
-}
-
 // @see ISO_IEC_23094-1 (7.3.2.6 Slice layer RBSP syntax)
 static int evc_parse_slice_header(EVCParserContext *ctx, EVCParserSliceHeader *sh, const uint8_t *bs, int bs_size)
 {
@@ -439,11 +88,11 @@  static int evc_parse_slice_header(EVCParserContext *ctx, EVCParserSliceHeader *s
     if (slice_pic_parameter_set_id < 0 || slice_pic_parameter_set_id >= EVC_MAX_PPS_COUNT)
         return AVERROR_INVALIDDATA;
 
-    pps = ctx->pps[slice_pic_parameter_set_id];
+    pps = ctx->ps.pps[slice_pic_parameter_set_id];
     if(!pps)
         return AVERROR_INVALIDDATA;
 
-    sps = ctx->sps[pps->pps_seq_parameter_set_id];
+    sps = ctx->ps.sps[pps->pps_seq_parameter_set_id];
     if(!sps)
         return AVERROR_INVALIDDATA;
 
@@ -579,7 +228,7 @@  int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz
         int SubGopLength;
         int bit_depth;
 
-        sps = ff_evc_parse_sps(ctx, data, nalu_size);
+        sps = ff_evc_parse_sps(&ctx->ps, data, nalu_size);
         if (!sps) {
             av_log(logctx, AV_LOG_ERROR, "SPS parsing error\n");
             return AVERROR_INVALIDDATA;
@@ -642,7 +291,7 @@  int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz
     case EVC_PPS_NUT: {
         EVCParserPPS *pps;
 
-        pps = ff_evc_parse_pps(ctx, data, nalu_size);
+        pps = ff_evc_parse_pps(&ctx->ps, data, nalu_size);
         if (!pps) {
             av_log(logctx, AV_LOG_ERROR, "PPS parsing error\n");
             return AVERROR_INVALIDDATA;
@@ -688,8 +337,8 @@  int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz
 
         // POC (picture order count of the current picture) derivation
         // @see ISO/IEC 23094-1:2020(E) 8.3.1 Decoding process for picture order count
-        pps = ctx->pps[sh.slice_pic_parameter_set_id];
-        sps = ctx->sps[pps->pps_seq_parameter_set_id];
+        pps = ctx->ps.pps[sh.slice_pic_parameter_set_id];
+        sps = ctx->ps.sps[pps->pps_seq_parameter_set_id];
         av_assert0(sps && pps);
 
         if (sps->sps_pocs_flag) {
@@ -764,11 +413,3 @@  int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_siz
 
     return 0;
 }
-
-void ff_evc_parse_free(EVCParserContext *ctx) {
-    for (int i = 0; i < EVC_MAX_SPS_COUNT; i++)
-        av_freep(&ctx->sps[i]);
-
-    for (int i = 0; i < EVC_MAX_PPS_COUNT; i++)
-        av_freep(&ctx->pps[i]);
-}
diff --git a/libavcodec/evc_parse.h b/libavcodec/evc_parse.h
index ee4b6c5708..b5462f5711 100644
--- a/libavcodec/evc_parse.h
+++ b/libavcodec/evc_parse.h
@@ -30,190 +30,7 @@ 
 #include "libavutil/log.h"
 #include "libavutil/rational.h"
 #include "evc.h"
-
-#define EVC_MAX_QP_TABLE_SIZE   58
-#define NUM_CPB                 32
-
-// rpl structure
-typedef struct RefPicListStruct {
-    int poc;
-    int tid;
-    int ref_pic_num;
-    int ref_pic_active_num;
-    int ref_pics[EVC_MAX_NUM_REF_PICS];
-    char pic_type;
-
-} RefPicListStruct;
-
-// chromaQP table structure to be signalled in SPS
-typedef struct ChromaQpTable {
-    int chroma_qp_table_present_flag;       // u(1)
-    int same_qp_table_for_chroma;           // u(1)
-    int global_offset_flag;                 // u(1)
-    int num_points_in_qp_table_minus1[2];   // ue(v)
-    int delta_qp_in_val_minus1[2][EVC_MAX_QP_TABLE_SIZE];   // u(6)
-    int delta_qp_out_val[2][EVC_MAX_QP_TABLE_SIZE];         // se(v)
-} ChromaQpTable;
-
-// Hypothetical Reference Decoder (HRD) parameters, part of VUI
-typedef struct HRDParameters {
-    int cpb_cnt_minus1;                             // ue(v)
-    int bit_rate_scale;                             // u(4)
-    int cpb_size_scale;                             // u(4)
-    int bit_rate_value_minus1[NUM_CPB];             // ue(v)
-    int cpb_size_value_minus1[NUM_CPB];             // ue(v)
-    int cbr_flag[NUM_CPB];                          // u(1)
-    int initial_cpb_removal_delay_length_minus1;    // u(5)
-    int cpb_removal_delay_length_minus1;            // u(5)
-    int dpb_output_delay_length_minus1;             // u(5)
-    int time_offset_length;                         // u(5)
-} HRDParameters;
-
-// video usability information (VUI) part of SPS
-typedef struct VUIParameters {
-    int aspect_ratio_info_present_flag;             // u(1)
-    int aspect_ratio_idc;                           // u(8)
-    int sar_width;                                  // u(16)
-    int sar_height;                                 // u(16)
-    int overscan_info_present_flag;                 // u(1)
-    int overscan_appropriate_flag;                  // u(1)
-    int video_signal_type_present_flag;             // u(1)
-    int video_format;                               // u(3)
-    int video_full_range_flag;                      // u(1)
-    int colour_description_present_flag;            // u(1)
-    int colour_primaries;                           // u(8)
-    int transfer_characteristics;                   // u(8)
-    int matrix_coefficients;                        // u(8)
-    int chroma_loc_info_present_flag;               // u(1)
-    int chroma_sample_loc_type_top_field;           // ue(v)
-    int chroma_sample_loc_type_bottom_field;        // ue(v)
-    int neutral_chroma_indication_flag;             // u(1)
-    int field_seq_flag;                             // u(1)
-    int timing_info_present_flag;                   // u(1)
-    int num_units_in_tick;                          // u(32)
-    int time_scale;                                 // u(32)
-    int fixed_pic_rate_flag;                        // u(1)
-    int nal_hrd_parameters_present_flag;            // u(1)
-    int vcl_hrd_parameters_present_flag;            // u(1)
-    int low_delay_hrd_flag;                         // u(1)
-    int pic_struct_present_flag;                    // u(1)
-    int bitstream_restriction_flag;                 // u(1)
-    int motion_vectors_over_pic_boundaries_flag;    // u(1)
-    int max_bytes_per_pic_denom;                    // ue(v)
-    int max_bits_per_mb_denom;                      // ue(v)
-    int log2_max_mv_length_horizontal;              // ue(v)
-    int log2_max_mv_length_vertical;                // ue(v)
-    int num_reorder_pics;                           // ue(v)
-    int max_dec_pic_buffering;                      // ue(v)
-
-    HRDParameters hrd_parameters;
-} VUIParameters;
-
-// The sturcture reflects SPS RBSP(raw byte sequence payload) layout
-// @see ISO_IEC_23094-1 section 7.3.2.1
-//
-// The following descriptors specify the parsing process of each element
-// u(n) - unsigned integer using n bits
-// ue(v) - unsigned integer 0-th order Exp_Golomb-coded syntax element with the left bit first
-typedef struct EVCParserSPS {
-    int sps_seq_parameter_set_id;   // ue(v)
-    int profile_idc;                // u(8)
-    int level_idc;                  // u(8)
-    int toolset_idc_h;              // u(32)
-    int toolset_idc_l;              // u(32)
-    int chroma_format_idc;          // ue(v)
-    int pic_width_in_luma_samples;  // ue(v)
-    int pic_height_in_luma_samples; // ue(v)
-    int bit_depth_luma_minus8;      // ue(v)
-    int bit_depth_chroma_minus8;    // ue(v)
-
-    int sps_btt_flag;                           // u(1)
-    int log2_ctu_size_minus5;                   // ue(v)
-    int log2_min_cb_size_minus2;                // ue(v)
-    int log2_diff_ctu_max_14_cb_size;           // ue(v)
-    int log2_diff_ctu_max_tt_cb_size;           // ue(v)
-    int log2_diff_min_cb_min_tt_cb_size_minus2; // ue(v)
-
-    int sps_suco_flag;                       // u(1)
-    int log2_diff_ctu_size_max_suco_cb_size; // ue(v)
-    int log2_diff_max_suco_min_suco_cb_size; // ue(v)
-
-    int sps_admvp_flag;     // u(1)
-    int sps_affine_flag;    // u(1)
-    int sps_amvr_flag;      // u(1)
-    int sps_dmvr_flag;      // u(1)
-    int sps_mmvd_flag;      // u(1)
-    int sps_hmvp_flag;      // u(1)
-
-    int sps_eipd_flag;                 // u(1)
-    int sps_ibc_flag;                  // u(1)
-    int log2_max_ibc_cand_size_minus2; // ue(v)
-
-    int sps_cm_init_flag; // u(1)
-    int sps_adcc_flag;    // u(1)
-
-    int sps_iqt_flag; // u(1)
-    int sps_ats_flag; // u(1)
-
-    int sps_addb_flag;   // u(1)
-    int sps_alf_flag;    // u(1)
-    int sps_htdf_flag;   // u(1)
-    int sps_rpl_flag;    // u(1)
-    int sps_pocs_flag;   // u(1)
-    int sps_dquant_flag; // u(1)
-    int sps_dra_flag;    // u(1)
-
-    int log2_max_pic_order_cnt_lsb_minus4; // ue(v)
-    int log2_sub_gop_length;               // ue(v)
-    int log2_ref_pic_gap_length;           // ue(v)
-
-    int max_num_tid0_ref_pics; // ue(v)
-
-    int sps_max_dec_pic_buffering_minus1; // ue(v)
-    int long_term_ref_pic_flag;           // u(1)
-    int rpl1_same_as_rpl0_flag;           // u(1)
-    int num_ref_pic_list_in_sps[2];       // ue(v)
-    struct RefPicListStruct rpls[2][EVC_MAX_NUM_RPLS];
-
-    int picture_cropping_flag;      // u(1)
-    int picture_crop_left_offset;   // ue(v)
-    int picture_crop_right_offset;  // ue(v)
-    int picture_crop_top_offset;    // ue(v)
-    int picture_crop_bottom_offset; // ue(v)
-
-    struct ChromaQpTable chroma_qp_table_struct;
-
-    int vui_parameters_present_flag;    // u(1)
-
-    struct VUIParameters vui_parameters;
-
-} EVCParserSPS;
-
-typedef struct EVCParserPPS {
-    int pps_pic_parameter_set_id;                           // ue(v)
-    int pps_seq_parameter_set_id;                           // ue(v)
-    int num_ref_idx_default_active_minus1[2];               // ue(v)
-    int additional_lt_poc_lsb_len;                          // ue(v)
-    int rpl1_idx_present_flag;                              // u(1)
-    int single_tile_in_pic_flag;                            // u(1)
-    int num_tile_columns_minus1;                            // ue(v)
-    int num_tile_rows_minus1;                               // ue(v)
-    int uniform_tile_spacing_flag;                          // u(1)
-    int tile_column_width_minus1[EVC_MAX_TILE_ROWS];        // ue(v)
-    int tile_row_height_minus1[EVC_MAX_TILE_COLUMNS];          // ue(v)
-    int loop_filter_across_tiles_enabled_flag;              // u(1)
-    int tile_offset_len_minus1;                             // ue(v)
-    int tile_id_len_minus1;                                 // ue(v)
-    int explicit_tile_id_flag;                              // u(1)
-    int tile_id_val[EVC_MAX_TILE_ROWS][EVC_MAX_TILE_COLUMNS];  // u(v)
-    int pic_dra_enabled_flag;                               // u(1)
-    int pic_dra_aps_id;                                     // u(5)
-    int arbitrary_slice_present_flag;                       // u(1)
-    int constrained_intra_pred_flag;                        // u(1)
-    int cu_qp_delta_enabled_flag;                           // u(1)
-    int log2_cu_qp_delta_area_minus6;                       // ue(v)
-
-} EVCParserPPS;
+#include "evc_ps.h"
 
 // The sturcture reflects Slice Header RBSP(raw byte sequence payload) layout
 // @see ISO_IEC_23094-1 section 7.3.2.6
@@ -265,10 +82,7 @@  typedef struct EVCParserPoc {
 } EVCParserPoc;
 
 typedef struct EVCParserContext {
-    //ParseContext pc;
-    EVCParserSPS *sps[EVC_MAX_SPS_COUNT];
-    EVCParserPPS *pps[EVC_MAX_PPS_COUNT];
-
+    EVCParamSets ps;
     EVCParserPoc poc;
 
     int nuh_temporal_id;            // the value of TemporalId (shall be the same for all VCL NAL units of an Access Unit)
@@ -349,14 +163,6 @@  static inline uint32_t evc_read_nal_unit_length(const uint8_t *bits, int bits_si
 // nuh_temporal_id specifies a temporal identifier for the NAL unit
 int ff_evc_get_temporal_id(const uint8_t *bits, int bits_size, void *logctx);
 
-// @see ISO_IEC_23094-1 (7.3.2.1 SPS RBSP syntax)
-EVCParserSPS *ff_evc_parse_sps(EVCParserContext *ctx, const uint8_t *bs, int bs_size);
-
-// @see ISO_IEC_23094-1 (7.3.2.2 SPS RBSP syntax)
-EVCParserPPS *ff_evc_parse_pps(EVCParserContext *ctx, const uint8_t *bs, int bs_size);
-
 int ff_evc_parse_nal_unit(EVCParserContext *ctx, const uint8_t *buf, int buf_size, void *logctx);
 
-void ff_evc_parse_free(EVCParserContext *ctx);
-
 #endif /* AVCODEC_EVC_PARSE_H */
diff --git a/libavcodec/evc_parser.c b/libavcodec/evc_parser.c
index c85b8f89e7..1fd8aac1dc 100644
--- a/libavcodec/evc_parser.c
+++ b/libavcodec/evc_parser.c
@@ -202,7 +202,7 @@  static void evc_parser_close(AVCodecParserContext *s)
 {
     EVCParserContext *ctx = s->priv_data;
 
-    ff_evc_parse_free(ctx);
+    ff_evc_ps_free(&ctx->ps);
 }
 
 const AVCodecParser ff_evc_parser = {
diff --git a/libavcodec/evc_ps.c b/libavcodec/evc_ps.c
new file mode 100644
index 0000000000..af74ba46b0
--- /dev/null
+++ b/libavcodec/evc_ps.c
@@ -0,0 +1,381 @@ 
+/*
+ * 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 "golomb.h"
+#include "parser.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(GetBitContext *gb, RefPicListStruct *rpl)
+{
+    uint32_t delta_poc_st, strp_entry_sign_flag = 0;
+    rpl->ref_pic_num = get_ue_golomb(gb);
+    if (rpl->ref_pic_num > 0) {
+        delta_poc_st = get_ue_golomb(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(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(gb);
+    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(gb);
+        hrd->cpb_size_value_minus1[SchedSelIdx] = get_ue_golomb(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)
+{
+    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(gb);
+        vui->chroma_sample_loc_type_bottom_field = get_ue_golomb(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(gb, 32);
+        vui->time_scale = get_bits(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)
+        hrd_parameters(gb, &vui->hrd_parameters);
+    vui->vcl_hrd_parameters_present_flag = get_bits(gb, 1);
+    if (vui->vcl_hrd_parameters_present_flag)
+        hrd_parameters(gb, &vui->hrd_parameters);
+    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(gb);
+        vui->max_bits_per_mb_denom = get_ue_golomb(gb);
+        vui->log2_max_mv_length_horizontal = get_ue_golomb(gb);
+        vui->log2_max_mv_length_vertical = get_ue_golomb(gb);
+        vui->num_reorder_pics = get_ue_golomb(gb);
+        vui->max_dec_pic_buffering = get_ue_golomb(gb);
+    }
+
+    return 0;
+}
+
+// @see ISO_IEC_23094-1 (7.3.2.1 SPS RBSP syntax)
+EVCParserSPS *ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size)
+{
+    GetBitContext gb;
+    EVCParserSPS *sps;
+    int sps_seq_parameter_set_id;
+
+    if (init_get_bits8(&gb, bs, bs_size) < 0)
+        return NULL;
+
+    sps_seq_parameter_set_id = get_ue_golomb(&gb);
+
+    if (sps_seq_parameter_set_id >= EVC_MAX_SPS_COUNT)
+        return NULL;
+
+    if(!ps->sps[sps_seq_parameter_set_id]) {
+        if((ps->sps[sps_seq_parameter_set_id] = av_malloc(sizeof(EVCParserSPS))) == NULL)
+            return NULL;
+    }
+
+    sps = ps->sps[sps_seq_parameter_set_id];
+    memset(sps, 0, sizeof(*sps));
+
+    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(&gb);
+
+    sps->pic_width_in_luma_samples = get_ue_golomb(&gb);
+    sps->pic_height_in_luma_samples = get_ue_golomb(&gb);
+
+    sps->bit_depth_luma_minus8 = get_ue_golomb(&gb);
+    sps->bit_depth_chroma_minus8 = get_ue_golomb(&gb);
+
+    sps->sps_btt_flag = get_bits(&gb, 1);
+    if (sps->sps_btt_flag) {
+        sps->log2_ctu_size_minus5 = get_ue_golomb(&gb);
+        sps->log2_min_cb_size_minus2 = get_ue_golomb(&gb);
+        sps->log2_diff_ctu_max_14_cb_size = get_ue_golomb(&gb);
+        sps->log2_diff_ctu_max_tt_cb_size = get_ue_golomb(&gb);
+        sps->log2_diff_min_cb_min_tt_cb_size_minus2 = get_ue_golomb(&gb);
+    }
+
+    sps->sps_suco_flag = get_bits(&gb, 1);
+    if (sps->sps_suco_flag) {
+        sps->log2_diff_ctu_size_max_suco_cb_size = get_ue_golomb(&gb);
+        sps->log2_diff_max_suco_min_suco_cb_size = get_ue_golomb(&gb);
+    }
+
+    sps->sps_admvp_flag = get_bits(&gb, 1);
+    if (sps->sps_admvp_flag) {
+        sps->sps_affine_flag = get_bits(&gb, 1);
+        sps->sps_amvr_flag = get_bits(&gb, 1);
+        sps->sps_dmvr_flag = get_bits(&gb, 1);
+        sps->sps_mmvd_flag = get_bits(&gb, 1);
+        sps->sps_hmvp_flag = get_bits(&gb, 1);
+    }
+
+    sps->sps_eipd_flag =  get_bits(&gb, 1);
+    if (sps->sps_eipd_flag) {
+        sps->sps_ibc_flag = get_bits(&gb, 1);
+        if (sps->sps_ibc_flag)
+            sps->log2_max_ibc_cand_size_minus2 = get_ue_golomb(&gb);
+    }
+
+    sps->sps_cm_init_flag = get_bits(&gb, 1);
+    if (sps->sps_cm_init_flag)
+        sps->sps_adcc_flag = get_bits(&gb, 1);
+
+    sps->sps_iqt_flag = get_bits(&gb, 1);
+    if (sps->sps_iqt_flag)
+        sps->sps_ats_flag = get_bits(&gb, 1);
+
+    sps->sps_addb_flag = get_bits(&gb, 1);
+    sps->sps_alf_flag = get_bits(&gb, 1);
+    sps->sps_htdf_flag = get_bits(&gb, 1);
+    sps->sps_rpl_flag = get_bits(&gb, 1);
+    sps->sps_pocs_flag = get_bits(&gb, 1);
+    sps->sps_dquant_flag = get_bits(&gb, 1);
+    sps->sps_dra_flag = get_bits(&gb, 1);
+
+    if (sps->sps_pocs_flag)
+        sps->log2_max_pic_order_cnt_lsb_minus4 = get_ue_golomb(&gb);
+
+    if (!sps->sps_pocs_flag || !sps->sps_rpl_flag) {
+        sps->log2_sub_gop_length = get_ue_golomb(&gb);
+        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(&gb);
+    else {
+        sps->sps_max_dec_pic_buffering_minus1 = get_ue_golomb(&gb);
+        sps->long_term_ref_pic_flag = get_bits(&gb, 1);
+        sps->rpl1_same_as_rpl0_flag = get_bits(&gb, 1);
+        sps->num_ref_pic_list_in_sps[0] = get_ue_golomb(&gb);
+
+        for (int i = 0; i < sps->num_ref_pic_list_in_sps[0]; ++i)
+            ref_pic_list_struct(&gb, &sps->rpls[0][i]);
+
+        if (!sps->rpl1_same_as_rpl0_flag) {
+            sps->num_ref_pic_list_in_sps[1] = get_ue_golomb(&gb);
+            for (int i = 0; i < sps->num_ref_pic_list_in_sps[1]; ++i)
+                ref_pic_list_struct(&gb, &sps->rpls[1][i]);
+        }
+    }
+
+    sps->picture_cropping_flag = get_bits(&gb, 1);
+
+    if (sps->picture_cropping_flag) {
+        sps->picture_crop_left_offset = get_ue_golomb(&gb);
+        sps->picture_crop_right_offset = get_ue_golomb(&gb);
+        sps->picture_crop_top_offset = get_ue_golomb(&gb);
+        sps->picture_crop_bottom_offset = get_ue_golomb(&gb);
+    }
+
+    if (sps->chroma_format_idc != 0) {
+        sps->chroma_qp_table_struct.chroma_qp_table_present_flag = get_bits(&gb, 1);
+
+        if (sps->chroma_qp_table_struct.chroma_qp_table_present_flag) {
+            sps->chroma_qp_table_struct.same_qp_table_for_chroma = get_bits(&gb, 1);
+            sps->chroma_qp_table_struct.global_offset_flag = get_bits(&gb, 1);
+            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);;
+                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(&gb);
+                }
+            }
+        }
+    }
+
+    sps->vui_parameters_present_flag = get_bits(&gb, 1);
+    if (sps->vui_parameters_present_flag)
+        vui_parameters(&gb, &(sps->vui_parameters));
+
+    // @note
+    // If necessary, add the missing fields to the EVCParserSPS structure
+    // and then extend parser implementation
+
+    return sps;
+}
+
+// @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
+//
+EVCParserPPS *ff_evc_parse_pps(EVCParamSets *ps, const uint8_t *bs, int bs_size)
+{
+    GetBitContext gb;
+    EVCParserPPS *pps;
+
+    int pps_pic_parameter_set_id;
+
+    if (init_get_bits8(&gb, bs, bs_size) < 0)
+        return NULL;
+
+    pps_pic_parameter_set_id = get_ue_golomb(&gb);
+    if (pps_pic_parameter_set_id > EVC_MAX_PPS_COUNT)
+        return NULL;
+
+    if(!ps->pps[pps_pic_parameter_set_id]) {
+        if ((ps->pps[pps_pic_parameter_set_id] = av_malloc(sizeof(EVCParserPPS))) == NULL)
+            return NULL;
+    }
+
+    pps = ps->pps[pps_pic_parameter_set_id];
+    memset(pps, 0, sizeof(*pps));
+
+    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) {
+        av_freep(&ps->pps[pps_pic_parameter_set_id]);
+        return NULL;
+    }
+
+    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_bits(&gb, 1);
+    pps->single_tile_in_pic_flag = get_bits(&gb, 1);
+
+    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);
+        pps->uniform_tile_spacing_flag = get_bits(&gb, 1);
+
+        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_bits(&gb, 1);
+        pps->tile_offset_len_minus1 = get_ue_golomb(&gb);
+    }
+
+    pps->tile_id_len_minus1 = get_ue_golomb(&gb);
+    pps->explicit_tile_id_flag = get_bits(&gb, 1);
+
+    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_bits(&gb, 1);
+
+    if (pps->pic_dra_enabled_flag)
+        pps->pic_dra_aps_id = get_bits(&gb, 5);
+
+    pps->arbitrary_slice_present_flag = get_bits(&gb, 1);
+    pps->constrained_intra_pred_flag = get_bits(&gb, 1);
+    pps->cu_qp_delta_enabled_flag = get_bits(&gb, 1);
+
+    if (pps->cu_qp_delta_enabled_flag)
+        pps->log2_cu_qp_delta_area_minus6 = get_ue_golomb(&gb);
+
+    return pps;
+}
+
+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]);
+}
diff --git a/libavcodec/evc_ps.h b/libavcodec/evc_ps.h
new file mode 100644
index 0000000000..989336079f
--- /dev/null
+++ b/libavcodec/evc_ps.h
@@ -0,0 +1,228 @@ 
+/*
+ * 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
+ */
+
+/**
+ * @file
+ * EVC decoder/parser shared code
+ */
+
+#ifndef AVCODEC_EVC_PS_H
+#define AVCODEC_EVC_PS_H
+
+#include <stdint.h>
+
+#include "evc.h"
+
+#define EVC_MAX_QP_TABLE_SIZE   58
+#define NUM_CPB                 32
+
+// rpl structure
+typedef struct RefPicListStruct {
+    int poc;
+    int tid;
+    int ref_pic_num;
+    int ref_pic_active_num;
+    int ref_pics[EVC_MAX_NUM_REF_PICS];
+    char pic_type;
+
+} RefPicListStruct;
+
+// chromaQP table structure to be signalled in SPS
+typedef struct ChromaQpTable {
+    int chroma_qp_table_present_flag;       // u(1)
+    int same_qp_table_for_chroma;           // u(1)
+    int global_offset_flag;                 // u(1)
+    int num_points_in_qp_table_minus1[2];   // ue(v)
+    int delta_qp_in_val_minus1[2][EVC_MAX_QP_TABLE_SIZE];   // u(6)
+    int delta_qp_out_val[2][EVC_MAX_QP_TABLE_SIZE];         // se(v)
+} ChromaQpTable;
+
+// Hypothetical Reference Decoder (HRD) parameters, part of VUI
+typedef struct HRDParameters {
+    int cpb_cnt_minus1;                             // ue(v)
+    int bit_rate_scale;                             // u(4)
+    int cpb_size_scale;                             // u(4)
+    int bit_rate_value_minus1[NUM_CPB];             // ue(v)
+    int cpb_size_value_minus1[NUM_CPB];             // ue(v)
+    int cbr_flag[NUM_CPB];                          // u(1)
+    int initial_cpb_removal_delay_length_minus1;    // u(5)
+    int cpb_removal_delay_length_minus1;            // u(5)
+    int dpb_output_delay_length_minus1;             // u(5)
+    int time_offset_length;                         // u(5)
+} HRDParameters;
+
+// video usability information (VUI) part of SPS
+typedef struct VUIParameters {
+    int aspect_ratio_info_present_flag;             // u(1)
+    int aspect_ratio_idc;                           // u(8)
+    int sar_width;                                  // u(16)
+    int sar_height;                                 // u(16)
+    int overscan_info_present_flag;                 // u(1)
+    int overscan_appropriate_flag;                  // u(1)
+    int video_signal_type_present_flag;             // u(1)
+    int video_format;                               // u(3)
+    int video_full_range_flag;                      // u(1)
+    int colour_description_present_flag;            // u(1)
+    int colour_primaries;                           // u(8)
+    int transfer_characteristics;                   // u(8)
+    int matrix_coefficients;                        // u(8)
+    int chroma_loc_info_present_flag;               // u(1)
+    int chroma_sample_loc_type_top_field;           // ue(v)
+    int chroma_sample_loc_type_bottom_field;        // ue(v)
+    int neutral_chroma_indication_flag;             // u(1)
+    int field_seq_flag;                             // u(1)
+    int timing_info_present_flag;                   // u(1)
+    int num_units_in_tick;                          // u(32)
+    int time_scale;                                 // u(32)
+    int fixed_pic_rate_flag;                        // u(1)
+    int nal_hrd_parameters_present_flag;            // u(1)
+    int vcl_hrd_parameters_present_flag;            // u(1)
+    int low_delay_hrd_flag;                         // u(1)
+    int pic_struct_present_flag;                    // u(1)
+    int bitstream_restriction_flag;                 // u(1)
+    int motion_vectors_over_pic_boundaries_flag;    // u(1)
+    int max_bytes_per_pic_denom;                    // ue(v)
+    int max_bits_per_mb_denom;                      // ue(v)
+    int log2_max_mv_length_horizontal;              // ue(v)
+    int log2_max_mv_length_vertical;                // ue(v)
+    int num_reorder_pics;                           // ue(v)
+    int max_dec_pic_buffering;                      // ue(v)
+
+    HRDParameters hrd_parameters;
+} VUIParameters;
+
+// The sturcture reflects SPS RBSP(raw byte sequence payload) layout
+// @see ISO_IEC_23094-1 section 7.3.2.1
+//
+// The following descriptors specify the parsing process of each element
+// u(n) - unsigned integer using n bits
+// ue(v) - unsigned integer 0-th order Exp_Golomb-coded syntax element with the left bit first
+typedef struct EVCParserSPS {
+    int sps_seq_parameter_set_id;   // ue(v)
+    int profile_idc;                // u(8)
+    int level_idc;                  // u(8)
+    int toolset_idc_h;              // u(32)
+    int toolset_idc_l;              // u(32)
+    int chroma_format_idc;          // ue(v)
+    int pic_width_in_luma_samples;  // ue(v)
+    int pic_height_in_luma_samples; // ue(v)
+    int bit_depth_luma_minus8;      // ue(v)
+    int bit_depth_chroma_minus8;    // ue(v)
+
+    int sps_btt_flag;                           // u(1)
+    int log2_ctu_size_minus5;                   // ue(v)
+    int log2_min_cb_size_minus2;                // ue(v)
+    int log2_diff_ctu_max_14_cb_size;           // ue(v)
+    int log2_diff_ctu_max_tt_cb_size;           // ue(v)
+    int log2_diff_min_cb_min_tt_cb_size_minus2; // ue(v)
+
+    int sps_suco_flag;                       // u(1)
+    int log2_diff_ctu_size_max_suco_cb_size; // ue(v)
+    int log2_diff_max_suco_min_suco_cb_size; // ue(v)
+
+    int sps_admvp_flag;     // u(1)
+    int sps_affine_flag;    // u(1)
+    int sps_amvr_flag;      // u(1)
+    int sps_dmvr_flag;      // u(1)
+    int sps_mmvd_flag;      // u(1)
+    int sps_hmvp_flag;      // u(1)
+
+    int sps_eipd_flag;                 // u(1)
+    int sps_ibc_flag;                  // u(1)
+    int log2_max_ibc_cand_size_minus2; // ue(v)
+
+    int sps_cm_init_flag; // u(1)
+    int sps_adcc_flag;    // u(1)
+
+    int sps_iqt_flag; // u(1)
+    int sps_ats_flag; // u(1)
+
+    int sps_addb_flag;   // u(1)
+    int sps_alf_flag;    // u(1)
+    int sps_htdf_flag;   // u(1)
+    int sps_rpl_flag;    // u(1)
+    int sps_pocs_flag;   // u(1)
+    int sps_dquant_flag; // u(1)
+    int sps_dra_flag;    // u(1)
+
+    int log2_max_pic_order_cnt_lsb_minus4; // ue(v)
+    int log2_sub_gop_length;               // ue(v)
+    int log2_ref_pic_gap_length;           // ue(v)
+
+    int max_num_tid0_ref_pics; // ue(v)
+
+    int sps_max_dec_pic_buffering_minus1; // ue(v)
+    int long_term_ref_pic_flag;           // u(1)
+    int rpl1_same_as_rpl0_flag;           // u(1)
+    int num_ref_pic_list_in_sps[2];       // ue(v)
+    struct RefPicListStruct rpls[2][EVC_MAX_NUM_RPLS];
+
+    int picture_cropping_flag;      // u(1)
+    int picture_crop_left_offset;   // ue(v)
+    int picture_crop_right_offset;  // ue(v)
+    int picture_crop_top_offset;    // ue(v)
+    int picture_crop_bottom_offset; // ue(v)
+
+    struct ChromaQpTable chroma_qp_table_struct;
+
+    int vui_parameters_present_flag;    // u(1)
+
+    struct VUIParameters vui_parameters;
+
+} EVCParserSPS;
+
+typedef struct EVCParserPPS {
+    int pps_pic_parameter_set_id;                           // ue(v)
+    int pps_seq_parameter_set_id;                           // ue(v)
+    int num_ref_idx_default_active_minus1[2];               // ue(v)
+    int additional_lt_poc_lsb_len;                          // ue(v)
+    int rpl1_idx_present_flag;                              // u(1)
+    int single_tile_in_pic_flag;                            // u(1)
+    int num_tile_columns_minus1;                            // ue(v)
+    int num_tile_rows_minus1;                               // ue(v)
+    int uniform_tile_spacing_flag;                          // u(1)
+    int tile_column_width_minus1[EVC_MAX_TILE_ROWS];        // ue(v)
+    int tile_row_height_minus1[EVC_MAX_TILE_COLUMNS];          // ue(v)
+    int loop_filter_across_tiles_enabled_flag;              // u(1)
+    int tile_offset_len_minus1;                             // ue(v)
+    int tile_id_len_minus1;                                 // ue(v)
+    int explicit_tile_id_flag;                              // u(1)
+    int tile_id_val[EVC_MAX_TILE_ROWS][EVC_MAX_TILE_COLUMNS];  // u(v)
+    int pic_dra_enabled_flag;                               // u(1)
+    int pic_dra_aps_id;                                     // u(5)
+    int arbitrary_slice_present_flag;                       // u(1)
+    int constrained_intra_pred_flag;                        // u(1)
+    int cu_qp_delta_enabled_flag;                           // u(1)
+    int log2_cu_qp_delta_area_minus6;                       // ue(v)
+
+} EVCParserPPS;
+
+typedef struct EVCParamSets {
+    EVCParserSPS *sps[EVC_MAX_SPS_COUNT];
+    EVCParserPPS *pps[EVC_MAX_PPS_COUNT];
+} EVCParamSets;
+
+// @see ISO_IEC_23094-1 (7.3.2.1 SPS RBSP syntax)
+EVCParserSPS *ff_evc_parse_sps(EVCParamSets *ps, const uint8_t *bs, int bs_size);
+
+// @see ISO_IEC_23094-1 (7.3.2.2 SPS RBSP syntax)
+EVCParserPPS *ff_evc_parse_pps(EVCParamSets *ps, const uint8_t *bs, int bs_size);
+
+void ff_evc_ps_free(EVCParamSets *ps);
+
+#endif /* AVCODEC_EVC_PS_H */