H264视频的sps和pps解析和哥伦布编码

来源:互联网 发布:网络黄牛是什么意思 编辑:程序博客网 时间:2024/06/06 02:41
</pre><pre name="code" class="html">

</pre></div></div><div class="bct fc05 fc11 nbw-blog ztag" style="line-height:28px; word-wrap:break-word; margin:15px 0px; padding:5px 0px; overflow:hidden; font-family:'Hiragino Sans GB W3','Hiragino Sans GB',Arial,Helvetica,simsun,u5b8bu4f53"><ol style="font-size:14px; font-family:Arial; line-height:22px; margin-top:0.3em; margin-bottom:0px; margin-left:3.2em"><li style="margin-bottom:0.1em"><span style="font-family:SimSun; font-size:12px">将数字以<a target=_blank target="_blank" title="二进制" rel="nofollow" href="http://zh.wikipedia.org/wiki/%E4%BA%8C%E8%BF%9B%E5%88%B6" style="color:rgb(11,0,128); text-decoration:none">二进制</a>形式写出,去掉最低的k个比特位,之后加1</span></li><li style="margin-bottom:0.1em"><span style="font-family:SimSun; font-size:12px">计算留下的<a target=_blank target="_blank" title="比特数(页面不存在)" rel="nofollow" href="http://zh.wikipedia.org/w/index.php?title=%E6%AF%94%E7%89%B9%E6%95%B0&action=edit&redlink=1" style="color:rgb(165,88,88); text-decoration:none">比特数</a>,将此数减一,即是需要增加的前导零个数</span></li><li style="margin-bottom:0.1em"><span style="font-family:SimSun; font-size:12px">将第一步中去掉的最低k个比特位补回比特串尾部</span></li></ol><p style="margin-top:0.4em; margin-bottom:0.5em; padding-top:0px; padding-bottom:0px; font-family:Arial; line-height:22px"><span style="font-family:SimSun"><strong><span style="font-size:18px; color:#000099">一、k=0阶指数哥伦布码如下所示:</span></strong></span></p><p style="margin-top:0.4em; margin-bottom:0.5em; padding-top:0px; padding-bottom:0px; font-family:Arial; line-height:22px"><span style="font-family:SimSun"><strong><span style="font-size:18px; color:#000099"></span></strong></span></p><pre style="white-space:pre-wrap; word-wrap:break-word; font-size:14px; background-color:rgb(255,255,255); padding:1em; border:1px dashed rgb(47,111,171); line-height:1.3em"><span style="font-family:SimSun; font-size:12px"> 0 => 1 => 1  1 => 10 => 010  2 => 11 => 011  3 => 100 => 00100  4 => 101 => 00101  5 => 110 => 00110  6 => 111 => 00111  7 => 1000 => 0001000  8 => 1001 => 0001001</span>

具体过程如下所示

-----------------------------------------------------------------------------------------------------

比特串格式为“前缀1后缀”。

1)1后缀=codeNum+1,如codeNum = 3,则1后缀=4,即为100,后缀为00;

2)前缀与后缀的比特数相同,且前缀的各位比特为0,

下例为对不同codeNum进行的编码结果:

 0 => 1 => 1

 1 => 10 => 010 (10为2个比特,所以1前面要补的0的个数为:2-1=1,所以为:0   10)

 2 => 11 => 011

 3 => 100 => 00100

 4 => 101 => 00101

 5 => 110 => 00110

 6 => 111 => 00111

 7 => 1000 => 0001000

 8 => 1001 => 0001001 (1001为4个比特,所以前面补4-1=3个0)

   

 待编码数字 加1加1后二进制表示  需补的前缀0 其它 0 1 00000001   1 2 10   2 3 11   3 4 100   4 5 101   5 6 110   6 7 111   7 8 1000   8 9 1001  9 10 1010   10 11 1011   11 12 1100  ----------------------------------------------------------------------------------------------------------------------------------------------------------

解码:

      解析k阶指数哥伦布码时,首先从比特流的当前位置开始寻找第一个非零比特,并将找到的零比特个数记为leadingZeroBits,然后根据leadingZeroBits计算CodeNum。用伪代码描述如下:

    

指数哥伦布编码(to be continued..) - lhzsolomon@126 - Truemens world

下表给出了0阶、1阶、2阶和3阶指数哥伦布码的结构。指数哥伦布码的比特串分为“前缀”和“后缀”两部分。前缀由leadingZeroBits 个连续的0和一个1构成,后缀由leadingZeroBits+k个比特构成,即表中的xi串,i的范围为0~(leadingZeroBits+k- 1),每个xi的值为0或1。

指数哥伦布编码(to be continued..) - lhzsolomon@126 - Truemens world

(1)ue(v):无符号直接映射,code_num = v 。应用在宏块类型、参考帧索引等参数上。
(2)se(v):符号映射,应用于运动矢量差值,量化参数差值等,映射规则如下:
code_num=2lvl    (v<0)
code_num=2lvl-1 (v>0)
(3)me(v):标记映射,参数 根据标准中定义的一张表格映射到code_num。这种映射方式用于coded_block_pattern参数。
每一种映射方式(ue,se,me)都被尽量设计成对出现频率高的值使用较短的码字而对出现频率低的值使用较长的码字。例如,宏块模式Pred L0 16x16被映射到code_num 0,因为这种预测方式出现频率高,而Pred_8x8被映射为code num3,因其出现频率较低。

  H.264的一个重要特色就是采用UVLC(Universal Variable Length coding, 统一可变长编码)编码,提高了编码效率。

          UVLC编码中有一种编码方式就是指数哥伦布编码。程序实现该编码时需要计算编码长度len及其value,下面分别对无符号和有符号两种指数哥伦布编码进行分析。

          设编码值为code_val。

    static const int i_size0_255[256] =
    {
        1,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
        6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
        7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
        7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
        8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
        8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
        8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
        8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
    };

    void bs_write( bs_t *s, int bit_len, int value); 

1. ue(v)

        1) value = code_val+1
        2)len = 2*i_size0_255[value]+1
编程实现如下:
void ue_v( bs_t *s, unsigned int code_val )
{
    int i_size = 0;
    if( val == 0 )
    {
        bs_write( s, 1, 1); 
    }
    else
    {
        unsigned int tmp = ++code_val;
        if( tmp >= 0x00010000 )
        {
            i_size += 16;
            tmp >>= 16;
        }
        if( tmp >= 0x100 )
        {
            i_size += 8;
            tmp >>= 8;
        }
        i_size += i_size0_255[tmp];
        bs_write( s, 2 * i_size - 1, code_val);
    }
}

2. se(v)

        1) 若code_val>0:    value = 2*code_val-1
            若code_val>0:     value = -2*val
       2)len = 2*i_size0_255[value]+1
编程实现如下:
static void se_v( bs_t *s, int code_val )
{
    ue_v( s, code_val <= 0 ? -code_val  * 2 : code_val * 2 - 1);
}
----------------------------------------------------------------------------------------------------------------------------------------------------------

如下示例:

二进制比特数          长度                 解析值  

1001                           1                           0

 001 1001                   5                           5

 01 1010                      3                           2

 010                                                        1

 000 1011                                             10

 0001 001                    7                           8

0 0
原创粉丝点击