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;
}