/***************************************************************************************
|
|
***************************************************************************************/
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <string.h>
|
#include <stdint.h> /* for uint32_t, etc */
|
#include "sps_pps.h"
|
|
/* report level */
|
#define RPT_ERR (1) // error, system error
|
#define RPT_WRN (2) // warning, maybe wrong, maybe OK
|
#define RPT_INF (3) // important information
|
#define RPT_DBG (4) // debug information
|
|
static int rpt_lvl = RPT_WRN; /* report level: ERR, WRN, INF, DBG */
|
|
/* report micro */
|
#define RPT(lvl, ...) \
|
do { \
|
if(lvl <= rpt_lvl) { \
|
switch(lvl) { \
|
case RPT_ERR: \
|
fprintf(stderr, "\"%s\" line %d [err]: ", __FILE__, __LINE__); \
|
break; \
|
case RPT_WRN: \
|
fprintf(stderr, "\"%s\" line %d [wrn]: ", __FILE__, __LINE__); \
|
break; \
|
case RPT_INF: \
|
fprintf(stderr, "\"%s\" line %d [inf]: ", __FILE__, __LINE__); \
|
break; \
|
case RPT_DBG: \
|
fprintf(stderr, "\"%s\" line %d [dbg]: ", __FILE__, __LINE__); \
|
break; \
|
default: \
|
fprintf(stderr, "\"%s\" line %d [???]: ", __FILE__, __LINE__); \
|
break; \
|
} \
|
fprintf(stderr, __VA_ARGS__); \
|
fprintf(stderr, "\n"); \
|
} \
|
} while(0)
|
|
/********************************************
|
*define here
|
********************************************/
|
#define SPS_PPS_DEBUG
|
#undef SPS_PPS_DEBUG
|
|
#define MAX_LEN 32
|
|
|
/********************************************
|
*functions
|
********************************************/
|
/**
|
* @brief Function get_1bit() ¶Á1¸öbit
|
* @param[in] h get_bit_context structrue
|
* @retval 0: success, -1 : failure
|
* @pre
|
* @post
|
*/
|
static int get_1bit(void *h)
|
{
|
get_bit_context *ptr = (get_bit_context *)h;
|
int ret = 0;
|
uint8_t *cur_char = NULL;
|
uint8_t shift;
|
|
if(NULL == ptr)
|
{
|
RPT(RPT_ERR, "NULL pointer");
|
ret = -1;
|
goto exit;
|
}
|
|
cur_char = ptr->buf + (ptr->bit_pos >> 3);
|
shift = 7 - (ptr->cur_bit_pos);
|
ptr->bit_pos++;
|
ptr->cur_bit_pos = ptr->bit_pos & 0x7;
|
ret = ((*cur_char) >> shift) & 0x01;
|
|
exit:
|
return ret;
|
}
|
|
|
/**
|
* @brief Function get_bits() ¶Án¸öbits£¬n²»Äܳ¬¹ý32
|
* @param[in] h get_bit_context structrue
|
* @param[in] n how many bits you want?
|
* @retval 0: success, -1 : failure
|
* @pre
|
* @post
|
*/
|
static int get_bits(void *h, int n)
|
{
|
get_bit_context *ptr = (get_bit_context *)h;
|
uint8_t temp[5] = {0};
|
uint8_t *cur_char = NULL;
|
uint8_t nbyte;
|
uint8_t shift;
|
uint32_t result;
|
uint64_t ret = 0;
|
|
if(NULL == ptr)
|
{
|
RPT(RPT_ERR, "NULL pointer");
|
ret = -1;
|
goto exit;
|
}
|
|
if(n > MAX_LEN)
|
{
|
n = MAX_LEN;
|
}
|
|
if((ptr->bit_pos + n) > ptr->total_bit)
|
{
|
n = ptr->total_bit- ptr->bit_pos;
|
}
|
|
cur_char = ptr->buf+ (ptr->bit_pos>>3);
|
nbyte = (ptr->cur_bit_pos + n + 7) >> 3;
|
shift = (8 - (ptr->cur_bit_pos + n))& 0x07;
|
|
if(n == MAX_LEN)
|
{
|
RPT(RPT_DBG, "12(ptr->bit_pos(:%d) + n(:%d)) > ptr->total_bit(:%d)!!! ",\
|
ptr->bit_pos, n, ptr->total_bit);
|
RPT(RPT_DBG, "0x%x 0x%x 0x%x 0x%x", (*cur_char), *(cur_char+1),*(cur_char+2),*(cur_char+3));
|
}
|
|
memcpy(&temp[5-nbyte], cur_char, nbyte);
|
ret = (uint32_t)temp[0] << 24;
|
ret = ret << 8;
|
ret = ((uint32_t)temp[1]<<24)|((uint32_t)temp[2] << 16)\
|
|((uint32_t)temp[3] << 8)|temp[4];
|
|
ret = (ret >> shift) & (((uint64_t)1<<n) - 1);
|
|
result = ret;
|
ptr->bit_pos += n;
|
ptr->cur_bit_pos = ptr->bit_pos & 0x7;
|
|
exit:
|
return result;
|
}
|
|
|
/**
|
* @brief Function parse_codenum() Ö¸Êý¸çÂײ¼±àÂë½âÎö£¬²Î¿¼h264±ê×¼µÚ9½Ú
|
* @param[in] buf
|
* @retval code_num
|
* @pre
|
* @post
|
*/
|
static int parse_codenum(void *buf)
|
{
|
uint8_t leading_zero_bits = -1;
|
uint8_t b;
|
uint32_t code_num = 0;
|
|
for(b=0; !b; leading_zero_bits++)
|
{
|
b = get_1bit(buf);
|
}
|
|
code_num = ((uint32_t)1 << leading_zero_bits) - 1 + get_bits(buf, leading_zero_bits);
|
|
return code_num;
|
}
|
|
/**
|
* @brief Function parse_ue() Ö¸Êý¸çÂײ¼±àÂë½âÎö ue(),²Î¿¼h264±ê×¼µÚ9½Ú
|
* @param[in] buf sps_pps parse buf
|
* @retval code_num
|
* @pre
|
* @post
|
*/
|
static int parse_ue(void *buf)
|
{
|
return parse_codenum(buf);
|
}
|
|
|
/**
|
* @brief Function parse_se() Ö¸Êý¸çÂײ¼±àÂë½âÎö se(), ²Î¿¼h264±ê×¼µÚ9½Ú
|
* @param[in] buf sps_pps parse buf
|
* @retval code_num
|
* @pre
|
* @post
|
*/
|
static int parse_se(void *buf)
|
{
|
int ret = 0;
|
int code_num;
|
|
code_num = parse_codenum(buf);
|
ret = (code_num + 1) >> 1;
|
ret = (code_num & 0x01)? ret : -ret;
|
|
return ret;
|
}
|
|
|
/**
|
* @brief Function get_bit_context_free() ÉêÇëµÄget_bit_context½á¹¹ÄÚ´æÊÍ·Å
|
* @param[in] buf get_bit_context buf
|
* @retval none
|
* @pre
|
* @post
|
*/
|
static void get_bit_context_free(void *buf)
|
{
|
get_bit_context *ptr = (get_bit_context *)buf;
|
|
if(ptr)
|
{
|
if(ptr->buf)
|
{
|
free(ptr->buf);
|
}
|
|
free(ptr);
|
}
|
}
|
|
|
/**
|
* @brief Function de_emulation_prevention() ½â¾ºÕù´úÂë
|
* @param[in] buf get_bit_context buf
|
* @retval none
|
* @pre
|
* @post
|
* @note:
|
* µ÷ÊÔʱ×ÜÊÇ·¢ÏÖvui.time_scaleÖµÌØ±ðÆæ¹Ö£¬×ÜÊÇ16777216£¬ºóÀ´²éѯÔÒòÈçÏÂ:
|
* http://www.cnblogs.com/eustoma/archive/2012/02/13/2415764.html
|
* H.264±àÂëʱ£¬ÔÚÿ¸öNALǰÌí¼ÓÆðʼÂë 0x000001£¬½âÂëÆ÷ÔÚÂëÁ÷Öмì²âµ½ÆðʼÂ룬µ±Ç°NAL½áÊø¡£
|
* ΪÁË·ÀÖ¹NALÄÚ²¿³öÏÖ0x000001µÄÊý¾Ý£¬h.264ÓÖÌá³ö'·ÀÖ¹¾ºÕù emulation prevention"»úÖÆ£¬
|
* ÔÚ±àÂëÍêÒ»¸öNALʱ£¬Èç¹û¼ì²â³öÓÐÁ¬ÐøÁ½¸ö0x00×Ö½Ú£¬¾ÍÔÚºóÃæ²åÈëÒ»¸ö0x03¡£
|
* µ±½âÂëÆ÷ÔÚNALÄÚ²¿¼ì²âµ½0x000003µÄÊý¾Ý£¬¾Í°Ñ0x03Åׯú£¬»Ö¸´ÔʼÊý¾Ý¡£
|
* 0x000000 >>>>>> 0x00000300
|
* 0x000001 >>>>>> 0x00000301
|
* 0x000002 >>>>>> 0x00000302
|
* 0x000003 >>>>>> 0x00000303
|
*/
|
static void *de_emulation_prevention(void *buf)
|
{
|
get_bit_context *ptr = NULL;
|
get_bit_context *buf_ptr = (get_bit_context *)buf;
|
int i = 0, j = 0;
|
uint8_t *tmp_ptr = NULL;
|
int tmp_buf_size = 0;
|
int val = 0;
|
|
if(NULL == buf_ptr)
|
{
|
RPT(RPT_ERR, "NULL ptr");
|
goto exit;
|
}
|
|
ptr = (get_bit_context *)malloc(sizeof(get_bit_context));
|
if(NULL == ptr)
|
{
|
RPT(RPT_ERR, "NULL ptr");
|
goto exit;
|
}
|
|
memcpy(ptr, buf_ptr, sizeof(get_bit_context));
|
|
ptr->buf = (uint8_t *)malloc(ptr->buf_size);
|
if(NULL == ptr->buf)
|
{
|
RPT(RPT_ERR, "NULL ptr");
|
goto exit;
|
}
|
|
memcpy(ptr->buf, buf_ptr->buf, buf_ptr->buf_size);
|
|
tmp_ptr = ptr->buf;
|
tmp_buf_size = ptr->buf_size;
|
for(i=0; i<(tmp_buf_size-2); i++)
|
{
|
/*¼ì²â0x000003*/
|
val = (tmp_ptr[i]^0x00) + (tmp_ptr[i+1]^0x00) + (tmp_ptr[i+2]^0x03);
|
if(val == 0)
|
{
|
/*ÌÞ³ý0x03*/
|
for(j=i+2; j<tmp_buf_size-1; j++)
|
{
|
tmp_ptr[j] = tmp_ptr[j+1];
|
}
|
|
/*ÏàÓ¦µÄbufsizeÒª¼õС*/
|
ptr->buf_size--;
|
}
|
}
|
|
/*ÖØÐ¼ÆËãtotal_bit*/
|
ptr->total_bit = ptr->buf_size << 3;
|
|
return (void *)ptr;
|
|
exit:
|
get_bit_context_free(ptr);
|
return NULL;
|
}
|
|
|
/**
|
* @brief Function get_bit_context_free() VUI_parameters ½âÎö£¬ÔÀí²Î¿¼h264±ê×¼
|
* @param[in] buf get_bit_context buf
|
* @param[in] vui_ptr vui½âÎö½á¹û
|
* @retval 0: success, -1 : failure
|
* @pre
|
* @post
|
*/
|
static int vui_parameters_set(void *buf, vui_parameters_t *vui_ptr)
|
{
|
int ret = 0;
|
int SchedSelIdx = 0;
|
|
if(NULL == vui_ptr || NULL == buf)
|
{
|
RPT(RPT_ERR,"ERR null pointer\n");
|
ret = -1;
|
goto exit;
|
}
|
|
vui_ptr->aspect_ratio_info_present_flag = get_1bit(buf);
|
if(vui_ptr->aspect_ratio_info_present_flag)
|
{
|
vui_ptr->aspect_ratio_idc = get_bits(buf, 8);
|
if(vui_ptr->aspect_ratio_idc == Extended_SAR)
|
{
|
vui_ptr->sar_width = get_bits(buf, 16);
|
vui_ptr->sar_height = get_bits(buf, 16);
|
}
|
}
|
|
vui_ptr->overscan_info_present_flag = get_1bit(buf);
|
if(vui_ptr->overscan_info_present_flag)
|
{
|
vui_ptr->overscan_appropriate_flag = get_1bit(buf);
|
}
|
|
vui_ptr->video_signal_type_present_flag = get_1bit(buf);
|
if(vui_ptr->video_signal_type_present_flag)
|
{
|
vui_ptr->video_format = get_bits(buf, 3);
|
vui_ptr->video_full_range_flag = get_1bit(buf);
|
|
vui_ptr->colour_description_present_flag = get_1bit(buf);
|
if(vui_ptr->colour_description_present_flag)
|
{
|
vui_ptr->colour_primaries = get_bits(buf, 8);
|
vui_ptr->transfer_characteristics = get_bits(buf, 8);
|
vui_ptr->matrix_coefficients = get_bits(buf, 8);
|
}
|
}
|
|
vui_ptr->chroma_loc_info_present_flag = get_1bit(buf);
|
if(vui_ptr->chroma_loc_info_present_flag)
|
{
|
vui_ptr->chroma_sample_loc_type_top_field = parse_ue(buf);
|
vui_ptr->chroma_sample_loc_type_bottom_field = parse_ue(buf);
|
}
|
|
vui_ptr->timing_info_present_flag = get_1bit(buf);
|
if(vui_ptr->timing_info_present_flag)
|
{
|
vui_ptr->num_units_in_tick = get_bits(buf, 32);
|
vui_ptr->time_scale = get_bits(buf, 32);
|
vui_ptr->fixed_frame_rate_flag = get_1bit(buf);
|
}
|
|
vui_ptr->nal_hrd_parameters_present_flag = get_1bit(buf);
|
if(vui_ptr->nal_hrd_parameters_present_flag)
|
{
|
vui_ptr->cpb_cnt_minus1 = parse_ue(buf);
|
vui_ptr->bit_rate_scale = get_bits(buf, 4);
|
vui_ptr->cpb_size_scale = get_bits(buf, 4);
|
|
for(SchedSelIdx=0; SchedSelIdx<=vui_ptr->cpb_cnt_minus1; SchedSelIdx++)
|
{
|
vui_ptr->bit_rate_value_minus1[SchedSelIdx] = parse_ue(buf);
|
vui_ptr->cpb_size_value_minus1[SchedSelIdx] = parse_ue(buf);
|
vui_ptr->cbr_flag[SchedSelIdx] = get_1bit(buf);
|
}
|
|
vui_ptr->initial_cpb_removal_delay_length_minus1 = get_bits(buf, 5);
|
vui_ptr->cpb_removal_delay_length_minus1 = get_bits(buf, 5);
|
vui_ptr->dpb_output_delay_length_minus1 = get_bits(buf, 5);
|
vui_ptr->time_offset_length = get_bits(buf, 5);
|
}
|
|
|
vui_ptr->vcl_hrd_parameters_present_flag = get_1bit(buf);
|
if(vui_ptr->vcl_hrd_parameters_present_flag)
|
{
|
vui_ptr->cpb_cnt_minus1 = parse_ue(buf);
|
vui_ptr->bit_rate_scale = get_bits(buf, 4);
|
vui_ptr->cpb_size_scale = get_bits(buf, 4);
|
|
for(SchedSelIdx=0; SchedSelIdx<=vui_ptr->cpb_cnt_minus1; SchedSelIdx++)
|
{
|
vui_ptr->bit_rate_value_minus1[SchedSelIdx] = parse_ue(buf);
|
vui_ptr->cpb_size_value_minus1[SchedSelIdx] = parse_ue(buf);
|
vui_ptr->cbr_flag[SchedSelIdx] = get_1bit(buf);
|
}
|
|
vui_ptr->initial_cpb_removal_delay_length_minus1 = get_bits(buf, 5);
|
vui_ptr->cpb_removal_delay_length_minus1 = get_bits(buf, 5);
|
vui_ptr->dpb_output_delay_length_minus1 = get_bits(buf, 5);
|
vui_ptr->time_offset_length = get_bits(buf, 5);
|
}
|
|
if(vui_ptr->nal_hrd_parameters_present_flag \
|
|| vui_ptr->vcl_hrd_parameters_present_flag)
|
{
|
vui_ptr->low_delay_hrd_flag = get_1bit(buf);
|
}
|
|
vui_ptr->pic_struct_present_flag = get_1bit(buf);
|
|
vui_ptr->bitstream_restriction_flag = get_1bit(buf);
|
if(vui_ptr->bitstream_restriction_flag)
|
{
|
vui_ptr->motion_vectors_over_pic_boundaries_flag = get_1bit(buf);
|
vui_ptr->max_bytes_per_pic_denom = parse_ue(buf);
|
vui_ptr->max_bits_per_mb_denom = parse_ue(buf);
|
vui_ptr->log2_max_mv_length_horizontal= parse_ue(buf);
|
vui_ptr->log2_max_mv_length_vertical = parse_ue(buf);
|
vui_ptr->num_reorder_frames = parse_ue(buf);
|
vui_ptr->max_dec_frame_buffering = parse_ue(buf);
|
}
|
|
exit:
|
return ret;
|
}
|
|
|
/**
|
* @brief Function sps_info_print() µ÷ÊÔÐÅÏ¢´òÓ¡
|
* @param[in] sps_ptr spsÐÅÏ¢½á¹¹ÌåÖ¸Õë
|
* @retval
|
* @pre
|
* @post
|
*/
|
#ifdef SPS_PPS_DEBUG
|
/*SPS ÐÅÏ¢´òÓ¡£¬µ÷ÊÔʹÓÃ*/
|
static void sps_info_print(SPS* sps_ptr)
|
{
|
if(NULL != sps_ptr)
|
{
|
RPT(RPT_DBG, "profile_idc: %d", sps_ptr->profile_idc);
|
RPT(RPT_DBG, "constraint_set0_flag: %d", sps_ptr->constraint_set0_flag);
|
RPT(RPT_DBG, "constraint_set1_flag: %d", sps_ptr->constraint_set1_flag);
|
RPT(RPT_DBG, "constraint_set2_flag: %d", sps_ptr->constraint_set2_flag);
|
RPT(RPT_DBG, "constraint_set3_flag: %d", sps_ptr->constraint_set3_flag);
|
RPT(RPT_DBG, "reserved_zero_4bits: %d", sps_ptr->reserved_zero_4bits);
|
RPT(RPT_DBG, "level_idc: %d", sps_ptr->level_idc);
|
RPT(RPT_DBG, "seq_parameter_set_id: %d", sps_ptr->seq_parameter_set_id);
|
RPT(RPT_DBG, "chroma_format_idc: %d", sps_ptr->chroma_format_idc);
|
RPT(RPT_DBG, "separate_colour_plane_flag: %d", sps_ptr->separate_colour_plane_flag);
|
RPT(RPT_DBG, "bit_depth_luma_minus8: %d", sps_ptr->bit_depth_luma_minus8);
|
RPT(RPT_DBG, "bit_depth_chroma_minus8: %d", sps_ptr->bit_depth_chroma_minus8);
|
RPT(RPT_DBG, "qpprime_y_zero_transform_bypass_flag: %d", sps_ptr->qpprime_y_zero_transform_bypass_flag);
|
RPT(RPT_DBG, "seq_scaling_matrix_present_flag: %d", sps_ptr->seq_scaling_matrix_present_flag);
|
//RPT(RPT_INF, "seq_scaling_list_present_flag:%d", sps_ptr->seq_scaling_list_present_flag);
|
RPT(RPT_DBG, "log2_max_frame_num_minus4: %d", sps_ptr->log2_max_frame_num_minus4);
|
RPT(RPT_DBG, "pic_order_cnt_type: %d", sps_ptr->pic_order_cnt_type);
|
RPT(RPT_DBG, "num_ref_frames: %d", sps_ptr->num_ref_frames);
|
RPT(RPT_DBG, "gaps_in_frame_num_value_allowed_flag: %d", sps_ptr->gaps_in_frame_num_value_allowed_flag);
|
RPT(RPT_DBG, "pic_width_in_mbs_minus1: %d", sps_ptr->pic_width_in_mbs_minus1);
|
RPT(RPT_DBG, "pic_height_in_map_units_minus1: %d", sps_ptr->pic_height_in_map_units_minus1);
|
RPT(RPT_DBG, "frame_mbs_only_flag: %d", sps_ptr->frame_mbs_only_flag);
|
RPT(RPT_DBG, "mb_adaptive_frame_field_flag: %d", sps_ptr->mb_adaptive_frame_field_flag);
|
RPT(RPT_DBG, "direct_8x8_inference_flag: %d", sps_ptr->direct_8x8_inference_flag);
|
RPT(RPT_DBG, "frame_cropping_flag: %d", sps_ptr->frame_cropping_flag);
|
RPT(RPT_DBG, "frame_crop_left_offset: %d", sps_ptr->frame_crop_left_offset);
|
RPT(RPT_DBG, "frame_crop_right_offset: %d", sps_ptr->frame_crop_right_offset);
|
RPT(RPT_DBG, "frame_crop_top_offset: %d", sps_ptr->frame_crop_top_offset);
|
RPT(RPT_DBG, "frame_crop_bottom_offset: %d", sps_ptr->frame_crop_bottom_offset);
|
RPT(RPT_DBG, "vui_parameters_present_flag: %d", sps_ptr->vui_parameters_present_flag);
|
|
if(sps_ptr->vui_parameters_present_flag)
|
{
|
RPT(RPT_DBG, "aspect_ratio_info_present_flag: %d", sps_ptr->vui_parameters.aspect_ratio_info_present_flag);
|
RPT(RPT_DBG, "aspect_ratio_idc: %d", sps_ptr->vui_parameters.aspect_ratio_idc);
|
RPT(RPT_DBG, "sar_width: %d", sps_ptr->vui_parameters.sar_width);
|
RPT(RPT_DBG, "sar_height: %d", sps_ptr->vui_parameters.sar_height);
|
RPT(RPT_DBG, "overscan_info_present_flag: %d", sps_ptr->vui_parameters.overscan_info_present_flag);
|
RPT(RPT_DBG, "overscan_info_appropriate_flag: %d", sps_ptr->vui_parameters.overscan_appropriate_flag);
|
RPT(RPT_DBG, "video_signal_type_present_flag: %d", sps_ptr->vui_parameters.video_signal_type_present_flag);
|
RPT(RPT_DBG, "video_format: %d", sps_ptr->vui_parameters.video_format);
|
RPT(RPT_DBG, "video_full_range_flag: %d", sps_ptr->vui_parameters.video_full_range_flag);
|
RPT(RPT_DBG, "colour_description_present_flag: %d", sps_ptr->vui_parameters.colour_description_present_flag);
|
RPT(RPT_DBG, "colour_primaries: %d", sps_ptr->vui_parameters.colour_primaries);
|
RPT(RPT_DBG, "transfer_characteristics: %d", sps_ptr->vui_parameters.transfer_characteristics);
|
RPT(RPT_DBG, "matrix_coefficients: %d", sps_ptr->vui_parameters.matrix_coefficients);
|
RPT(RPT_DBG, "chroma_loc_info_present_flag: %d", sps_ptr->vui_parameters.chroma_loc_info_present_flag);
|
RPT(RPT_DBG, "chroma_sample_loc_type_top_field: %d", sps_ptr->vui_parameters.chroma_sample_loc_type_top_field);
|
RPT(RPT_DBG, "chroma_sample_loc_type_bottom_field: %d", sps_ptr->vui_parameters.chroma_sample_loc_type_bottom_field);
|
RPT(RPT_DBG, "timing_info_present_flag: %d", sps_ptr->vui_parameters.timing_info_present_flag);
|
RPT(RPT_DBG, "num_units_in_tick: %d", sps_ptr->vui_parameters.num_units_in_tick);
|
RPT(RPT_DBG, "time_scale: %d", sps_ptr->vui_parameters.time_scale);
|
RPT(RPT_DBG, "fixed_frame_rate_flag: %d", sps_ptr->vui_parameters.fixed_frame_rate_flag);
|
RPT(RPT_DBG, "nal_hrd_parameters_present_flag: %d", sps_ptr->vui_parameters.nal_hrd_parameters_present_flag);
|
RPT(RPT_DBG, "cpb_cnt_minus1: %d", sps_ptr->vui_parameters.cpb_cnt_minus1);
|
RPT(RPT_DBG, "bit_rate_scale: %d", sps_ptr->vui_parameters.bit_rate_scale);
|
RPT(RPT_DBG, "cpb_size_scale: %d", sps_ptr->vui_parameters.cpb_size_scale);
|
RPT(RPT_DBG, "initial_cpb_removal_delay_length_minus1: %d", sps_ptr->vui_parameters.initial_cpb_removal_delay_length_minus1);
|
RPT(RPT_DBG, "cpb_removal_delay_length_minus1: %d", sps_ptr->vui_parameters.cpb_removal_delay_length_minus1);
|
RPT(RPT_DBG, "dpb_output_delay_length_minus1: %d", sps_ptr->vui_parameters.dpb_output_delay_length_minus1);
|
RPT(RPT_DBG, "time_offset_length: %d", sps_ptr->vui_parameters.time_offset_length);
|
RPT(RPT_DBG, "vcl_hrd_parameters_present_flag: %d", sps_ptr->vui_parameters.vcl_hrd_parameters_present_flag);
|
RPT(RPT_DBG, "low_delay_hrd_flag: %d", sps_ptr->vui_parameters.low_delay_hrd_flag);
|
RPT(RPT_DBG, "pic_struct_present_flag: %d", sps_ptr->vui_parameters.pic_struct_present_flag);
|
RPT(RPT_DBG, "bitstream_restriction_flag: %d", sps_ptr->vui_parameters.bitstream_restriction_flag);
|
RPT(RPT_DBG, "motion_vectors_over_pic_boundaries_flag: %d", sps_ptr->vui_parameters.motion_vectors_over_pic_boundaries_flag);
|
RPT(RPT_DBG, "max_bytes_per_pic_denom: %d", sps_ptr->vui_parameters.max_bytes_per_pic_denom);
|
RPT(RPT_DBG, "max_bits_per_mb_denom: %d", sps_ptr->vui_parameters.max_bits_per_mb_denom);
|
RPT(RPT_DBG, "log2_max_mv_length_horizontal: %d", sps_ptr->vui_parameters.log2_max_mv_length_horizontal);
|
RPT(RPT_DBG, "log2_max_mv_length_vertical: %d", sps_ptr->vui_parameters.log2_max_mv_length_vertical);
|
RPT(RPT_DBG, "num_reorder_frames: %d", sps_ptr->vui_parameters.num_reorder_frames);
|
RPT(RPT_DBG, "max_dec_frame_buffering: %d", sps_ptr->vui_parameters.max_dec_frame_buffering);
|
}
|
|
}
|
}
|
#endif
|
|
int h265dec_seq_parameter_set(void *buf_ptr, int* width,int* height)
|
{
|
int ret = 0;
|
//int profile_idc = 0;
|
unsigned i;
|
void *buf = NULL;
|
|
unsigned sps_video_parameter_set_id = 0;
|
unsigned sps_max_sub_layers_minus1 = 0;
|
unsigned sps_temporal_id_nesting_flag = 0;
|
unsigned sps_seq_parameter_set_id = 0;
|
unsigned chroma_format_idc = 0;
|
unsigned pic_width_in_luma_samples = 0;
|
unsigned pic_height_in_luma_samples = 0;
|
bool sub_layer_profile_present_flag[7], sub_layer_level_present_flag[7];
|
|
if(NULL == buf_ptr)
|
{
|
RPT(RPT_ERR,"ERR null pointer\n");
|
ret = -1;
|
goto exit;
|
}
|
|
buf = de_emulation_prevention(buf_ptr);
|
if(NULL == buf)
|
{
|
RPT(RPT_ERR,"ERR null pointer\n");
|
ret = -1;
|
goto exit;
|
}
|
|
sps_video_parameter_set_id = get_bits(buf, 4);//sps_video_parameter_set_id
|
sps_max_sub_layers_minus1 = get_bits(buf, 3);//sps_max_sub_layers_minus1
|
sps_temporal_id_nesting_flag = get_1bit(buf);//sps_temporal_id_nesting_flag
|
get_bits(buf,32);
|
get_bits(buf,32);
|
get_bits(buf,32);
|
|
for (i = 0; i < sps_max_sub_layers_minus1; ++i)
|
{
|
sub_layer_profile_present_flag[i] = get_1bit(buf);
|
sub_layer_level_present_flag[i] = get_1bit(buf);
|
}
|
if (sps_max_sub_layers_minus1 > 0)
|
{
|
get_bits(buf,2*(8-sps_max_sub_layers_minus1)); // reserved_zero_2bits
|
}
|
for (i = 0; i < sps_max_sub_layers_minus1; ++i)
|
{
|
if (sub_layer_profile_present_flag[i])
|
{
|
get_bits(buf,32);
|
get_bits(buf,32);
|
get_bits(buf,24);
|
}
|
if (sub_layer_level_present_flag[i])
|
{
|
get_bits(buf,8); // sub_layer_level_idc[i]
|
}
|
}
|
|
sps_seq_parameter_set_id = parse_ue(buf); // sps_seq_parameter_set_id
|
chroma_format_idc = parse_ue(buf);
|
if (chroma_format_idc == 3)
|
get_1bit(buf); // separate_colour_plane_flag
|
pic_width_in_luma_samples = parse_ue(buf);
|
pic_height_in_luma_samples = parse_ue(buf);
|
|
*width = pic_width_in_luma_samples;
|
*height = pic_height_in_luma_samples;
|
|
exit:
|
get_bit_context_free(buf);
|
return ret;
|
|
}
|
|
|
|
/**
|
* @brief Function h264dec_seq_parameter_set() h264 SPS infomation ½âÎö
|
* @param[in] buf buf ptr, Ðèͬ²½00 00 00 01 X7ºó´«Èë
|
* @param[in] sps_ptr spsÖ¸Õ룬±£´æSPSÐÅÏ¢
|
* @retval 0: success, -1 : failure
|
* @pre
|
* @post
|
*/
|
int h264dec_seq_parameter_set(void *buf_ptr, SPS *sps_ptr)
|
{
|
SPS *sps = sps_ptr;
|
int ret = 0;
|
int profile_idc = 0;
|
int i,j;
|
void *buf = NULL;
|
|
if(NULL == buf_ptr || NULL == sps)
|
{
|
RPT(RPT_ERR,"ERR null pointer\n");
|
ret = -1;
|
goto exit;
|
}
|
|
memset((void *)sps, 0, sizeof(SPS));
|
|
buf = de_emulation_prevention(buf_ptr);
|
if(NULL == buf)
|
{
|
RPT(RPT_ERR,"ERR null pointer\n");
|
ret = -1;
|
goto exit;
|
}
|
|
sps->profile_idc = get_bits(buf, 8);
|
sps->constraint_set0_flag = get_1bit(buf);
|
sps->constraint_set1_flag = get_1bit(buf);
|
sps->constraint_set2_flag = get_1bit(buf);
|
sps->constraint_set3_flag = get_1bit(buf);
|
sps->reserved_zero_4bits = get_bits(buf, 4);
|
sps->level_idc = get_bits(buf, 8);
|
sps->seq_parameter_set_id = parse_ue(buf);
|
|
profile_idc = sps->profile_idc;
|
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))
|
{
|
sps->chroma_format_idc = parse_ue(buf);
|
if(sps->chroma_format_idc == 3)
|
{
|
sps->separate_colour_plane_flag = get_1bit(buf);
|
}
|
|
sps->bit_depth_luma_minus8 = parse_ue(buf);
|
sps->bit_depth_chroma_minus8 = parse_ue(buf);
|
sps->qpprime_y_zero_transform_bypass_flag = get_1bit(buf);
|
|
sps->seq_scaling_matrix_present_flag = get_1bit(buf);
|
if(sps->seq_scaling_matrix_present_flag)
|
{
|
for(i = 0;i<8;i++)
|
{
|
if(get_1bit(buf))
|
{
|
int last =8,next = 8,size = (i<6)?16:64;
|
for(j = 0;j<size;j++)
|
{
|
if(next)
|
{
|
next = (last + parse_se(buf))&0xff;
|
last = next?next:last;
|
}
|
}
|
}
|
}
|
|
//for(i=0; i<((sps->chroma_format_idc != 3)?8:12); i++)
|
//{
|
// sps->seq_scaling_list_present_flag[i] = get_1bit(buf);
|
// if(sps->seq_scaling_list_present_flag[i])
|
// {
|
// if(i<6)
|
// {
|
// for(j=0; j<16; j++)
|
// {
|
// last_scale = 8;
|
// next_scale = 8;
|
// if(next_scale != 0)
|
// {
|
// delta_scale = parse_se(buf);
|
// next_scale = (last_scale + delta_scale + 256)%256;
|
// sps->UseDefaultScalingMatrix4x4Flag[i] = ((j == 0) && (next_scale == 0));
|
// }
|
// sps->ScalingList4x4[i][j] = (next_scale == 0)?last_scale:next_scale;
|
// last_scale = sps->ScalingList4x4[i][j];
|
// }
|
// }
|
// else
|
// {
|
// int ii = i-6;
|
// next_scale = 8;
|
// last_scale = 8;
|
// for(j=0; j<64; j++)
|
// {
|
// if(next_scale != 0)
|
// {
|
// delta_scale = parse_se(buf);
|
// next_scale = (last_scale + delta_scale + 256)%256;
|
// sps->UseDefaultScalingMatrix8x8Flag[ii] = ((j == 0) && (next_scale == 0));
|
// }
|
// sps->ScalingList8x8[ii][j] = (next_scale == 0)?last_scale:next_scale;
|
// last_scale = sps->ScalingList8x8[ii][j];
|
// }
|
// }
|
// }
|
//}
|
}
|
}
|
|
sps->log2_max_frame_num_minus4 = parse_ue(buf);
|
sps->pic_order_cnt_type = parse_ue(buf);
|
if(sps->pic_order_cnt_type == 0)
|
{
|
sps->log2_max_pic_order_cnt_lsb_minus4 = parse_ue(buf);
|
}
|
else if(sps->pic_order_cnt_type == 1)
|
{
|
sps->delta_pic_order_always_zero_flag = get_1bit(buf);
|
sps->offset_for_non_ref_pic = parse_se(buf);
|
sps->offset_for_top_to_bottom_field = parse_se(buf);
|
|
sps->num_ref_frames_in_pic_order_cnt_cycle = parse_ue(buf);
|
for(i=0; i<sps->num_ref_frames_in_pic_order_cnt_cycle; i++)
|
{
|
sps->offset_for_ref_frame_array[i] = parse_se(buf);
|
}
|
}
|
|
sps->num_ref_frames = parse_ue(buf);
|
sps->gaps_in_frame_num_value_allowed_flag = get_1bit(buf);
|
sps->pic_width_in_mbs_minus1 = parse_ue(buf);
|
sps->pic_height_in_map_units_minus1 = parse_ue(buf);
|
|
sps->frame_mbs_only_flag = get_1bit(buf);
|
if(!sps->frame_mbs_only_flag)
|
{
|
sps->mb_adaptive_frame_field_flag = get_1bit(buf);
|
}
|
|
sps->direct_8x8_inference_flag = get_1bit(buf);
|
|
sps->frame_cropping_flag = get_1bit(buf);
|
if(sps->frame_cropping_flag)
|
{
|
sps->frame_crop_left_offset = parse_ue(buf);
|
sps->frame_crop_right_offset = parse_ue(buf);
|
sps->frame_crop_top_offset = parse_ue(buf);
|
sps->frame_crop_bottom_offset = parse_ue(buf);
|
}
|
|
sps->vui_parameters_present_flag = get_1bit(buf);
|
if(sps->vui_parameters_present_flag)
|
{
|
vui_parameters_set(buf, &sps->vui_parameters);
|
}
|
|
#ifdef SPS_PPS_DEBUG
|
sps_info_print(sps);
|
#endif
|
|
exit:
|
get_bit_context_free(buf);
|
return ret;
|
}
|
|
|
/**
|
* @brief Function more_rbsp_data() ¼ÆËãpps´®×îºóÒ»¸öΪ1µÄ±ÈÌØÎ»¼°Æäºó¶¼ÊDZÈÌØ0µÄ¸öÊý
|
* @param[in] buf get_bit_context structure
|
* @retval
|
* @pre
|
* @post
|
* @note Õâ¶Î´úÂëÀ´×ÔÍøÓѵİïÖú£¬²¢Ã»ÓÐÑéÖ¤£¬Ê¹ÓÃʱÐè×¢Òâ
|
*/
|
static int more_rbsp_data(void *buf)
|
{
|
get_bit_context *ptr = (get_bit_context *)buf;
|
get_bit_context tmp;
|
|
if(NULL == buf)
|
{
|
RPT(RPT_ERR, "NULL pointer, err");
|
return -1;
|
}
|
|
memset(&tmp, 0, sizeof(get_bit_context));
|
memcpy(&tmp, ptr, sizeof(get_bit_context));
|
|
for(tmp.bit_pos = ptr->total_bit - 1;tmp.bit_pos > ptr->bit_pos;tmp.bit_pos -= 2)
|
{
|
if(get_1bit(&tmp))
|
{
|
break;
|
}
|
}
|
|
return tmp.bit_pos == ptr->bit_pos? 0:1;
|
}
|
|
|
/**
|
* @brief Function h264dec_picture_parameter_set() h264 PPS infomation ½âÎö
|
* @param[in] buf buf ptr, Ðèͬ²½00 00 00 01 X8ºó´«Èë
|
* @param[in] pps_ptr ppsÖ¸Õ룬±£´æppsÐÅÏ¢
|
* @retval 0: success, -1 : failure
|
* @pre
|
* @post
|
*/
|
int h264dec_picture_parameter_set(void *buf_ptr, PPS *pps_ptr)
|
{
|
PPS *pps = pps_ptr;
|
int ret = 0;
|
void *buf = NULL;
|
int iGroup = 0;
|
int i,j,last_scale, next_scale, delta_scale;
|
|
if(NULL == buf_ptr || NULL == pps_ptr)
|
{
|
RPT(RPT_ERR, "NULL pointer\n");
|
ret = -1;
|
goto exit;
|
}
|
|
memset((void *)pps, 0, sizeof(PPS));
|
|
buf = de_emulation_prevention(buf_ptr);
|
if(NULL == buf)
|
{
|
RPT(RPT_ERR,"ERR null pointer\n");
|
ret = -1;
|
goto exit;
|
}
|
|
pps->pic_parameter_set_id = parse_ue(buf);
|
pps->seq_parameter_set_id = parse_ue(buf);
|
pps->entropy_coding_mode_flag = get_1bit(buf);
|
pps->pic_order_present_flag = get_1bit(buf);
|
|
pps->num_slice_groups_minus1 = parse_ue(buf);
|
if(pps->num_slice_groups_minus1 > 0)
|
{
|
pps->slice_group_map_type = parse_ue(buf);
|
if(pps->slice_group_map_type == 0)
|
{
|
for(iGroup=0; iGroup<=pps->num_slice_groups_minus1; iGroup++)
|
{
|
pps->run_length_minus1[iGroup] = parse_ue(buf);
|
}
|
}
|
else if(pps->slice_group_map_type == 2)
|
{
|
for(iGroup=0; iGroup<=pps->num_slice_groups_minus1; iGroup++)
|
{
|
pps->top_left[iGroup] = parse_ue(buf);
|
pps->bottom_right[iGroup] = parse_ue(buf);
|
}
|
}
|
else if(pps->slice_group_map_type == 3 \
|
||pps->slice_group_map_type == 4\
|
||pps->slice_group_map_type == 5)
|
{
|
pps->slice_group_change_direction_flag = get_1bit(buf);
|
pps->slice_group_change_rate_minus1 = parse_ue(buf);
|
}
|
else if(pps->slice_group_map_type == 6)
|
{
|
pps->pic_size_in_map_units_minus1 = parse_ue(buf);
|
for(i=0; i<pps->pic_size_in_map_units_minus1; i++)
|
{
|
/*ÕâµØ·½¿ÉÄÜÓÐÎÊÌ⣬¶Ôu(v)Àí½âÆ«²î*/
|
pps->slice_group_id[i] = get_bits(buf, pps->pic_size_in_map_units_minus1);
|
}
|
}
|
}
|
|
pps->num_ref_idx_10_active_minus1 = parse_ue(buf);
|
pps->num_ref_idx_11_active_minus1 = parse_ue(buf);
|
pps->weighted_pred_flag = get_1bit(buf);
|
pps->weighted_bipred_idc = get_bits(buf, 2);
|
pps->pic_init_qp_minus26 = parse_se(buf); /*relative26*/
|
pps->pic_init_qs_minus26 = parse_se(buf); /*relative26*/
|
pps->chroma_qp_index_offset = parse_se(buf);
|
pps->deblocking_filter_control_present_flag = get_1bit(buf);
|
pps->constrained_intra_pred_flag = get_1bit(buf);
|
pps->redundant_pic_cnt_present_flag = get_1bit(buf);
|
|
if(more_rbsp_data(buf))
|
{
|
pps->transform_8x8_mode_flag = get_1bit(buf);
|
pps->pic_scaling_matrix_present_flag = get_1bit(buf);
|
if(pps->pic_scaling_matrix_present_flag)
|
{
|
for(i=0; i<6+2*pps->transform_8x8_mode_flag; i++)
|
{
|
pps->pic_scaling_list_present_flag[i] = get_1bit(buf);
|
if(pps->pic_scaling_list_present_flag[i])
|
{
|
if(i<6)
|
{
|
for(j=0; j<16; j++)
|
{
|
next_scale = 8;
|
last_scale = 8;
|
if(next_scale != 0)
|
{
|
delta_scale = parse_se(buf);
|
next_scale = (last_scale + delta_scale + 256)%256;
|
pps->UseDefaultScalingMatrix4x4Flag[i] = ((j == 0) && (next_scale == 0));
|
}
|
pps->ScalingList4x4[i][j] = (next_scale == 0)?last_scale:next_scale;
|
last_scale = pps->ScalingList4x4[i][j];
|
}
|
}
|
else
|
{
|
int ii = i-6;
|
next_scale = 8;
|
last_scale = 8;
|
for(j=0; j<64; j++)
|
{
|
if(next_scale != 0)
|
{
|
delta_scale = parse_se(buf);
|
next_scale = (last_scale + delta_scale + 256)%256;
|
pps->UseDefaultScalingMatrix8x8Flag[ii] = ((j == 0) && (next_scale == 0));
|
}
|
pps->ScalingList8x8[ii][j] = (next_scale == 0)?last_scale:next_scale;
|
last_scale = pps->ScalingList8x8[ii][j];
|
}
|
}
|
}
|
}
|
|
pps->second_chroma_qp_index_offset = parse_se(buf);
|
}
|
}
|
|
exit:
|
get_bit_context_free(buf);
|
return ret;
|
}
|
|
|
// calculation width height and framerate
|
int h264_get_width(SPS *sps_ptr)
|
{
|
return (sps_ptr->pic_width_in_mbs_minus1 + 1) * 16;
|
}
|
|
int h264_get_height(SPS *sps_ptr)
|
{
|
return (sps_ptr->pic_height_in_map_units_minus1 + 1) * 16 * (2 - sps_ptr->frame_mbs_only_flag);
|
}
|
|
int h264_get_format(SPS *sps_ptr)
|
{
|
return sps_ptr->frame_mbs_only_flag;
|
}
|
|
|
/*
|
1 - 23.98
|
2 - 24
|
3 - 25
|
4 - 29.97
|
5 - 30
|
6 - 50
|
7 - 59.94
|
8 - 60
|
9 - 6
|
10 - 8
|
11 - 12
|
12 - 15
|
13 - 10.
|
*/
|
int h264_get_framerate(float *framerate,SPS *sps_ptr)
|
{
|
int fr;
|
int fr_int;
|
if(sps_ptr->vui_parameters.timing_info_present_flag)
|
{
|
if(sps_ptr->vui_parameters.num_units_in_tick == 0 || sps_ptr->vui_parameters.time_scale == 0)
|
{
|
*framerate = 25.0;
|
return 3;
|
}
|
|
if(sps_ptr->frame_mbs_only_flag == 0 && sps_ptr->vui_parameters.fixed_frame_rate_flag == 1)
|
{
|
*framerate = (float)sps_ptr->vui_parameters.time_scale / (float)sps_ptr->vui_parameters.num_units_in_tick/2.0;
|
//fr_int = sps_ptr->vui_parameters.time_scale / sps_ptr->vui_parameters.num_units_in_tick / 2;
|
}
|
else if(sps_ptr->frame_mbs_only_flag == 1)
|
{
|
*framerate = (float)sps_ptr->vui_parameters.time_scale / (float)sps_ptr->vui_parameters.num_units_in_tick/2.0;
|
//fr_int = sps_ptr->vui_parameters.time_scale / sps_ptr->vui_parameters.num_units_in_tick / 2;
|
}
|
else
|
{
|
*framerate = (float)sps_ptr->vui_parameters.time_scale / (float)sps_ptr->vui_parameters.num_units_in_tick;
|
//fr_int = sps_ptr->vui_parameters.time_scale / sps_ptr->vui_parameters.num_units_in_tick;
|
}
|
fr_int = sps_ptr->vui_parameters.time_scale / sps_ptr->vui_parameters.num_units_in_tick / 2;
|
}
|
else
|
{
|
*framerate = 25.0;
|
return 3;
|
}
|
|
switch(fr_int)
|
{
|
case 23:// 23.98
|
fr = 1;
|
break;
|
case 24:
|
fr = 2;
|
break;
|
case 25:
|
fr = 3;
|
break;
|
case 29://29.97
|
fr = 4;
|
break;
|
case 30:
|
fr = 5;
|
break;
|
case 50:
|
fr = 6;
|
break;
|
case 59://59.94
|
fr = 7;
|
break;
|
case 60:
|
fr = 8;
|
break;
|
case 6:
|
fr = 10;
|
break;
|
case 8:
|
fr = 11;
|
break;
|
case 12:
|
fr = 12;
|
break;
|
case 15:
|
fr = 13;
|
break;
|
case 10:
|
fr = 14;
|
break;
|
|
default:
|
fr = 0;
|
break;
|
}
|
|
return fr;
|
}
|
|
|
// for mpeg-2
|
void memcpy_sps_data(uint8_t *dst,uint8_t *src,int len)
|
{
|
int tmp;
|
for(tmp = 0; tmp < len; tmp++)
|
{
|
//printf("0x%02x ", src[tmp]);
|
dst[(tmp/4)*4+(3 - (tmp % 4))] = src[tmp];
|
}
|
}
|
/*_*/
|
|
//////////////////////////////////////////////////////////
|
|
//H264
|
bool inline is_sps_header(slice_header_t* sps)
|
{
|
if(sps->start_code_prefix[0] == 0 && sps->start_code_prefix[1] == 0 && sps->start_code_prefix[2] == 0 && sps->start_code_prefix[3] == 1 && ((sps->start_code_prefix[4]&0x1f) == 7))
|
return true;
|
return false;
|
}
|
bool inline is_pps_header(slice_header_t* pps)
|
{
|
if(pps->start_code_prefix[0] == 0 && pps->start_code_prefix[1] == 0 && pps->start_code_prefix[2] == 0 && pps->start_code_prefix[3] == 1 && ((pps->start_code_prefix[4]&0x1f) == 8))
|
return true;
|
return false;
|
}
|
bool inline is_sei_header(slice_header_t* sei)
|
{
|
if(sei->start_code_prefix[0] == 0 && sei->start_code_prefix[1] == 0 && sei->start_code_prefix[2] == 0 && sei->start_code_prefix[3] == 1 && ((sei->start_code_prefix[4]&0x1f) == 6))
|
return true;
|
return false;
|
}
|
bool inline is_IFrame_header(slice_header_t* IFrame)
|
{
|
if(IFrame->start_code_prefix[0] == 0 && IFrame->start_code_prefix[1] == 0 && IFrame->start_code_prefix[2] == 0 && IFrame->start_code_prefix[3] == 1 && ((IFrame->start_code_prefix[4]&0x1f) == 5))
|
{
|
// 0x00 0x00 0x00 0x01 0x65
|
return true;
|
}
|
else if(IFrame->start_code_prefix[0] == 0 && IFrame->start_code_prefix[1] == 0 && IFrame->start_code_prefix[2] == 1 && ((IFrame->start_code_prefix[3]&0x1f) == 5))
|
{
|
// 0x00 0x00 0x01 0x65
|
return true;
|
}
|
return false;
|
}
|
bool inline is_PFrame_header(slice_header_t* PFrame)
|
{
|
if(PFrame->start_code_prefix[0] == 0 && PFrame->start_code_prefix[1] == 0 && PFrame->start_code_prefix[2] == 0 && PFrame->start_code_prefix[3] == 1 && ((PFrame->start_code_prefix[4]&0x1f) == 1))
|
return true;
|
return false;
|
}
|
|
void get_sps_pps_len(uint8_t *h264_data,int h264_len,int* sps_len,int* pps_len,int* Iframe_len)
|
{
|
int nPos_SPS = 0;//SPSÓαêλÖÃ
|
int nPos_PPS = 0;//PPSÓαêλÖÃ
|
int nPos_IFrame = 0;//¹Ø¼üÖ¡ÓαêλÖÃ
|
int nPos = 0;//±éÀúÓαêλÖÃ
|
|
int nSizeSPS,nSizePPS,nSizeIFrame = 0;
|
|
slice_header_t* sps;
|
slice_header_t* pps;
|
slice_header_t* IFrame;
|
|
sps = (slice_header_t*)(h264_data);
|
|
if(is_sps_header(sps))
|
{
|
for(; nPos<h264_len; nPos++)
|
{
|
pps = (slice_header_t*)(h264_data + nPos);
|
if(is_pps_header(pps))
|
{
|
nPos_PPS = nPos;
|
}
|
|
IFrame = (slice_header_t*)(h264_data + nPos);
|
if(is_IFrame_header(IFrame))
|
{
|
nPos_IFrame = nPos;
|
break;
|
}
|
}
|
}
|
else
|
{
|
*sps_len = 0;
|
*pps_len = 0;
|
*Iframe_len = 0;
|
}
|
|
nSizeSPS = nPos_PPS - nPos_SPS;
|
nSizePPS = nPos_IFrame - nPos_PPS;
|
nSizeIFrame = h264_len - nPos_IFrame;
|
|
*sps_len = nSizeSPS;
|
*pps_len = nSizePPS;
|
*Iframe_len = nSizeIFrame;
|
|
}
|
|
|
//h265
|
bool inline is_hevc_vps_header(slice_header_t* vps)
|
{
|
int nal_type = 0;
|
nal_type = (vps->start_code_prefix[4] & 0x7E) >> 1;
|
|
if(vps->start_code_prefix[0] == 0 && vps->start_code_prefix[1] == 0 && vps->start_code_prefix[2] == 0 && vps->start_code_prefix[3] == 1 && nal_type == 32)
|
return true;
|
return false;
|
}
|
|
bool inline is_hevc_sps_header(slice_header_t* sps)
|
{
|
int nal_type = 0;
|
nal_type = (sps->start_code_prefix[4] & 0x7E) >> 1;
|
|
if(sps->start_code_prefix[0] == 0 && sps->start_code_prefix[1] == 0 && sps->start_code_prefix[2] == 0 && sps->start_code_prefix[3] == 1 && nal_type == 33)
|
return true;
|
return false;
|
}
|
|
bool inline is_hevc_pps_header(slice_header_t* pps)
|
{
|
int nal_type = 0;
|
nal_type = (pps->start_code_prefix[4] & 0x7E) >> 1;
|
|
if(pps->start_code_prefix[0] == 0 && pps->start_code_prefix[1] == 0 && pps->start_code_prefix[2] == 0 && pps->start_code_prefix[3] == 1 && nal_type == 34)
|
return true;
|
return false;
|
}
|
|
bool inline is_hevc_IFrame_header(slice_header_t* Iframe)
|
{
|
int nal_type = 0;
|
nal_type = (Iframe->start_code_prefix[4] & 0x7E) >> 1;
|
|
if(Iframe->start_code_prefix[0] == 0 && Iframe->start_code_prefix[1] == 0 && Iframe->start_code_prefix[2] == 0 && Iframe->start_code_prefix[3] == 1 && nal_type == 19)
|
return true;
|
return false;
|
|
}
|
|
bool inline is_hevc_PFrame_header(slice_header_t* Pframe)
|
{
|
int nal_type = 0;
|
nal_type = (Pframe->start_code_prefix[4] & 0x7E) >> 1;
|
|
if(Pframe->start_code_prefix[0] == 0 && Pframe->start_code_prefix[1] == 0 && Pframe->start_code_prefix[2] == 0 && Pframe->start_code_prefix[3] == 1 && nal_type == 1)
|
return true;
|
return false;
|
|
}
|
|
bool inline is_hevc_SEI_header(slice_header_t* sei)
|
{
|
int nal_type = 0;
|
nal_type = (sei->start_code_prefix[4] & 0x7E) >> 1;
|
|
if(sei->start_code_prefix[0] == 0 && sei->start_code_prefix[1] == 0 && sei->start_code_prefix[2] == 0 && sei->start_code_prefix[3] == 1 && nal_type == 39)
|
return true;
|
return false;
|
}
|
|
void get_vps_sps_pps_len(uint8_t *h265_data,int h265_len,int* vps_len,int* sps_len,int* pps_len,int* Iframe_len)
|
{
|
int nPos_VPS = 0;//VPSÓαêλÖÃ
|
int nPos_SPS = 0;//SPSÓαêλÖÃ
|
int nPos_PPS = 0;//PPSÓαêλÖÃ
|
int nPos_IFrame = 0;//¹Ø¼üÖ¡ÓαêλÖÃ
|
int nPos = 0;//±éÀúÓαêλÖÃ
|
|
int nSizeVPS,nSizeSPS,nSizePPS,nSizeIFrame = 0;
|
|
slice_header_t* vps;
|
slice_header_t* sps;
|
slice_header_t* pps;
|
slice_header_t* IFrame;
|
|
vps = (slice_header_t*)(h265_data);
|
|
if(is_hevc_vps_header(vps))
|
{
|
for(; nPos<h265_len; nPos++)
|
{
|
sps = (slice_header_t*)(h265_data + nPos);
|
if(is_hevc_sps_header(sps))
|
{
|
nPos_SPS = nPos;
|
}
|
|
pps = (slice_header_t*)(h265_data + nPos);
|
if(is_hevc_pps_header(pps))
|
{
|
nPos_PPS = nPos;
|
}
|
|
IFrame = (slice_header_t*)(h265_data + nPos);
|
if(is_hevc_IFrame_header(IFrame))
|
{
|
nPos_IFrame = nPos;
|
break;
|
}
|
}
|
}
|
else
|
{
|
*vps_len = 0;
|
*sps_len = 0;
|
*pps_len = 0;
|
*Iframe_len = 0;
|
}
|
|
nSizeVPS = nPos_SPS - nPos_VPS;
|
nSizeSPS = nPos_PPS - nPos_SPS;
|
nSizePPS = nPos_IFrame - nPos_PPS;
|
nSizeIFrame = h265_len - nPos_IFrame;
|
|
*vps_len = nSizeVPS;
|
*sps_len = nSizeSPS;
|
*pps_len = nSizePPS;
|
*Iframe_len = nSizeIFrame;
|
|
}
|
|
bool is_VOL_header(mpeg_header_t* VOL)
|
{
|
if(VOL->start_code_prefix[0] == 0 && VOL->start_code_prefix[1] == 0 && VOL->start_code_prefix[2] == 0x01 && VOL->start_code_prefix[3] == 0x20)
|
return true;
|
return false;
|
}
|
|
//MPEG2
|
bool is_sequence_header(mpeg_header_t* SH)
|
{
|
if((SH->start_code_prefix[0] == 0 && SH->start_code_prefix[1] == 0 && SH->start_code_prefix[2] == 0x01 && SH->start_code_prefix[3] == 0xB3))
|
return true;
|
return false;
|
}
|
|
bool is_H264_IFrame_Data(uint8_t *h264_data,int h264_len)
|
{
|
int nPos = 0;//±éÀúÓαêλÖÃ
|
|
slice_header_t* sps;
|
slice_header_t* pps;
|
slice_header_t* IFrame;
|
|
sps = (slice_header_t*)(h264_data);
|
|
if(is_sps_header(sps))
|
{
|
for(; nPos<h264_len; nPos++)
|
{
|
pps = (slice_header_t*)(h264_data + nPos);
|
if(is_pps_header(pps))
|
{
|
//nPos_PPS = nPos;
|
}
|
|
IFrame = (slice_header_t*)(h264_data + nPos);
|
if(is_IFrame_header(IFrame))
|
{
|
//nPos_IFrame = nPos;
|
return true;
|
}
|
}
|
}
|
return false;
|
}
|
|
bool is_h265_IFrame_Data(uint8_t *h265_data,int h265_len)
|
{
|
// int nPos_VPS = 0;//VPSÓαêλÖÃ
|
int nPos_SPS = 0;//SPSÓαêλÖÃ
|
int nPos_PPS = 0;//PPSÓαêλÖÃ
|
int nPos_IFrame = 0;//¹Ø¼üÖ¡ÓαêλÖÃ
|
int nPos = 0;//±éÀúÓαêλÖÃ
|
|
// int nSizeVPS,nSizeSPS,nSizePPS,nSizeIFrame = 0;
|
|
slice_header_t* vps;
|
slice_header_t* sps;
|
slice_header_t* pps;
|
slice_header_t* IFrame;
|
|
vps = (slice_header_t*)(h265_data);
|
|
if(is_hevc_vps_header(vps))
|
{
|
for(; nPos<h265_len; nPos++)
|
{
|
sps = (slice_header_t*)(h265_data + nPos);
|
if(is_hevc_sps_header(sps))
|
{
|
nPos_SPS = nPos;
|
}
|
|
pps = (slice_header_t*)(h265_data + nPos);
|
if(is_hevc_pps_header(pps))
|
{
|
nPos_PPS = nPos;
|
}
|
|
IFrame = (slice_header_t*)(h265_data + nPos);
|
if(is_hevc_IFrame_header(IFrame))
|
{
|
nPos_IFrame = nPos;
|
return true;
|
}
|
}
|
}
|
return false;
|
}
|
|
|