Files
gb28181/GB28181Device/rtp/h265_util.cpp
2024-12-15 20:42:32 +08:00

220 lines
6.2 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-2022, 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 "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;
}
else if (i > length)
{
i = 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->sps_seq_parameter_set_id > 15 || h->chroma_format_idc > 3)
{
log_print(HT_LOG_ERR, "%s, sps_seq_parameter_set_id[%d],chroma_format_idc[%d]!!!\r\n", __FUNCTION__, h->sps_seq_parameter_set_id, 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;
}