0阶 无符号指数哥伦布编码

指数哥伦布编码与哈夫曼编码一样都属于变长编码

但二者也有显著的区别:

1>信源相关性: 哈夫曼编码依赖于信源的概率分布,而指数哥伦布编码与信源无关

2>额外信息: 哈夫曼编码必须携带与该信源匹配的码表,指数哥伦布编码无需携带额外信息

h264官方协议文档中定义了4类指数哥伦布编码分为:

ue(v)无符号指数哥伦布编码 、se(v)有符号指数哥伦布编码、 te(v)截断指数哥伦布编码 和 me(v)映射指数哥伦布编码

下面我们截取了协议文档中 ue(v)无符号指数哥伦布编码的部分作为例子来分析,其他几种模式均是在此基础上 进行变换得来。

9                       Parsing process

Inputs to this process are bits from the RBSP.

Outputs of this process are syntax element values.

This process is invoked when the descriptor of a syntax element in the syntax tables in subclause 7.3 is equal to ue(v), me(v), se(v), te(v) (see subclause 9.1), ce(v) (see subclause 9.2), or ae(v) (see subclause 9.3).

9.1              Parsing process for Exp-Golomb codes

This process is invoked when the descriptor of a syntax element in the syntax tables in subclause 7.3 is equal to ue(v), me(v), se(v), or te(v). For syntax elements in subclauses 7.3.4 and 7.3.5, this process is invoked only when entropy_coding_mode_flag is equal to 0.

Inputs to this process are bits from the RBSP.

Outputs of this process are syntax element values.

Syntax elements coded as ue(v), me(v), or se(v) are Exp-Golomb-coded. Syntax elements coded as te(v) are truncated Exp-Golomb-coded. The parsing process for these syntax elements begins with reading the bits starting at the current location in the bitstream up to and including the first non-zero bit, and counting the number of leading bits that are equal to 0. This process is specified as follows:

leadingZeroBits = ?1


for( b = 0; !b; leadingZeroBits++ )

b = read_bits( 1 )

The variable codeNum is then assigned as follows:


(9-1)


codeNum = 2leadingZeroBits ? 1 + read_bits( leadingZeroBits )


(9-2)

where the value returned from read_bits( leadingZeroBits ) is interpreted as a binary representation of an unsigned integer with most significant bit written first.

Table 9-1 illustrates the structure of the Exp-Golomb code by separating the bit string into "prefix" and "suffix" bits. The "prefix" bits are those bits that are parsed in the above pseudo-code for the computation of leadingZeroBits, and are shown as either 0 or 1 in the bit string column of Table 9-1. The "suffix" bits are those bits that are parsed in the computation of codeNum and are shown as xi in Table 9-1, with i being in the range 0 to leadingZeroBits ? 1, inclusive.

Each xi can take on values 0 or 1.

Table 9-1 – Bit strings with "prefix" and "suffix" bits and assignment to codeNum ranges (informative)


Bit string form


Range of codeNum


1


0


0 1 x0


1..2


0 0 1 x1 x0


3..6


0 0 0 1 x2 x1 x0


7..14


0 0 0 0 1 x3 x2 x1 x0


15..30


0 0 0 0 0 1 x4 x3 x2 x1 x0


31..62



从上述表中我们可以看到 一个编码片段 分为3个部分 前缀0 、标志位bit1、后缀二进制数与前缀的位数相同。

计算公式为 codeNum = 2leadingZeroBits ? 1 + read_bits( leadingZeroBits )

如 0 0 0 1 0 1 1
      前缀prefix 为 2^(leadingZeroBits = 3) -1 = 7
      后缀surfix 0 1 1 = 0*2^2 + 1*2^1 +1*2^0 = 3
      codeNum = prefix + surfix = 10

具体实现如下

// ExpColomb.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <assert.h>

typedef unsigned char UINT8;
/*
buf 为字节数组
bytePosition 为字节位置
bitPosition 为当前字节中 从左往右 的 bit位 的 位置 范围(0~7)
如 buf:                   0 0 0 0 1 0 0 0, 1 1 0 0 0 1 0 0, 0
bytePosition:         [         0         ]  [         1         ]
bitPosition:           0 1 2 3 4 5 6 7  0 1 2 3 4 5 6 7  0
*/
static int get_bit_at_position(UINT8 *buf, UINT8 &bytePosition, UINT8 &bitPosition)
{
    UINT8 mask = 0, val = 0;

    mask = 1 << (7 - bitPosition);
    val = ((buf[bytePosition] & mask) != 0);//获取当前bit位的值
    if (++bitPosition > 7)//若大于7则进入下一个字节
    {
        bytePosition++;
        bitPosition = 0;
    }

    return val;
}

static int get_uev_code_num(UINT8 *buf, UINT8 &bytePosition, UINT8 &bitPosition)
{
    assert(bitPosition < 8);
    UINT8 bitVal = 0;
    int codeNum = 0,prefix = 0, surfix = 0,leadingZeroBits = 0;
    //获取前导0的个数
    while (true)
    {
        bitVal = get_bit_at_position(buf, bytePosition, bitPosition);
        if (0 == bitVal)
        {
            leadingZeroBits++;
        }
        else
        {
            break;
        }
    }
    /*如 0 0 0     1     0 1 1
    前缀prefix 为  2^(leadingZeroBits = 3) -1 = 7
    后缀surfix  0 1 1  = 0*2^2 + 1*2^1 +1*2^0 = 3
    codeNum = prefix + surfix = 10
    */
    prefix = (1 << leadingZeroBits) - 1;
    for (int bit_pos = leadingZeroBits-1; bit_pos >-1; bit_pos--)
    {
        bitVal = get_bit_at_position(buf, bytePosition, bitPosition);
        surfix += (1 << bit_pos)*bitVal;
    }
    codeNum = prefix + surfix;
    return codeNum;
}

int main()
{
    UINT8 strArray[6] = { 0xA6, 0x42, 0x98, 0xE2, 0x04, 0x8A };
    UINT8 bytePosition = 0, bitPosition = 0;
    UINT8 dataBitLength = sizeof(strArray) * 8; //数组的总bit数

    int codeNum = 0;
    while ((bytePosition * 8 + bitPosition) < dataBitLength)
    {
        codeNum = get_uev_code_num(strArray, bytePosition, bitPosition);
        printf("ExpColomb codeNum = %d\n", codeNum);
    }

    getchar();
    return 0;
}

从运行结果可以看到  这里用6个字节 表示了从0到9的10个十进制数

标准协议文档中se(v) 有符号指数哥伦布编码如下

Table 9-3 – Assignment of syntax element to codeNum for signed Exp-Golomb coded syntax elements se(v)


codeNum


syntax element value


0


0


1


1


2


?1


3


2


4


?2


5


3


6


?3


k


(?1)k+1 Ceil( k÷2 )

我们可以看出 se(v) 是由 我们上面计算的codeNum通过公式 (?1)codeNum+1 Ceil(codeNum÷2 )  变换得来,

其中 ceil 为向上取整 ceil(1.5) = 2

映射指数哥伦布也是在得出codeNum的基础上,再通过查表得出具体数值  如:

 (a)   ChromaArrayType is equal to 0 or 3


codeNum


coded_block_pattern


 


Intra_4x4, Intra_8x8


Inter


0


15


0


1


0


1


2


7


2


3


11


4


4


13


8


5


14


3


6


3


5


7


5


10


8


10


12

一个codeNum通过查表可以得到2个参数

原文地址:https://www.cnblogs.com/gaobw/p/9661412.html

时间: 2024-10-14 14:08:12

0阶 无符号指数哥伦布编码的相关文章

【视频编解码&#183;学习笔记】8. 熵编码算法:基本算法列举 &amp; 指数哥伦布编码

一.H.264中的熵编码基本方法: 熵编码具有消除数据之间统计冗余的功能,在编码端作为最后一道工序,将语法元素写入输出码流 熵解码作为解码过程的第一步,将码流解析出语法元素供后续步骤重建图像使用 在H.264的标准协议中,不同的语法元素指定了不同的熵编码方法.在协议文档中共指定了10种语法元素的描述符,这些描述符表达了码流解析为语法元素值的方法,其中包含了H.264标准所支持的所有熵编码方法: 语法元素描述符 编码方法 b(8) 8位二进制比特位串,用于描述rbsp_byte() f(n) n位

Golomb及指数哥伦布编码原理介绍及实现

本文主要有以下三部分内容: 介绍了Golomb编码,及其两个变种:Golomb-Rice和Exp-Golomb的基本原理 C++实现了一个简单的BitStream库,能够方便在bit流和byte数字之间进行转换 C++实现了Golomb-Rice和Exp-Golomb的编码,并进行了测试. 在文章的最后提供了本文中的源代码下载. Golomb编码的基本原理 Golomb编码是一种无损的数据压缩方法,由数学家Solomon W.Golomb在1960年代发明.Golomb编码只能对非负整数进行编码

H.264学习笔记6——指数哥伦布编码

在H.264中,使用CABAC需要进行二值化处理,而指数哥伦布编码就是CABAC的一种二值化处理的方法.k阶指数哥伦布编解码具体过程如下: A.编码过程:假设待编码数字为CodeNum(必须非负整数) 指数哥伦布编码后的形式为[MZeors][1][Info],MZero表示M个0. 1.将CodeNum以二进制形式表示(若不足k位,前面补0),去掉后面k位(若刚好是k位,去掉k位后得0),将结果(数值)加1,得到二进制数T1: 2.M为二进制数T1的二进制位数减一: 3.然后将第一步中舍去的k

(转)指数哥伦布编码

在H.264中,使用CABAC需要进行二值化处理,而指数哥伦布编码就是CABAC的一种二值化处理的方法.k阶指数哥伦布编解码具体过程如下: A.编码过程:假设待编码数字为CodeNum(必须非负整数) 指数哥伦布编码后的形式为[MZeors][1][Info],MZero表示M个0. 1.将CodeNum以二进制形式表示(若不足k位,前面补0),去掉后面k位(若刚好是k位,去掉k位后得0),将结果(数值)加1,得到二进制数T1: 2.M为二进制数T1的二进制位数减一: 3.然后将第一步中舍去的k

H.264---指数哥伦布编码

转自:http://www.cnblogs.com/DwyaneTalk/p/4035206.html   一.哥伦布码 哥伦布码就是将编码对象分能成等间隔的若干区间(Group),每个Group有一个索引值:Group Id. >对于Group Id采用二元码编码: >对于Group内的编码对象采用定长码. 如下图: 对于编码对象n: n = q * m + r = low(n/m) * m + r.其中q = low(n/m),表示取下整,对应是Group Id; 余数r对应是Group内

int类型有符号与无符号内存中 -- C

/* int 有符号 0xffffffff == -1 0xfffffffe == -2 最小 0x80000000 == -21 4748 3648 最大 0x7fffffff == 21 4748 3647 0x00000001 == 1 0x00000000 == 0 int 无符号 最大 0xffffffff == 42 9496 7295 0x80000000 == 21 4748 3648 0x7fffffff == 21 4748 3647 最小 0x00000000 == 0 *

int有符号和无符号类型内存 -- C

/* int 有符号 0xffffffff == -1 0xfffffffe == -2 最小 0x80000000 == -21 4748 3648 最大 0x7fffffff == 21 4748 3647 0x00000001 == 1 0x00000000 == 0 int 无符号 最大 0xffffffff == 42 9496 7295 0x80000000 == 21 4748 3648 0x7fffffff == 21 4748 3647 最小 0x00000000 == 0 *

[C/C++]如何将一个无符号整型所有数据位置为1

正解「x = -1;」 -1超出无符号整型x的表达范围,根据标准(C++11 section 4.7.2),-1将被转化为2^n-1(n为x的bit数). 不正解 「x = 0xFFFFFFFF;」 这只适用于32bit整型. 不正解「x = ~0;」 这个被很多书认定为「标准答案」的解答也是错的.C/C++标准支持原码/反码/补码三种负数表示形式,只有在补码环境下才会得到正确结果.(例如在反码下,~0将得到-0,-0转为无符号仍然是0) 那么x = ~0u呢? 仍然是错的.根据标准(C++11

关于无符号整型数中1的个数与0的个数的改变与计算引发的思考

首先可以把unsigned int数中的1的个数与0的个数改变与计算的实现: </pre><pre name="code" class="cpp">/********************************************************************** * * Copyright (c)2015,WK Studios * * Filename: A.h * * Compiler: GCC vc 6.0 *