做暖暖视频网站,深圳龙华是穷人区吗,企业网站适合响应式嘛,西安外包公司排行一、引言
由于视频的传输和存贮是十分在乎体积的#xff0c;对于每一个比特#xff08;bit#xff09;都要格外珍惜#xff0c;所以H.264中用到了多种熵编码来对原本的数据进行压缩。 比如Sequence Paramater Set#xff08;sps / 序列参数集#xff09;中#xff0c;s…一、引言
由于视频的传输和存贮是十分在乎体积的对于每一个比特bit都要格外珍惜所以H.264中用到了多种熵编码来对原本的数据进行压缩。 比如Sequence Paramater Setsps / 序列参数集中seq_parameter_set_id这个属性用到了无符号指数哥伦布编码ue(v) offset_for_non_ref_pic这个属性用到了有符号指数哥伦布编码se(v) 要拿到sps中的上述属性需要对H.264码流对应的位置进行指数哥伦布编码的解码。 二、指数哥伦布编码简介
哥伦布编码又译作格伦布编码英语Golomb coding是一种无失真资料压缩方法由数学家所罗门·格伦布在1960年代提出。其优点为易于编码与解码目前广泛用于无损影像压缩。它是一种变长编码。
其具体原理可以参考《百度百科指数哥伦布码》
《维基百科格伦布编码》
《Golomb Codes》 三、FFmpeg源码中 无符号指数哥伦布编码的解码实现
FFmpeg源码中通过get_ue_golomb、get_ue_golomb_long、get_ue_golomb_31等函数实现 对无符号指数哥伦布编码的解码。下面以get_ue_golomb_31函数为例进行讲解。 get_ue_golomb_31函数定义在FFmpeg源码本文演示用的FFmpeg源码版本为5.0.3的头文件libavcodec/golomb.h中
/*** read unsigned exp golomb code, constraint to a max of 31.* If the value encountered is not in 0..31, the return value* is outside the range 0..30.*/
static inline int get_ue_golomb_31(GetBitContext *gb)
{unsigned int buf;#if CACHED_BITSTREAM_READERbuf show_bits_long(gb, 32);buf 32 - 9;skip_bits_long(gb, ff_golomb_vlc_len[buf]);
#elseOPEN_READER(re, gb);UPDATE_CACHE(re, gb);buf GET_CACHE(re, gb);buf 32 - 9;LAST_SKIP_BITS(re, gb, ff_golomb_vlc_len[buf]);CLOSE_READER(re, gb);
#endifreturn ff_ue_golomb_vlc_code[buf];
} 形参gb既是输入型参数也是输出型参数。指向已经被初始化的GetBitContext类型的变量。执行get_ue_golomb_31函数之前必须确保已经使用init_get_bits函数进行初始化。关于GetBitContext结构体可以参考《FFmpeg中位操作相关的源码GetBitContext结构体init_get_bits函数、get_bits1函数和get_bits函数分析》 如果是使用get_ue_golomb_31函数对某个NALU比如sps中的属性进行读取。
执行get_ue_golomb_31函数之前
gb-buffer需指向存放该NALU的“NALU Header RBSP 的缓冲区”。
gb-buffer_end需指向上述缓冲区的末尾也就是RBSP的最后一个字节。
gb-index的值需等于当前读取到该缓冲区的第几位了单位为bit。要对以该位为起始的数据进行无符号指数哥伦布编码的解码。
gb-size_in_bit 的值需等于NALU Header SODB的位数单位为bit。
gb-size_in_bits_plus8的值需等于 s-size_in_bit 的值 加 8。 执行get_ue_golomb_31函数后
gb-index的值会加上 “读取到的无符号指数哥伦布编码后的位数”。gb的其它成员的值不变。
get_ue_golomb_31函数返回值为对gb-index的位置 进行无符号指数哥伦布解码后得到的数据。 注意get_ue_golomb_31函数有读取范围的限制只能读取0到31的数据所以如果get_ue_golomb_31函数的返回值大于31表示出错了。 所以FFmpeg源码中源文件libavcodec/h264_ps.c对sps进行解码的函数ff_h264_decode_seq_parameter_set中有这样的一段逻辑
#define MAX_SPS_COUNT 32int ff_h264_decode_seq_parameter_set(GetBitContext *gb, AVCodecContext *avctx,H264ParamSets *ps, int ignore_truncation){//...sps_id get_ue_golomb_31(gb);if (sps_id MAX_SPS_COUNT) {av_log(avctx, AV_LOG_ERROR, sps_id %u out of range\n, sps_id);goto fail;}//...
}
如果读取到的sps_id值不小于32表示out of range了。 如果想要更大的读取范围可以用get_ue_golomb函数和get_ue_golomb_long函数。它们的用法跟get_ue_golomb_31函数一样只是读取范围更大而已。 四、FFmpeg源码中 有符号指数哥伦布编码的解码实现
FFmpeg源码中通过get_se_golomb和get_se_golomb_long等函数实现对 有符号指数哥伦布编码的解码。它们都定义在libavcodec/golomb.h中。
其形参跟get_ue_golomb_31函数相同不同的地方为返回值是对gb-index的位置 进行有符号指数哥伦布解码后得到的数据。