412 lines
12 KiB
C++
412 lines
12 KiB
C++
/***************************************************************************************
|
|
*
|
|
* IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
|
|
*
|
|
* By downloading, copying, installing or using the software you agree to this license.
|
|
* If you do not agree to this license, do not download, install,
|
|
* copy or use the software.
|
|
*
|
|
* Copyright (C) 2014-2024, Happytimesoft Corporation, all rights reserved.
|
|
*
|
|
* Redistribution and use in binary forms, with or without modification, are permitted.
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software distributed
|
|
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
|
|
* language governing permissions and limitations under the License.
|
|
*
|
|
****************************************************************************************/
|
|
|
|
#include "sys_inc.h"
|
|
#include "bs.h"
|
|
#include "util.h"
|
|
#include "h265.h"
|
|
#include "h265_util.h"
|
|
|
|
|
|
/**************************************************************************************/
|
|
|
|
int h265_extract_rbsp(const uint8 *src, int length, uint8 *dst)
|
|
{
|
|
int i, si, di;
|
|
|
|
for (i = 0; i + 1 < length; i += 2)
|
|
{
|
|
if (src[i])
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (i > 0 && src[i - 1] == 0)
|
|
{
|
|
i--;
|
|
}
|
|
|
|
if (i + 2 < length && src[i + 1] == 0 && src[i + 2] <= 3)
|
|
{
|
|
if (src[i + 2] != 3 && src[i + 2] != 0)
|
|
{
|
|
/* startcode, so we must be past the end */
|
|
length = i;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i >= length - 1)
|
|
{
|
|
// no escaped 0
|
|
memcpy(dst, src, length);
|
|
return length;
|
|
}
|
|
|
|
memcpy(dst, src, i);
|
|
si = di = i;
|
|
|
|
while (si + 2 < length)
|
|
{
|
|
// remove escapes (very rare 1:2^22)
|
|
if (src[si + 2] > 3)
|
|
{
|
|
dst[di++] = src[si++];
|
|
dst[di++] = src[si++];
|
|
}
|
|
else if (src[si] == 0 && src[si + 1] == 0 && src[si + 2] != 0)
|
|
{
|
|
if (src[si + 2] == 3)
|
|
{
|
|
// escape
|
|
dst[di++] = 0;
|
|
dst[di++] = 0;
|
|
si += 3;
|
|
|
|
continue;
|
|
}
|
|
else // next start code
|
|
{
|
|
return si;
|
|
}
|
|
}
|
|
|
|
dst[di++] = src[si++];
|
|
}
|
|
|
|
while (si < length)
|
|
{
|
|
dst[di++] = src[si++];
|
|
}
|
|
|
|
return si;
|
|
}
|
|
|
|
void h265_parser_init(h265_t * h)
|
|
{
|
|
memset(h, 0, sizeof(h265_t));
|
|
}
|
|
|
|
int h265_parser_parse(h265_t * h, uint8 * p_data, int len)
|
|
{
|
|
uint32 i;
|
|
bs_t s;
|
|
uint8 bufs[512];
|
|
|
|
if (len > (int)sizeof(bufs))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
len = h265_extract_rbsp(p_data, len, bufs);
|
|
|
|
bs_init(&s, bufs, len);
|
|
|
|
bs_read(&s, 4); // sps_video_parameter_set_id u(4)
|
|
h->sps_max_sub_layers_minus1 = bs_read(&s, 3); // sps_max_sub_layers_minus1 u(3)
|
|
if (h->sps_max_sub_layers_minus1 > 6)
|
|
{
|
|
log_print(HT_LOG_ERR, "%s, sps_max_sub_layers_minus1[%d]>6!!!\r\n",
|
|
__FUNCTION__, h->sps_max_sub_layers_minus1);
|
|
return -1;
|
|
}
|
|
|
|
bs_read(&s, 1); // sps_temporal_id_nesting_flag u(1)
|
|
|
|
// profile_tier_level( maxNumSubLayersMinus1 )
|
|
{
|
|
bs_read(&s, 2); // general_profile_space u(2)
|
|
bs_read(&s, 1); // general_tier_flag u(1)
|
|
h->general_profile_idc = bs_read(&s, 5); // general_profile_idc u(5)
|
|
bs_read(&s, 32); // general_profile_compatibility_flag[ j ] u(5)
|
|
bs_read(&s, 1); // general_progressive_source_flag u(1)
|
|
bs_read(&s, 1); // general_interlaced_source_flag u(1)
|
|
bs_read(&s, 1); // general_non_packed_constraint_flag u(1)
|
|
bs_read(&s, 1); // general_frame_only_constraint_flag u(1)
|
|
bs_skip(&s, 44); // general_reserved_zero_44bits u(44)
|
|
h->general_level_idc = bs_read(&s, 8); // general_level_idc u(8)
|
|
|
|
uint8 sub_layer_profile_present_flag[6] = {0};
|
|
uint8 sub_layer_level_present_flag[6] = {0};
|
|
|
|
for (i = 0; i < h->sps_max_sub_layers_minus1; i++)
|
|
{
|
|
sub_layer_profile_present_flag[i]= bs_read(&s, 1);
|
|
sub_layer_level_present_flag[i]= bs_read(&s, 1);
|
|
}
|
|
|
|
if (h->sps_max_sub_layers_minus1 > 0)
|
|
{
|
|
for (i = h->sps_max_sub_layers_minus1; i < 8; i++)
|
|
{
|
|
bs_read(&s, 2);
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < h->sps_max_sub_layers_minus1; i++)
|
|
{
|
|
if (sub_layer_profile_present_flag[i])
|
|
{
|
|
bs_read(&s, 2); // sub_layer_profile_space[i]
|
|
bs_read(&s, 1); // sub_layer_tier_flag[i]
|
|
bs_read(&s, 5); // sub_layer_profile_idc[i]
|
|
bs_read(&s, 32); // sub_layer_profile_compatibility_flag[i][32]
|
|
bs_read(&s, 1); // sub_layer_progressive_source_flag[i]
|
|
bs_read(&s, 1); // sub_layer_interlaced_source_flag[i]
|
|
bs_read(&s, 1); // sub_layer_non_packed_constraint_flag[i]
|
|
bs_read(&s, 1); // sub_layer_frame_only_constraint_flag[i]
|
|
bs_read(&s, 44); // sub_layer_reserved_zero_44bits[i]
|
|
}
|
|
|
|
if (sub_layer_level_present_flag[i])
|
|
{
|
|
bs_read(&s, 8); // sub_layer_level_idc[i]
|
|
}
|
|
}
|
|
}
|
|
|
|
h->sps_seq_parameter_set_id = bs_read_ue(&s); // sps_seq_parameter_set_id ue(v)
|
|
h->chroma_format_idc = bs_read_ue(&s); // chroma_format_idc ue(v)
|
|
if (h->chroma_format_idc > 3)
|
|
{
|
|
log_print(HT_LOG_ERR, "%s, chroma_format_idc[%d]!!!\r\n",
|
|
__FUNCTION__, h->chroma_format_idc);
|
|
return -1;
|
|
}
|
|
|
|
if (h->chroma_format_idc == 3)
|
|
{
|
|
h->separate_colour_plane_flag = bs_read(&s, 1); // separate_colour_plane_flag
|
|
}
|
|
|
|
h->pic_width_in_luma_samples = bs_read_ue(&s); // pic_width_in_luma_samples ue(v)
|
|
h->pic_height_in_luma_samples = bs_read_ue(&s); // pic_height_in_luma_samples ue(v)
|
|
|
|
h->conformance_window_flag = bs_read(&s, 1 ); // conformance_window_flag u(1)
|
|
if (h->conformance_window_flag)
|
|
{
|
|
h->conf_win_left_offset = bs_read_ue(&s); // conf_win_left_offset ue(v)
|
|
h->conf_win_right_offset = bs_read_ue(&s); // conf_win_right_offset ue(v)
|
|
h->conf_win_top_offset = bs_read_ue(&s); // conf_win_top_offset ue(v)
|
|
h->conf_win_bottom_offset = bs_read_ue(&s); // conf_win_bottom_offset ue(v)
|
|
}
|
|
|
|
h->bit_depth_luma_minus8 = bs_read_ue(&s); // bit_depth_luma_minus8 ue(v)
|
|
h->bit_depth_chroma_minus8 = bs_read_ue(&s); // bit_depth_chroma_minus8 ue(v)
|
|
|
|
return 0;
|
|
}
|
|
|
|
void hvcc_init(HEVCDecoderConfigurationRecord * hvcc)
|
|
{
|
|
memset(hvcc, 0, sizeof(HEVCDecoderConfigurationRecord));
|
|
|
|
hvcc->lengthSizeMinusOne = 3; // 4 bytes
|
|
|
|
/*
|
|
* The following fields have all their valid bits set by default,
|
|
* the ProfileTierLevel parsing code will unset them when needed.
|
|
*/
|
|
hvcc->general_profile_compatibility_flags = 0xffffffff;
|
|
hvcc->general_constraint_indicator_flags = 0xffffffffffff;
|
|
|
|
/*
|
|
* Initialize this field with an invalid value which can be used to detect
|
|
* whether we didn't see any VUI (in which case it should be reset to zero).
|
|
*/
|
|
hvcc->min_spatial_segmentation_idc = MAX_SPATIAL_SEGMENTATION + 1;
|
|
}
|
|
|
|
int hvcc_parse_vps(HEVCDecoderConfigurationRecord * hvcc, uint8 * p_data, int len)
|
|
{
|
|
uint32 vps_max_sub_layers_minus1;
|
|
uint8 bufs[512];
|
|
bs_t s;
|
|
|
|
if (len > (int)sizeof(bufs))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
len = h265_extract_rbsp(p_data, len, bufs);
|
|
|
|
bs_init(&s, bufs, len);
|
|
|
|
/*
|
|
* vps_video_parameter_set_id u(4)
|
|
* vps_reserved_three_2bits u(2)
|
|
* vps_max_layers_minus1 u(6)
|
|
*/
|
|
bs_skip(&s, 12);
|
|
|
|
vps_max_sub_layers_minus1 = bs_read(&s, 3);
|
|
|
|
/*
|
|
* numTemporalLayers greater than 1 indicates that the stream to which this
|
|
* configuration record applies is temporally scalable and the contained
|
|
* number of temporal layers (also referred to as temporal sub-layer or
|
|
* sub-layer in ISO/IEC 23008-2) is equal to numTemporalLayers. Value 1
|
|
* indicates that the stream is not temporally scalable. Value 0 indicates
|
|
* that it is unknown whether the stream is temporally scalable.
|
|
*/
|
|
hvcc->numTemporalLayers = MAX(hvcc->numTemporalLayers, vps_max_sub_layers_minus1 + 1);
|
|
|
|
/*
|
|
* vps_temporal_id_nesting_flag u(1)
|
|
* vps_reserved_0xffff_16bits u(16)
|
|
*/
|
|
bs_skip(&s, 17);
|
|
|
|
uint8 profile_space;
|
|
uint8 tier_flag;
|
|
uint8 profile_idc;
|
|
uint32 profile_compatibility_flags;
|
|
uint64 constraint_indicator_flags;
|
|
uint8 level_idc;
|
|
|
|
profile_space = bs_read(&s, 2);
|
|
tier_flag = bs_read(&s, 1);
|
|
profile_idc = bs_read(&s, 5);
|
|
profile_compatibility_flags = bs_read(&s, 32);
|
|
constraint_indicator_flags = (uint64)bs_read(&s, 16) << 32;
|
|
constraint_indicator_flags |= bs_read(&s, 32);
|
|
level_idc = bs_read(&s, 8);
|
|
|
|
hvcc->general_profile_space = profile_space;
|
|
|
|
/*
|
|
* The level indication general_level_idc must indicate a level of
|
|
* capability equal to or greater than the highest level indicated for the
|
|
* highest tier in all the parameter sets.
|
|
*/
|
|
if (hvcc->general_tier_flag < tier_flag)
|
|
hvcc->general_level_idc = level_idc;
|
|
else
|
|
hvcc->general_level_idc = MAX(hvcc->general_level_idc, level_idc);
|
|
|
|
/*
|
|
* The tier indication general_tier_flag must indicate a tier equal to or
|
|
* greater than the highest tier indicated in all the parameter sets.
|
|
*/
|
|
hvcc->general_tier_flag = MAX(hvcc->general_tier_flag, tier_flag);
|
|
|
|
/*
|
|
* The profile indication general_profile_idc must indicate a profile to
|
|
* which the stream associated with this configuration record conforms.
|
|
*
|
|
* If the sequence parameter sets are marked with different profiles, then
|
|
* the stream may need examination to determine which profile, if any, the
|
|
* entire stream conforms to. If the entire stream is not examined, or the
|
|
* examination reveals that there is no profile to which the entire stream
|
|
* conforms, then the entire stream must be split into two or more
|
|
* sub-streams with separate configuration records in which these rules can
|
|
* be met.
|
|
*
|
|
* Note: set the profile to the highest value for the sake of simplicity.
|
|
*/
|
|
hvcc->general_profile_idc = MAX(hvcc->general_profile_idc, profile_idc);
|
|
|
|
/*
|
|
* Each bit in general_profile_compatibility_flags may only be set if all
|
|
* the parameter sets set that bit.
|
|
*/
|
|
hvcc->general_profile_compatibility_flags &= profile_compatibility_flags;
|
|
|
|
/*
|
|
* Each bit in general_constraint_indicator_flags may only be set if all
|
|
* the parameter sets set that bit.
|
|
*/
|
|
hvcc->general_constraint_indicator_flags &= constraint_indicator_flags;
|
|
|
|
/* nothing useful for hvcC past this point */
|
|
return 0;
|
|
}
|
|
|
|
int hvcc_parse_pps(HEVCDecoderConfigurationRecord * hvcc, uint8 * p_data, int len)
|
|
{
|
|
uint8 tiles_enabled_flag, entropy_coding_sync_enabled_flag;
|
|
uint8 bufs[512];
|
|
bs_t s;
|
|
|
|
if (len > (int)sizeof(bufs))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
len = h265_extract_rbsp(p_data, len, bufs);
|
|
|
|
bs_init(&s, bufs, len);
|
|
|
|
bs_read_ue(&s); // pps_pic_parameter_set_id
|
|
bs_read_ue(&s); // pps_seq_parameter_set_id
|
|
|
|
/*
|
|
* dependent_slice_segments_enabled_flag u(1)
|
|
* output_flag_present_flag u(1)
|
|
* num_extra_slice_header_bits u(3)
|
|
* sign_data_hiding_enabled_flag u(1)
|
|
* cabac_init_present_flag u(1)
|
|
*/
|
|
bs_skip(&s, 7);
|
|
|
|
bs_read_ue(&s); // num_ref_idx_l0_default_active_minus1
|
|
bs_read_ue(&s); // num_ref_idx_l1_default_active_minus1
|
|
bs_read_se(&s); // init_qp_minus26
|
|
|
|
/*
|
|
* constrained_intra_pred_flag u(1)
|
|
* transform_skip_enabled_flag u(1)
|
|
*/
|
|
bs_skip(&s, 2);
|
|
|
|
if (bs_read(&s, 1)) // cu_qp_delta_enabled_flag
|
|
bs_read_ue(&s); // diff_cu_qp_delta_depth
|
|
|
|
bs_read_se(&s); // pps_cb_qp_offset
|
|
bs_read_se(&s); // pps_cr_qp_offset
|
|
|
|
/*
|
|
* pps_slice_chroma_qp_offsets_present_flag u(1)
|
|
* weighted_pred_flag u(1)
|
|
* weighted_bipred_flag u(1)
|
|
* transquant_bypass_enabled_flag u(1)
|
|
*/
|
|
bs_skip(&s, 4);
|
|
|
|
tiles_enabled_flag = bs_read(&s, 1);
|
|
entropy_coding_sync_enabled_flag = bs_read(&s, 1);
|
|
|
|
if (entropy_coding_sync_enabled_flag && tiles_enabled_flag)
|
|
hvcc->parallelismType = 0; // mixed-type parallel decoding
|
|
else if (entropy_coding_sync_enabled_flag)
|
|
hvcc->parallelismType = 3; // wavefront-based parallel decoding
|
|
else if (tiles_enabled_flag)
|
|
hvcc->parallelismType = 2; // tile-based parallel decoding
|
|
else
|
|
hvcc->parallelismType = 1; // slice-based parallel decoding
|
|
|
|
/* nothing useful for hvcC past this point */
|
|
return 0;
|
|
}
|
|
|
|
|
|
|