解析JM代码比较理解H264语法元素解码ue(v),se(v),u(n)
来源:互联网 发布:微场景制作软件推荐 编辑:程序博客网 时间:2024/06/05 07:15
ue(v):无符号整数指数哥伦布码编码的语法元素,左位在先。
se(v):有符号整数指数哥伦布码编码的语法元素,左位在先。
u(n):n位无符号整数。在语法表中,如果n是‘v’,其比特数由其它语法元素值确定。解析过程由函
数read_bits(n)的返回值规定,该返回值用最高有效位在前的二进制表示。
//! Syntaxelement 。an important data structure!
typedef struct syntaxelement
{
int type; //!< type of syntax element for data part.
int value1; //!< numerical value of syntax element
int value2; //!< for blocked symbols, e.g. run/level
int len; //!< length of code
int inf; //!< info part of UVLC code
unsigned int bitpattern; //!< UVLC bitpattern
int context; //!< CABAC context
int k; //!< CABAC context for coeff_count,uv
#if TRACE
#define TRACESTRING_SIZE 100 //!< size of trace string
char tracestring[TRACESTRING_SIZE]; //!< trace string
#endif
//!< for mapping of syntaxElement to UVLC
void (*mapping)(int value1, int value2, int* len_ptr, int* info_ptr);
//!< used for CABAC: refers to actual coding method of each individual syntax element type
void (*writing)(struct syntaxelement *, EncodingEnvironmentPtr);
} SyntaxElement;
/*!
*****************************************************************
* \brief
* ue_v, reads an ue(v) syntax element(ue(v)语法元素), the length in bits is stored in
* the global UsedBits variable(UsedBits是全局变量)
*
* \param tracestring
* the string for the trace file
*
* \param bitstream
* the stream to be read from
*
* \return
* the value of the coded syntax element
*
****************************************************************
*/
int ue_v (char *tracestring, Bitstream *bitstream)
{
SyntaxElement symbol, *sym=&symbol;
assert (bitstream->streamBuffer != NULL);
sym->type = SE_HEADER;
sym->mapping = linfo_ue; // Mapping rule
SYMTRACESTRING(tracestring);
readSyntaxElement_VLC (sym, bitstream);/*无符号变长指数哥伦布解码*/
UsedBits+=sym->len;
return sym->value1;
}
int se_v (char *tracestring, Bitstream *bitstream)
{
SyntaxElement symbol, *sym=&symbol;
assert (bitstream->streamBuffer != NULL);
sym->type = SE_HEADER;
sym->mapping = linfo_se; // Mapping rule: signed integer
SYMTRACESTRING(tracestring);
readSyntaxElement_VLC (sym, bitstream);
UsedBits+=sym->len;
return sym->value1;
}
/*!
****************************************************************
* \brief
* u_v, reads an u(v) syntax element, the length in bits is stored in
* the global UsedBits variable
*
* \param LenInBits
* length of the syntax element
*
* \param bitstream
* the stream to be read from
*
* \return
* the value of the coded syntax element。 do analyze one syntaxElement form bitstream to sym based on rule(u_v,u_1,ue_v...)
*
****************************************************************
*/
int u_v (int LenInBits, char*tracestring, Bitstream *bitstream)
{
SyntaxElement symbol, *sym=&symbol;
assert (bitstream->streamBuffer != NULL);
sym->type = SE_HEADER;//++ SE_HEADER=0
sym->mapping = linfo_ue; // Mapping rule。this is dummy
sym->len = LenInBits;
SYMTRACESTRING(tracestring);
readSyntaxElement_FLC (sym, bitstream);/*fixed length code*/
UsedBits+=sym->len;
return sym->inf;
};
significant differences between ue_v && u_v is respectively readSyntaxElement_VLC&& readSyntaxElement_FLC。
/*!
************************************************************************
* \brief
* read next UVLC codeword from UVLC-partition and
* map it to the corresponding syntax element
************************************************************************
*/
int readSyntaxElement_VLC(SyntaxElement *sym, Bitstream *currStream)
{
int frame_bitoffset = currStream->frame_bitoffset;
byte *buf = currStream->streamBuffer;
int BitstreamLengthInBytes = currStream->bitstream_length;
sym->len = GetVLCSymbol (buf, frame_bitoffset, &(sym->inf), BitstreamLengthInBytes);//++ 该处主要是获得哥伦布编码的标志比特位(从后继的码流中第一个比特位开始逐个检查)。
if (sym->len == -1)
return -1;
currStream->frame_bitoffset += sym->len;
sym->mapping(sym->len,sym->inf,&(sym->value1),&(sym->value2));
#if TRACE
tracebits(sym->tracestring, sym->len, sym->inf, sym->value1);
#endif
return 1;
}
/*!
************************************************************************
* \brief
* read FLC codeword from UVLC-partition .GetBits is enough,sym->mapping not needed
************************************************************************
*/
int readSyntaxElement_FLC(SyntaxElement *sym, Bitstream *currStream)
{
int frame_bitoffset = currStream->frame_bitoffset;
byte *buf = currStream->streamBuffer;
int BitstreamLengthInBytes = currStream->bitstream_length;
if ((GetBits(buf, frame_bitoffset, &(sym->inf), BitstreamLengthInBytes, sym->len)) < 0)
return -1;
currStream->frame_bitoffset += sym->len; // move bitstream pointer
sym->value1 = sym->inf;
#if TRACE
tracebits2(sym->tracestring, sym->len, sym->inf);
#endif
return 1;
}
so let's keep our eyes on functionGetBits() && (GetVLCSymbol , linfo_ue)。
/*!
************************************************************************
* \brief
* Reads bits from the bitstream buffer
*
* \param buffer
* containing VLC-coded data bits
* \param totbitoffset
* bit offset from start of partition
* \param info
* returns value of the read bits
* \param bytecount
* total bytes in bitstream
* \param numbits
* number of bits to read. read numbits data from buffer[] to *info,totbitoffset is the bit offset from start of byte
*
************************************************************************
*/
int GetBits (byte buffer[],int totbitoffset,int *info, int bytecount,
int numbits)
{
register int inf;
long byteoffset; // byte from start of buffer
int bitoffset; // bit from start of byte
int bitcounter=numbits;
byteoffset= totbitoffset/8;
bitoffset= 7-(totbitoffset%8);
inf=0;
while (numbits)
{
inf <<=1;
inf |= (buffer[byteoffset] & (0x01<<bitoffset))>>bitoffset;/*read 1 bit by 1 bit,here is to read most significant bit*/
numbits--;
bitoffset--;
if (bitoffset < 0)
{
byteoffset++;
bitoffset += 8;
if (byteoffset > bytecount)
{
return -1;
}
}
}
*info = inf;
return bitcounter; // return absolute offset in bit from start of frame
}
/*!
************************************************************************
* \brief
* read one exp-golomb VLC symbol
*
* \param buffer
* containing VLC-coded data bits
* \param totbitoffset
* bit offset from start of partition
* \param info
* returns the value of the symbol
* \param bytecount
* buffer length
* \return
* bits read
************************************************************************
*/
int GetVLCSymbol (byte buffer[],int totbitoffset,int *info, int bytecount)
{
register int inf;
long byteoffset; // byte from start of buffer
int bitoffset; // bit from start of byte
int ctr_bit=0; // control bit for current bit posision
int bitcounter=1;
int len;
int info_bit;
byteoffset= totbitoffset/8;
bitoffset= 7-(totbitoffset%8);
ctr_bit = (buffer[byteoffset] & (0x01<<bitoffset)); // set up control bit,used to find leading 1
len=1;/*len=leading zero number(M) + 1*/
while (ctr_bit==0)
{ // find leading 1 bit
len++;
bitoffset-=1;
bitcounter++;
if (bitoffset<0)
{ // finish with current byte ?
bitoffset=bitoffset+8;
byteoffset++;
}
ctr_bit=buffer[byteoffset] & (0x01<<(bitoffset));
}
// make infoword
inf=0; // shortest possible code is 1, then info is always 0
for(info_bit=0;(info_bit<(len-1)); info_bit++) /*类似GetBits while那段代码*/
{
bitcounter++;
bitoffset-=1;
if (bitoffset<0)
{ // finished with current byte ?
bitoffset=bitoffset+8;
byteoffset++;
}
if (byteoffset > bytecount)
{
return -1;
}
inf=(inf<<1);
if(buffer[byteoffset] & (0x01<<(bitoffset)))
inf |=1;
}
*info = inf;/*here is just to check M bit info,to get real value refer to sym->mapping()*/
return bitcounter; // return absolute offset in bit from start of frame
}
so now we know how to read exp-golomb symbol,next we'll find out how to convert the symbol to actual value。
/*!
************************************************************************
* \brief
* mapping rule for ue(v) syntax elements
* \par Input:
* length and info
* \par Output:
* number in the code table
************************************************************************
*/
void linfo_ue(int len, int info, int *value1, int *dummy)
{
//++ 参见9.1节 codeNum = pow(2,leadingZeroBits) - 1 + read_bits( leadingZeroBits )
//++ 所以此处:codeNum=*value1;leadingZeroBits=len/2;info=read_bits( leadingZeroBits )
//++ info的值即为二进制码字中信息域的十进制值;len/2即为信息域码字长度,当然也等于前导零域的码字长度;
*value1 = (int)pow(2,(len/2))+info-1; // *value1 = (int)(2<<(len>>1))+info-1;
}
/*!
************************************************************************
* \brief
* mapping rule for se(v) syntax elements
* \par Input:
* length and info
* \par Output:
* signed mvd
************************************************************************
*/
//++ 参见9.1.1Mapping process for signed Exp-Golomb codes
void linfo_se(int len, int info, int *value1, int *dummy)
{
int n;
n = (int)pow(2,(len/2))+info-1;
*value1 = (n+1)/2;
if((n & 0x01)==0) // lsb is signed bit。n为偶数的话则value1是负数
*value1 = -*value1;
}
follow picture may would be useful to have you understand above codes。
- 解析JM代码比较理解H264语法元素解码ue(v),se(v),u(n)
- h264 u(v) decode of frame_num, pic_order_cnt_lsb and slice_group_change_cycle
- 如何理解v-model就是语法糖?
- 导致解码延时/丢帧的语法元素—H264
- Hyper-v 2016 VHD Se
- U/V-Net Brief
- 解析I- L-O-V-E -Y-O-U
- V
- v
- v
- v
- v
- v
- V
- V
- V
- V
- V
- 数据库关闭
- 触摸屏驱动
- 为什么要用node.js
- UVA - 10596 Morning Walk
- 紫外线杀菌装置:Aquafine紫外线杀菌器 Aquafine CSL系列
- 解析JM代码比较理解H264语法元素解码ue(v),se(v),u(n)
- 数据库关闭(下)
- Android性能优化总结
- 紫外线消毒器:Aquafine紫外线杀菌器介绍
- CentOS 5 上安装Oracle11g
- 删除kafka 的topic
- linux经典书籍推荐
- Cannot construct net.sourceforge.cruisecontrol.BuildLoopInformation as it does not have a no-args co
- MyEclipse连接数据库DB2