参考博文
上一篇H264基本NALU结构解析1.NALU头encode
1.1NaluType
NAL Header:forbidden_bit,nal_reference_bit(优先级)2bit,nal_unit_type(类型)5bit。标识NAL单元中的RBSP数据类型,其中,nal_unit_type为1, 2, 3, 4, 5的NAL单元称为VCL的NAL单元,其他类型的NAL单元为非VCL的NAL单元。
int WriteAnnexbNALU (NALU_t *n)
{
int BitsWritten = 0;
assert (n != NULL);
assert (n->forbidden_bit == 0);
assert (f != NULL);
assert (n->startcodeprefix_len == 3 || n->startcodeprefix_len == 4);
// printf ("WriteAnnexbNALU: writing %d bytes w/ startcode_len %d\n", n->len+1, n->startcodeprefix_len);
if (n->startcodeprefix_len > 3)
{
putc (0, f);
BitsWritten =+ 8;
}
putc (0, f);
putc (0, f);
putc (1, f);
BitsWritten += 24;
n->buf[0] =
n->forbidden_bit << 7 |
n->nal_reference_idc << 5 |
n->nal_unit_type;
// printf ("First Byte %x, nal_ref_idc %x, nal_unit_type %d\n", n->buf[0], n->nal_reference_idc, n->nal_unit_type);
if (n->len != fwrite (n->buf, 1, n->len, f))
{
printf ("Fatal: cannot write %d bytes to bitstream file, exit (-1)\n", n->len);
exit (-1);
}
BitsWritten += n->len * 8;
fflush (f);
#if TRACE
fprintf (p_trace, "\n\nAnnex B NALU w/ %s startcode, len %d, forbidden_bit %d, nal_reference_idc %d, nal_unit_type %d\n\n",
n->startcodeprefix_len == 4?"long":"short", n->len, n->forbidden_bit, n->nal_reference_idc, n->nal_unit_type);
fflush (p_trace);
#endif
return BitsWritten;
}
2.指数哥伦布编码
http://guoh.org/lifelog/2013/10/exp-golomb-coding/2.1 Exp-Golomb code
指数哥伦布码是一种压缩编码方法,用来表示非负整数的k阶指数哥伦布码可用如下步骤生成。leadingZeroBits = −1
for (b = 0; !b; leadingZeroBits++)
b = read_bits(1)
=
-
+
read_bits为读取num个比特的值判断并获取对应的数值
2.2 JM8.6中ue_v/se_v计算
ue_v 为无符号指数哥伦布比特串与编码数值的映射se_v 为有符号指数哥伦布码比特串与编码数值的映射
/*!
************************************************************************
* \brief
* mapping for ue(v) syntax elements
* \param ue
* value to be mapped
* \param dummy
* dummy parameter
* \param info
* returns mapped value
* \param len
* returns mapped value length
************************************************************************
*/
void ue_linfo(int ue, int dummy, int *len,int *info)
{
int i,nn;
nn=(ue+1)/2;
for (i=0; i < 16 && nn != 0; i++)
{
nn /= 2;
}
*len= 2*i + 1; //获取编码长度,包括了补充0bit num = length -1;
*info=ue+1-(int)pow(2,i); //获取编码最高非零位后的值
}
/*!
************************************************************************
* \brief
* mapping for se(v) syntax elements
* \param se
* value to be mapped
* \param dummy
* dummy argument
* \param len
* returns mapped value length
* \param info
* returns mapped value
************************************************************************
*/
void se_linfo(int se, int dummy, int *len,int *info)
{
int i,n,sign,nn;
sign=0;
if (se <= 0)
{
sign=1;
}
n=abs(se) << 1;
/*
n+1 is the number in the code table. Based on this we find length and info
*/
nn=n/2;
for (i=0; i < 16 && nn != 0; i++)
{
nn /= 2;
}
*len=i*2 + 1;
*info=n - (int)pow(2,i) + sign;
}
2.3 SODB与RSBP区别
SODB是string比特数据源data bits,RSBP为raw字节序列流1)RBSP 的第一个byte包括(最高位的)8 bit的 SODB;RBSP 的下一个字节应包括接下来的 8bit的 SODB,直到剩下的 SODB 少于 8bit。
2)rbsp_trailing_bits( )用于 SODB 之后(少于8bit),满足如下规则:
i)最后 RBSP byte的包括 SODB 的剩下的所有bit
ii)下一个bit为单个 rbsp_stop_one_bit,其值为 1,并且 当 rbsp_stop_one_bit 不 是 一 个 byte_align对 齐 的 最后一 个 bit 时 ,
rbsp_alignment_zero_bit就会用来进行字节对齐。
3)在某些 RBSP 结尾的 rbsp_trailing_bits( )之后,可以出现值为 0x0000 的一个或多个 16 比特的语法元素 cabac_zero_word
void SODBtoRBSP(Bitstream *currStream)
{
currStream->byte_buf <<= 1;
currStream->byte_buf |= 1;
currStream->bits_to_go--;
currStream->byte_buf <<= currStream->bits_to_go;
currStream->streamBuffer[currStream->byte_pos++] = currStream->byte_buf;
currStream->bits_to_go = 8;
currStream->byte_buf = 0;
}