STATUS parseH265Sps()

in src/mkvgen/src/SpsParser.c [407:592]


STATUS parseH265Sps(PBYTE pSps, UINT32 spsSize, PH265SpsInfo pSpsInfo)
{
    STATUS retStatus = STATUS_SUCCESS;
    UINT32 i, read, sps_sub_layer_ordering_info_present_flag, scaling_list_enabled_flag, sps_scaling_list_data_present_flag, pcm_enabled_flag,
        num_short_term_ref_pic_sets, log2_max_pic_order_cnt_lsb_minus4;

    BitReader bitReader;
    UINT32 adaptedSize = spsSize;
    PBYTE pAdaptedBits = NULL;
    BOOL gotSpsData = FALSE;

    CHK(pSps != NULL && pSpsInfo != NULL, STATUS_NULL_ARG);
    CHK(spsSize != 0, STATUS_INVALID_ARG_LEN);

    MEMSET(pSpsInfo, 0x00, SIZEOF(H265SpsInfo));

    // Adapt the sps to get rid of the EPB - NOTE: the existing size should be greater than the adapted so
    // we don't need to run the function to extract the adapted size first
    // Allocate enough storage to store the data temporarily
    pAdaptedBits = (PBYTE) MEMALLOC(spsSize);
    CHK(pAdaptedBits != NULL, STATUS_NOT_ENOUGH_MEMORY);

    // Get the converted bits
    CHK_STATUS(adaptFrameNalsFromAnnexBToAvcc(pSps, spsSize, TRUE, pAdaptedBits, &adaptedSize));

    // Create a bit reader on top of the SPS
    CHK_STATUS(bitReaderReset(&bitReader, pAdaptedBits, adaptedSize * 8));

    // Read the sps_video_parameter_set_id
    CHK_STATUS(bitReaderReadBits(&bitReader, 4, &read));

    // Read the sps_max_sub_layers_minus1 - NOTE: As it's 3 bits only it cant be larger than 8
    CHK_STATUS(bitReaderReadBits(&bitReader, 3, &read));
    pSpsInfo->max_sub_layers_minus1 = (UINT8) read;

    // Read the sps_temporal_id_nesting_flag
    CHK_STATUS(bitReaderReadBits(&bitReader, 1, &read));

    // profile tier level
    CHK_STATUS(parseProfileTierLevel(&bitReader, pSpsInfo));

    // Read the sps_seq_parameter_set_id
    CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &read));

    // Read the chroma_format_idc
    CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &read));
    pSpsInfo->chroma_format_idc = (UINT8) read;

    if (pSpsInfo->chroma_format_idc == 3) {
        // Read the separate_colour_plane_flag
        CHK_STATUS(bitReaderReadBits(&bitReader, 1, &read));
    }

    // Read the pic_width_in_luma_samples
    CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &read));
    pSpsInfo->pic_width_in_luma_samples = (UINT16) read;

    // Read the pic_height_in_luma_samples
    CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &read));
    pSpsInfo->pic_height_in_luma_samples = (UINT16) read;

    // Read the conformance_window_flag
    CHK_STATUS(bitReaderReadBits(&bitReader, 1, &read));
    pSpsInfo->conformance_window_flag = (UINT8) read;

    if (pSpsInfo->conformance_window_flag != 0) {
        // Read the conf_win_left_offset
        CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &pSpsInfo->conf_win_left_offset));

        // Read the conf_win_right_offset
        CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &pSpsInfo->conf_win_right_offset));

        // Read the conf_win_top_offset
        CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &pSpsInfo->conf_win_top_offset));

        // Read the conf_win_bottom_offset
        CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &pSpsInfo->conf_win_bottom_offset));
    }

    // Read the bit_depth_luma_minus8
    CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &read));
    pSpsInfo->bit_depth_luma_minus8 = (UINT8) read;

    // Read the bit_depth_chroma_minus8
    CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &read));
    pSpsInfo->bit_depth_chroma_minus8 = (UINT8) read;

    // At this stage we have the sps data we need. The parser will break on some data
    // so at this stage we can return success and return the data we extracted.
    // This seems to come from an older version of the HEVC.
    gotSpsData = TRUE;

    // Read the log2_max_pic_order_cnt_lsb_minus4
    CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &log2_max_pic_order_cnt_lsb_minus4));

    // Read the sps_sub_layer_ordering_info_present_flag
    CHK_STATUS(bitReaderReadBits(&bitReader, 1, &sps_sub_layer_ordering_info_present_flag));

    i = (sps_sub_layer_ordering_info_present_flag != 0) ? 0 : pSpsInfo->max_sub_layers_minus1;
    for (; i <= pSpsInfo->max_sub_layers_minus1; i++) {
        // Read the sps_max_dec_pic_buffering_minus1[i]
        CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &read));

        // Read the sps_max_num_reorder_pics[i]
        CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &read));

        // Read the sps_max_latency_increase_plus1[i]
        CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &read));
    }

    // Read the log2_min_luma_coding_block_size_minus3
    CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &read));

    // Read the log2_diff_max_min_luma_coding_block_size
    CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &read));

    // Read the log2_min_transform_block_size_minus2
    CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &read));

    // Read the log2_diff_max_min_transform_block_size
    CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &read));

    // Read the max_transform_hierarchy_depth_inter
    CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &read));

    // Read the max_transform_hierarchy_depth_intra
    CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &read));

    // Read the scaling_list_enabled_flag
    CHK_STATUS(bitReaderReadBits(&bitReader, 1, &scaling_list_enabled_flag));

    if (scaling_list_enabled_flag != 0) {
        // Read the sps_scaling_list_data_present_flag
        CHK_STATUS(bitReaderReadBits(&bitReader, 1, &sps_scaling_list_data_present_flag));
        if (sps_scaling_list_data_present_flag != 0) {
            // Process scaling lists
            CHK_STATUS(parseScalingListData(&bitReader));
        }
    }

    // Read the amp_enabled_flag
    CHK_STATUS(bitReaderReadBits(&bitReader, 1, &read));

    // Read the sample_adaptive_offset_enabled_flag
    CHK_STATUS(bitReaderReadBits(&bitReader, 1, &read));

    // Read the pcm_enabled_flag
    CHK_STATUS(bitReaderReadBits(&bitReader, 1, &pcm_enabled_flag));

    if (pcm_enabled_flag != 0) {
        // Read the pcm_sample_bit_depth_luma_minus1
        CHK_STATUS(bitReaderReadBits(&bitReader, 4, &read));

        // Read the pcm_sample_bit_depth_chroma_minus1
        CHK_STATUS(bitReaderReadBits(&bitReader, 4, &read));

        // Read the log2_min_pcm_luma_coding_block_size_minus3
        CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &read));

        // Read the log2_diff_max_min_pcm_luma_coding_block_size
        CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &read));

        // Read the pcm_loop_filter_disabled_flag
        CHK_STATUS(bitReaderReadBits(&bitReader, 1, &read));
    }

    // Read the num_short_term_ref_pic_sets
    CHK_STATUS(bitReaderReadExpGolomb(&bitReader, &num_short_term_ref_pic_sets));
    for (i = 0; i < num_short_term_ref_pic_sets; i++) {
        // short_term_ref_pic_set()
        // TODO: Add proper processing for the rest but for now we already have the information we need
    }

CleanUp:

    if (pAdaptedBits != NULL) {
        MEMFREE(pAdaptedBits);
    }

    if (gotSpsData) {
        // If we got the data we need then we can reset the status
        retStatus = STATUS_SUCCESS;
    }

    return retStatus;
}