/***************************************************************************************
***************************************************************************************/
#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_
- 1
- 2
- 3
- 4
- 5
前往页