void getH264VideoResolution()

in src/source/codec/sps_decode.c [75:202]


void getH264VideoResolution(char *pSps, size_t uSpsLen, uint16_t *puWidth, uint16_t *puHeight)
{
    BitStream_t xBitStream = {.pBuf = (unsigned char *)pSps, .xCurrentBit = 0};
    int frame_crop_left_offset = 0;
    int frame_crop_right_offset = 0;
    int frame_crop_top_offset = 0;
    int frame_crop_bottom_offset = 0;
    int crop_unit_x = 0;
    int crop_unit_y = 0;
    int chroma_format_idc = 1;
    int profile_idc = uReadBits(&xBitStream, 8);
    int constraint_set0_flag = uReadBit(&xBitStream);
    int constraint_set1_flag = uReadBit(&xBitStream);
    int constraint_set2_flag = uReadBit(&xBitStream);
    int constraint_set3_flag = uReadBit(&xBitStream);
    int constraint_set4_flag = uReadBit(&xBitStream);
    int constraint_set5_flag = uReadBit(&xBitStream);
    int reserved_zero_2bits = uReadBits(&xBitStream, 2);
    int level_idc = uReadBits(&xBitStream, 8);
    int seq_parameter_set_id = uReadExponentialGolombCode(&xBitStream);

    int xWidth = 0;
    int xHeight = 0;

    /* Please refer to https://www.itu.int/rec/T-REC-H.264/ Section 7.4.2.1.1 Sequence parameter set data semantics */
    if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 244 || profile_idc == 44 || profile_idc == 83 || profile_idc == 86 || profile_idc == 118 ||
        profile_idc == 128 || profile_idc == 138 || profile_idc == 139 || profile_idc == 134 || profile_idc == 135)
    {
        chroma_format_idc = uReadExponentialGolombCode(&xBitStream);
        if (chroma_format_idc == 3)
        {
            int residual_colour_transform_flag = uReadBit(&xBitStream);
        }

        int bit_depth_luma_minus8 = uReadExponentialGolombCode(&xBitStream);
        int bit_depth_chroma_minus8 = uReadExponentialGolombCode(&xBitStream);
        int qpprime_y_zero_transform_bypass_flag = uReadBit(&xBitStream);

        int seq_scaling_matrix_present_flag = uReadBit(&xBitStream);
        if (seq_scaling_matrix_present_flag)
        {
            int i = 0;
            for (i = 0; i < 8; i++)
            {
                int seq_scaling_list_present_flag = uReadBit(&xBitStream);
                if (seq_scaling_list_present_flag)
                {
                    int sizeOfScalingList = (i < 6) ? 16 : 64;
                    int lastScale = 8;
                    int nextScale = 8;
                    int j = 0;
                    for (j = 0; j < sizeOfScalingList; j++)
                    {
                        if (nextScale != 0)
                        {
                            int delta_scale = uReadSE(&xBitStream);
                            nextScale = (lastScale + delta_scale + 256) % 256;
                        }
                        lastScale = (nextScale == 0) ? lastScale : nextScale;
                    }
                }
            }
        }
    }

    int log2_max_frame_num_minus4 = uReadExponentialGolombCode(&xBitStream);
    int pic_order_cnt_type = uReadExponentialGolombCode(&xBitStream);
    if (pic_order_cnt_type == 0)
    {
        int log2_max_pic_order_cnt_lsb_minus4 = uReadExponentialGolombCode(&xBitStream);
    }
    else if (pic_order_cnt_type == 1)
    {
        int delta_pic_order_always_zero_flag = uReadBit(&xBitStream);
        int offset_for_non_ref_pic = uReadSE(&xBitStream);
        int offset_for_top_to_bottom_field = uReadSE(&xBitStream);
        int num_ref_frames_in_pic_order_cnt_cycle = uReadExponentialGolombCode(&xBitStream);
        int i;
        for (i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++)
        {
            uReadSE(&xBitStream);
        }
    }
    int max_num_ref_frames = uReadExponentialGolombCode(&xBitStream);
    int gaps_in_frame_num_value_allowed_flag = uReadBit(&xBitStream);
    int pic_width_in_mbs_minus1 = uReadExponentialGolombCode(&xBitStream);
    int pic_height_in_map_units_minus1 = uReadExponentialGolombCode(&xBitStream);
    int frame_mbs_only_flag = uReadBit(&xBitStream);
    if (!frame_mbs_only_flag)
    {
        int mb_adaptive_frame_field_flag = uReadBit(&xBitStream);
    }
    int direct_8x8_inference_flag = uReadBit(&xBitStream);
    int frame_cropping_flag = uReadBit(&xBitStream);
    if (frame_cropping_flag)
    {
        frame_crop_left_offset = uReadExponentialGolombCode(&xBitStream);
        frame_crop_right_offset = uReadExponentialGolombCode(&xBitStream);
        frame_crop_top_offset = uReadExponentialGolombCode(&xBitStream);
        frame_crop_bottom_offset = uReadExponentialGolombCode(&xBitStream);
        if (0 == chroma_format_idc)
        {
            crop_unit_x = 1;
            crop_unit_y = 2 - frame_mbs_only_flag;
        }
        else if (1 == chroma_format_idc)
        {
            crop_unit_x = 2;
            crop_unit_y = 2 * (2 - frame_mbs_only_flag);
        }
        else if (2 == chroma_format_idc)
        {
            crop_unit_x = 2;
            crop_unit_y = 2 - frame_mbs_only_flag;
        }
        else
        {
            crop_unit_x = 1;
            crop_unit_y = 2 - frame_mbs_only_flag;
        }
    }

    xWidth = ((pic_width_in_mbs_minus1 + 1) * 16) - crop_unit_x * (frame_crop_left_offset + frame_crop_right_offset);
    xHeight = ((2 - frame_mbs_only_flag) * (pic_height_in_map_units_minus1 + 1) * 16) - crop_unit_y * (frame_crop_top_offset + frame_crop_bottom_offset);

    *puWidth = (uint16_t)xWidth;
    *puHeight = (uint16_t)xHeight;
}