SEO基础

SEO基础

Products

当前位置:首页 > SEO基础 >

南宁中信建设有限责任公司官网招聘信息是什么?

96SEO 2026-02-19 19:33 12


1、音视频之视频压缩技术及数字视频综述

在编码器输出的码流中数据的基本单位是句法元素。

南宁中信建设有限责任公司官网招聘信息是什么?

每个句法元素由若干比特组成它表示某个特定的物理意义例如宏块类型、量化参数等。

句法表征句法元素的组织结构语义阐述句法元素的具体含义。

所有的视频编码标准都是通过定义句法和语义来规范编解码器的工作流程。

一、语句

编码器输出的比特码流中每个比特都隶属某个句法元素也就是说码流是由一个个句法元素依次衔接组成的码流中除了句法元素外并不存在专门用于控制或同步的内容。

在H.264定义的码流中句法元素被组织成有层次的结构分别描述各个层次的信息。

图6.1表现

句法元素的分层结构有助于更有效地节省码流。

例如在一个图像中经常会在各个片之间有相同的数据如果每个片都同时携带这些数据势必会造成码流的浪费。

更为有效的做法是将该图像的公共信息抽取出来形成图像一级的句法元素而在片级只携带该片自身独有的句法元素。

在H.264中句法元素被组织成序列、图像、片、宏

H.264的分层结构是经过精心设计的与以往的视频编码标准相比有很大的改进这些改进主要针对传输中的错误掩藏在有误码发生时可以提高图像重建的性能。

在以往的标准中分层的组织结构如图

6.2所示它们如同TCP/IP的结构每一层都有头部然后在每层的数据部分包含该层的数据。

在这样的结构中每一层的头部和它的数据部分形成管理与被管理的强依赖关系头部的句法元素是该层数据的核心而一旦头部丢失数据部分的信息几乎不可能再被正确地解码出来。

尤其在序列层及图像层由于网络中MTU最大传输单元大小的限制不可能将整个层的句法元素全部放入同一个分组中这个时候如果头部所在的分组丢失该层其他分组即使能被正确接收也无法解码造成资源浪费。

在H.264中分层结构最大的不同是取消了序列层和图像层并将原本属于序列和图像头部的大部分句法元素游离出来形成序列和图像两级参数集其余的部分则放入片层。

参数集是一个独立的数据单位不依赖于参数集外的其他句法元素。

图6.3描述了参数集与参数集外句法元素的关系在图中我们可以看到参数集只是在片层句法元素需要的时候被引用而且一个参数集并不对应某个特定的图像或序列同一个序列参数集可以被多个序列中的图像参数集引用。

同理同一个图像参数集也可以被多个图像引用。

只在编码器认为需要更新参数集的内容时才会发送出新的参数集。

在这种机制下由于参数集是独立的它可以被多次重发或者采用特殊技术加以保护。

在图6.3的描述中参数集与参数集外部的句法元素处于不同信道中这是H.264的一个建议我们可以使用更安全但成本更昂贵的通道来传输参数集而使用成本低但不够可靠的信道传输其他句法元素

只需要保证片层中的某个句法元素需要引用某个参数集时那个参数集已经到达解码器即可也就是参数集在时间上必须先被传送。

当然在条件不允许的情况下我们也可以采用妥协的办法在同一个物理信道中传输所有的句法元素但专门为参数集采用安全可靠的通信协议如TCP。

当然H.264也允许我们为包括参数集在内的所有句法元素指定同样的通信协议但这时所有参数集必须被多次重发以保证解码器最终至少能接收到一个。

在参数集和片使用同个物理信道的情况下图6.3中的信道1和信道2应该被理解为逻辑上的信道因为从逻辑上看参数集与其他句法元素还是处于各自彼此独立的信道中。

H.264在片层增加了新的句法元素指明所引用的参数集的编号同时因为取消了图像层片成为了信道2中最上层的独立的数据单位每个片必须自己携带关于所属图像的编号、大小等基本信息这些信息在同一图像的每个片中都必须是一致的。

在编码时H.264的规范要求将参数集、片这些独立的数据单位尽可能各自完整地放入一个分组中进行传送。

从表面上看来H.264关于参数集和片层的结构增加了编码后数据的冗余度比如参数集必须多次重发又如每个片都必须携带一部分相同的关于整个图像的信息而这些数据完全是重复的降低了编码效率但这些技术的采用使得通信的鲁棒性大大增强当数据传输中出现丢包时能够将错误限制在最小范围防止错误的扩散解码后对错误的掩藏和恢复也能起到很好的作用。

一个片的丢失将不会影响其他片的解码还可以通过该片前后的片来恢复该片的数据。

H.264片层以下的句法元素的结构大体上和以往标准类似但在相当多的细节上有所改进所有改进的目的不外乎两个在错误发生时防止错误扩散和减少冗余信息提高编码效率。

这两者往往是矛盾的。

图6.3所示的码流的结构是一种简化的模型这个模型已经能够正确工作但还不够完善不适合复杂的场合。

在复杂的通信环境中

除了片和参数集外还需要其他的数据单位来提供额外的信息。

图6.4描述了在复杂通信中的码流中可能出现的数据单位。

如前文所述参数集可以被抽取出来使用其他信道传输。

在图6.4中我们看到一个序列的第一个图像叫做IDR图像即时解码刷新图像IDR图像都是I图像。

H.264引入IDR图像是为了解码的重同步当解码器解码到IDR图像时立即将参考帧队列清空将已解码的数据全部输出或抛弃重新查找参数集开始一个新的序列。

这样如果在前一个序列的传输中发生重大错误如严重的丢包或其他原因引起数据错位在这里可以获得重新同步。

IDR图像之后的图像永远不会引用IDR图像之前的图像的数据来解码。

要注意IDR图像和I图像的区别IDR图像一定是I图像但I图像不一定是IDR图像。

一个序列中可以有很多的I图像I图像之后的图像可以引用I图像之间的图像做运动参考。

在图6.4中除了参数集与片外还有其他的数据单位这些数据单位可以提供额外的数据或同步信息这些数据单位也是一系列句法元素的集合。

它们在解码过程中不是必需的但却可以适当提高同步性能或定义图像的复杂特征。

句法元素与变量

编码器将数据编码为句法元素然后依次发送。

在解码器端通常要将句法元素作求值计算得出一些中间数据这些中间数据就是H.264定义的变量如图6.5所示。

在图6.5中pic_width_in_mbs_minus1是解码器直接从码流中提取的句法元素这个句法元素表征图像的宽度以宏块为单位。

我们看到为了提高编码效率H.264将图像实际的宽度减去1后再传送。

PicWidthInMbspic_width_in_mbs_minus11

PicWidthInSamplesLPicWidthInMbs×16

PicWidthInSamplesCPicWidthInMbs×8

以上变量PicWidthInMbs表示图像以宏块为单位的宽变量

PicWidthInSamplesL、PicWidthInSamplesC分别表示图像的亮度、色度分量以像素为单位的宽。

H.264定义这些变量是因为在后续句法元素的提取算法或图像的重建中需要用到它们的值。

在H.264中句法元素的名称是由小写字母和一系列的下划线组成而变量名称由大小写字母组成中间没有下划线。

句法是句法元素的组织结构而对一个结构的描述必然少不了对应的语法语法提供判断、循环等必要的描述方法。

H.264采用一种类C语法。

描述子

描述子是指从比特流提取句法元素的方法即句法元素的解码算法每个句法元素都有相对应的描述子。

由于H.264编码的最后一步是熵编码所以这里的描述子大多是熵编码的解码算法。

H.264定义了如下几种描述子

ae(v)

我们看到描述子都在括号中带有一个参数这个参数表示需要提取的比特数。

当参数是n时表明调用这个描述子的时候会指明n的值也即该句法元素是定长编码的。

当参数是v时对应的句法元素是变长编码这时有两种情况i(v)和u(v)两个描述子的v由以前的句法元素指定也就是说在前面会有句法元素指定当前句法元素的比特长度除了这两个描述子外其他描述子都是熵编码它们的解码算法本身能够确定当前句法元素的比特长度。

二、句法表

句法表定义了H.264的句法指明在码流中依次出现的句法元素及它们出现的条件、提取描述子等。

就像前文所提句法表是分层嵌套的。

H.264的句法表见表6.1至表6.19。

表6.1

在句法表中的C字段表示该句法元素的分类这是为片分区服务的句法元素分类的具体含义在表6.20中详细介绍。

其中Descriptor

表6.20

在网络传输的环境下编码器将每个NAL各自独立、完整地放入一个分组由于分组都有头部解码器可以很方便地检测出NAL的分界依次取出NAL进行解码。

为了节省码流H.264没有另外在NAL的头部设立表示起始的句法元素我们从表6.1可以看到这点。

但是如果编码数据是储存在介质如DVD光盘上由于NAL是依次紧密排列的解码器将无法在数据流中分辨出每个NAL的起始位置和终止位置所以必须要有另外的机制来解决这个问题。

针对这个问题H.264草案的附录B中指明了一种简单又高效的方案。

当数据流存储在介质上时在每个NAL前添加起始码0x000001。

齐或必须是某个常数的倍数。

考虑到这种情况H.264建议在起始码前添加若干字节的0来填充直到该NAL的长度符合要求。

在这样的机制下解码器在码流中检测起始码作为一个NAL的起始标识当检测到下一个起始码时当前NAL结束。

H.264规定当检测到0x000000时也可以表征当前NAL的结束这是因为连着的3个字节的0中的任何一个字节的0要么属于起始码要么是起始码前面添加的0。

添加起始码是一个解决问题的很好的方法但上面关于起始码的介绍还不完整因为忽略了一个重要的问题如果在NAL内部出现了

0x000001或是0x000000的序列怎么办。

毫无疑问这种情况是致命的

解码器将把这些本来不是起始码的字节序列当作起始码而错误地认为这里往后是一个新的NAL的开始进而造成解码数据的错位而我们做的大量实验证明NAL内部经常会出现这样的字节序列。

于是H.264提出了另外一种机制叫做“防止竞争”在编码器编码完一个NAL时应该检测是否出现图6.6左侧中的四个字节序列以防止它们和起始码竞争。

如果检测到这些序列存在编码器将在最后一个字节前插入一个新的字节0x03从而使它们变成图6.6右测的样子。

当解码器在NAL内部检测到有0x000003的序列时将把0x03抛弃恢复原始数据。

我们可以从句法表6.1中看到解码器在NAL层的处理步骤其中变量NumBytesInNALunit是解码器计算出来的解码器在逐个字节地读一个NAL时并不同时对它解码而是要通过起始码机制将整个NAL读进计算出长度后再开始解码。

forbidden_zero_bit

表示当前NAL越重要越需要优先受到保护。

H.264规定如果当前NAL是一个序列参数集或一个图像参数集或属于参考图像的片或片分区等重要的数据单位时本句法元素必须大于0。

但在大于0时具体该取何值并没有进一步的规定通信双方可以灵活地制定策略。

nal_unit_type等于5时nal_ref_idc大于0nal_unit_type等于6、9、10、

nal_unit_type

6.20。

nal_unit_type5时表示当前NAL是IDR图像的一个片在这种情况下IDR图像中的每个片的nal_unit_type都应该等于5。

注意片分区不可用于IDR图像。

rbsp_byte[i]

RBSP的第i个字节。

RBSP指原始字节载荷它是NAL单元的数据部分的封装格式封装的数据来自SODB原始数据比特流。

SODB是编码后的原始数据SODB经封装为RBSP后放入NAL的数据部分。

下面介绍一个RBSP的生成顺序。

RBSP的第一个字节直接取自SODB的第18个比特RBSP字节内的比特按照从左到右对应为从高到低的顺序排列以此类推

RBSP其余的每个字节都直接取自SODB的相应比特RBSP的最后一个字节包含SODB的最后几个比特及如下的

rbsp_trailing_bits()

rbsp_trailing_bits()的第一个比特是1接下来填充0直到字节对齐

填充0的目的也是为了字节对齐最后添加若干个cabac_zero_word其值等于0x0000。

emulation_prevention_three_byte

2、序列参数语义

附录A.2.1所指明的所有制约条件等于0时表示不必遵从所有条件。

constraint_set1_flag

附录A.2.2所指明的所有制约条件等于0时表示不必遵从所有条件。

constraint_set2_flag

附录A.2.3所指明的所有制约条件等于0时表示不必遵从所有条件。

注意当constraint_set0_flag、constraint_set1_flag、

constraint_set2_flag中有两个以上等于1时本章参考文献1中附录

reserved_zero_5bits

在目前的标准中本句法元素必须等于0其他的值保留做将来用解码器应该忽略本句法元素的值。

seq_parameter_set_id

注意当编码器需要产生新的序列参数集时应该使用新的seq_parameter_set_id即使用新的序列参数集而不是去改变原来的参数集中的内容。

个句法元素frame_num服务的frame_num是最重要的句法元素之一

它标识所属图像的解码顺序。

可以在句法表看到fram-num的解码函数是uev函数中的v在这里指定

从另一个角度看这个句法元素同时也指明了frame_num的所能达到的最大值

变量MaxFrameNum表示frame_num的最大值。

在解码过程中它也是一个非常重要的变量。

值得注意的是frame_num是循环计数的即当它到达MaxFrameNum后又从0重新开始新一轮的计数。

解码器必须要有机制检测这种循环不然会引起类似千年虫的问题在图像的顺序上造成

pic_order_cnt_type

Count的编码方法、POC标识图像的播放顺序。

由于H.264使用了B帧预测使得图像的解码顺序并不一定等于播放顺序但它们之间存在一定的映射关系。

POC可以由frame-num通过映射关系计算得来也可以索性由编码器显式地传送。

H.264中一共定义了3种POC的编码方法这个句法元素就是用来通知解码器该用哪种方法来计算POC。

pic_order_cnt_type

一个非参考帧的接入单元后面紧跟着一个非参考图像指参考帧或参考场的接入单元两个分别包含互补非参考场对的接入单元后面紧跟着一个非参考图像的接入单元一个非参考场的接入单元后面紧跟着另外一个非参考场并且这两个场不能构成一个互补场对。

log2_max_pic_order_cnt_lsb_minus4

delta_pic_order_always_zero_flag

等于1时句法元素

delta_pic_order_cnt[0]和delta_pic_order_cnt[1]不在片头出现并且它们

的值默认为0本句法元素等于0时上述的两个句法元素将在片头出现。

order

num_ref_frames_in_pic_order_cnt_cycle

被用来解码picture

type1时用用于解码POC本句法元素对循环num_ref_frames_in_pic_order_cycle中的每一个元素指定一个偏移。

num_ref_frames

指定参考帧队列可能达到的最大长度解码器依照这个句法元素的值开辟存储区这个存储区用于存放已解码的参考帧H.264规定最多可用16个参考帧本句法元素的值最大为16。

值得注意的是这个长度以帧为单位如果在场模式下应该相应地扩展

gaps_in_frame_num_value_allowed_flag

这个句法元素等于1

时表示允许句法元素frame_num可以不连续。

当传输信道堵塞严重

时编码器来不及将编码后的图像全部发出这时允许丢弃若干帧图像。

在正常情况下每一帧图像都有依次连续的frame_num值解码器检查到如果frame_num不连续便能确定有图像被编码器丢弃。

这时解码器必须启动错误掩藏的机制来近似地恢复这些图像因为这些图像有可能被后续图像用作参考帧。

当这个句法元素等于0时表不允许frame_num不连续即编码器在任何情况下都不能丢弃图像。

这时H.264允许解码器可以不去检查

frame_num的连续性以减少计算量。

这种情况下如果依然发生frame_num不连续表示在传输中发生丢包解码器会通过其他机制检测到丢包的发生然后启动错误掩藏的恢复图像。

PicWidthInMbspic_width_in_mbs_minus11

通过这个句法元素解码器可以计算得到亮度分量以像素为单位的图像宽度

PicWidthInSamplesLPicWidthInMbs×16

PicWidthInSamplesCPicWidthInMbs×8

以上变量PicWidthInSamplesL、PicWidthInSamplesC

分别表示图像

H.264将图像的大小在序列参数集中定义意味着可以在通信过程中随着序列参数集动态地改变图像的大小在后文中可以看到甚至可以将传送的图像剪裁后输出。

本句法元素加1后指明图像高度

PicHeightInMapUnitspic_height_in_map_units_minus11

PicSizeInMapUnitsPicWidthInMbs×PicHeightInMapUnits

图像的高度的计算要比宽度的计算复杂因为一个图像可以是帧也可以是场从这个句法元素可以在帧模式和场模式下分别计算出亮度、色度的高。

值得注意的是这里以map_unit为单位map_unit的含义由后文叙述。

frame_mbs_only_flag

本句法元素等于1时表示本序列中所有图像的编码模式都是帧没有其他编码模式存在本句法元素等于0时

pic_height_in_map_units_minus1的进一步解析步骤。

当frame_mbs_only_flag等于1pic_height_in_map_units_minus1指的是一个picture中帧的高度当frame_mbs_only_flag等于0pic_heght_in_map_units_minus1指的是一个picture中场的高度所以可以得到如下以宏块为单位的图像高度

FrameHeightInMbs(2

frame_mbs_only_flag)×PicHeightInMapUnits

指明本序列是否属于帧场自适应模式。

mb_adaptive_frame_field_flag等于1时表明在本序列中的图像如果不是场模式就是帧场自适应模式等于0时表示本序列中的图像如果不是场模式就是帧模式。

全部是帧对应于frame_mbs_only_flag1的情况。

帧场自适应和场共存。

frame_mbs_only_flag0,

frame_cropping_flag

用于指明解码器是否要将图像裁剪后输出如果是的话后面紧跟着的四个句法元素分别指出左、右、上、

vui的码流结构在本章参考文献1中的附录指明用以表征视频格式等额外信息。

3、图像参数语义

指明熵编码的选择。

本句法元素为0时表示熵编码使用CAVLC本句法元素为1时表示熵编码使用CABAC。

些句法元素作为参数。

本句法元素等于1时表示在片头会有句法元素指明这些参数本句法元素等于0时表示片头不会给出这些参数这些参数使用默认值。

本句法元素加1后指明图像中片组的个数。

H.264中没有专门的句法元素用于指明是否使用片组模式当本句法元素等于0时即只有一个片组表示不使用片组模式后面也不会跟有用于计算片组映射的句法元素。

slice_group_map_type

1当frame_mbs_only_flag等于1时map_units指的就是宏块。

2当frame_mbs_only_falg等于0时又有以下几种情况

帧场自适应模式时map_units指的是宏块对场模式时map_units指的是宏块帧模式时map_units指的是与帧场自适应帧中的宏块对类似

run_length_minus1[i]

用以指明当片组类型等于0时每个片组连续的map_units个数。

top_left[i],bottom_right[i]

slice_group_change_direction_flag

当片组类型等于3、4、5时

SliceGroupChangeRate。

本句法元素表示一个片组的大小从一个图像到下一个的改变的倍数以map_units为单位。

在片组类型等于6时用以指明图像以map_units为单位的大小。

slice_group_id[i]

在片组类型等于6时用以指明某个map_units属于哪个片组。

加1后指明目前参考帧队列的长度即有多少个参考帧包括短期和长期。

值得注意的是当目前解码图像是场模式下参考帧队列的长度应该是本句法元素再乘以2

因为场模式下各帧必须被分解以场对形式存在这里所说的场模式包括图像的场及帧场自适应下的处于场模式的宏块对。

本句法元素的值有可能在片头被重载。

读者可能还记得在序列参数集中有句法元素num_ref_frames也是跟参考帧队列有关它们的区别是num_ref_frames指明参考帧队列的最大值解码器用它的值来分配内存空间num_ref_idx_l0_active_minus1

指明在这个队列中当前实际的、已存在的参考帧的数目这从它的名字“active”中也可以看出来。

编码器要通知解码器某个运动矢量所指向的是哪个参考图像时并不是直接传送该图像的编号而是传送该图像在参考帧队列中的序号。

这个序号并不是在码流中传送的而是编码器和解码器同步地、用相同的方法将参考图像放入队列从而获得一个序号。

这个队列在每解一个图像时甚至是每个片后都会动态地更新。

维护参考帧队列是编解码器十分重要的工作而本句法元素是维护参考帧队列的重要依据。

参考帧队列的复杂的维护机制也正是H.264重要且很有特色的组成部分。

weighted_pred_flag

用以指明是否允许P和SP片的加权预测如果允许在片头会出现用以计算加权预测的句法元素。

weighted_bipred_idc

用以指明是否允许B片的加权预测。

本句法元素等于0时表示使用默认加权预测模式等于1时表示使用显式加权预测模式等于2时表示使用隐式加权预测模式。

pic_init_qp_minus26

取值范围为[-26,25]加26后用以指明亮度分量的量化参数的初始值。

在H.264中量化参数分3个级别给出图像参数集、片头、宏块。

在图像参数集给出的是一个初始值。

pic_init_qs_minus26

色度分量的量化参数是根据亮度分量的量化参数计算出来的本句法元素用以指明计算时用到的参数。

deblocking_filter_control_present_flag

编码器可以通过句法元素显式地控制去块滤波的强度本句法元素指明是在片头是否会有句法元素传递这个控制信息。

如果本句法元素等于0那些用于传递滤波强度的句法元素不会出现解码器将独立地计算出滤波强度。

在P和B片中帧内编码的宏块的邻近宏块可能是采用的帧间编码。

当本句法元素等于1时表示帧内编码的宏块不能用帧间编码的宏块的像素作为自己的预测即帧内编码的宏块只能用邻近帧内编码的宏块的像素作为自己的预测而本句法元素等于0时表示不存在这种限制。

4、片头语句

要注意的是在帧场自适应模式下宏块都是成对出现的这时本句法元素表示的是第几个宏块对对应的第一个宏块的真实地址应该是2×first_mb_in_slice。

slice_type

每个参考帧都有一个依次连续的frame_num作为它们的标识这指明了各图像的解码顺序。

frame_num所能达到了最大值由前文序列参数集中的句法元素log2_max_frame_num_minus4推出。

事实上我们在表中可以看到frame_num的出现没有if语句限定条件这表明非参考帧的片头也会出现frame_num。

只是当该个图像是参考帧时

它所携带的这个句法元素在解码时才有意义。

见表6.22所示的例子。

H.264对frame_num的值作了如下规定当参数集中的句法元素

gaps_in_frame_num_value_allowed_flag等于0时每个图像的frame_num值是其前一个参考帧的frame_num值加1。

这句话包含有两层意思。

当gaps_in_frame_num_value_allowed_flag等于0时即

frame_num连续的情况下每个图像的frame_num由前一个参考帧图像对应的值加1着重点是“前一个参考帧”。

在表6.22中第3个图像是B帧按照定义它的frame_nun值应是前一个参考帧即第2个图像对应的值加1即为2第4个图像是P帧由于该序列B帧都不作为参考帧

所以对于该图像来说定义中所谓的“前一个参考帧”仍旧是指的第2个图像所以对于第4个图像来说它的frame_num的取值和第3个图像一样也为2。

相同的情况也发生在第6和第8帧上。

前面我们曾经提到对于非参考帧来说它的frame_num值在解码过程中是没有意义的因为frame_num值是参考帧特有的它的主要作

H.264并没有在非参考帧图像中取消这一句法元素原因是在POC的第二种和第三种解码方法中可以通过非参考帧的frame_num值计算出它们的POC值。

当gaps_in_frame_num_value_allowed_flag等于1前文已经提到这时若网络拥塞编码器可以将编码后的若干图像丢弃而不用另行通知解码器。

在这种情况下解码器必须有机制将缺失的frame_num及所对应的图像填补否则后续图像若将运动矢量指向缺失的图像将会产生解码错误。

field_pic_flag

这是在片层标识图像编码模式的唯一一个句法元素。

所谓的编码模式是指的帧编码、场编码、帧场自适应编码。

当这个句法元素取值为1时属于场编码0时为非场编码。

序列参数集中的句法元素frame_mbs_only_flag和

mb_adaptive_frame_field_flag再加上本句法元素共同决定图像的编码模式如图6.7所示。

在序列参数集中我们已经能够计算出图像的高和宽但需要指出的是这个高是指该序列中图像的帧的高度而一个实际的图像可能是帧也可能是场对于图像的实际高度应进一步作如下处理

/(1field_pic_flag)

亮度分量PicHeightInSamplesLPicHeightInMbs×16

色度分量PicHeightInSamplesCPicHeightInMbs×8

PicSizeInMbsPicWidthInMbs×PicHeightInMbs

前文已提到frame_num是参考帧的标识但是在解码器中并不是直接引用的frame_num值而是引用由frame_num进一步计算出来的变量PicNum的值由frame_num映射到PicNum的算法。

这里介绍在该算法中用到的两个变量MaxPicNum和CurrPicNum。

MaxPicNum

表征PicNum的最大值。

PicNum和frame_num一样也是嵌在循环中当达到这个最大值时PicNum将从0开始重新计数。

如果field_pic_flag0,

当前图像的PicNum值。

在计算PicNum的过程中当前图像的PicNum值是由frame_num直接算出在解某个图像时要将已经解码的各参考帧的PicNum重新计算一遍新的值参考当前图像的PicNum值得来。

如果field_pic_flag0,

Frame_num是对帧编号的也就是说如果在场模式下同属一个场对的顶场和底场两个图像的frame_num的值是相同的。

在帧或帧场自适应模式下就直接将图像的frame_num赋给PicNum而在场模式下将2×frame_num和2×frame_num1两个值分别赋给两个场。

2×frame_num1这个值永远被赋给当前场解码到当前场对的下一个场时刚才被赋为2×frame_num1的场的PicNum值被重新计算为

2×frame_num而将2×frame_num1赋给新的当前场。

bottom_field_flag

等于1时表示当前图像是属于底场等于0时表示当前图像是属于顶场。

idr_pic_id

IDR图像的标识。

不同的IDR图像有不同的idr_pic_id值。

值得注意的是IDR图像不等价于I图像只有在作为IDR图像的I帧才有这个句法元素。

在场模式下IDR帧的两个场有相同的idr_pic_id

值。

idr_pic_id的取值范围是[0,65535]和frame_num类似当它的值超出这个范围时它会以循环的方式重新开始计数。

pic_order_cnt_lsb

在POC的第一种算法中本句法元素来计算POC值在POC的第一种算法中是显式地传递POC的值而其他两种算法是通过frame_num来映射POC的值。

注意这个句法元素的读取函数是

log2_max_pic_order_cnt_lsb_minus4加4个比特而得到。

pic_order_cnt_lsb

MaxPicOrderCntLsb

如果是在场模式下场对中的两个场都各自被构造为一个图像它们有各自的POC算法来分别计算两个场的POC值也就是一个场对拥有一对POC值而在是帧模式或是帧场自适应模式下一个图像只能根据片头的句法元素计算出一个POC

frame_mbs_only_flag不为1时每个帧或帧场自适应的图像在解码完后必须分解为两个场以供后续图像中的场作为参考图像。

所以当

frame_mb_only_flag不为1时帧或帧场自适应中包含的两个场也必须

有各自的POC值。

通过本句法元素可以在已经解开的帧或帧场自适应图像的POC基础上新映射一个POC值并把它赋给底场。

当然像句法表指出的那样这个句法元素只用在POC

delta_pic_order_cnt[0]delta_pic_order_cnt[1]

前文已经提到POC的第二和第三种算法是从frame_num映射得来这两个句法元素用于映射算法。

delta_pic_order_cnt[0]用于帧编码方式下的底场和场编码方式的场delta_pic_order_cnt[1]用于帧编码方式下的顶场。

redundant_pic_cnt

指出在B图像的直接预测的模式下用时间预测还是用空间预测。

1表示空间预测0表示时间预测。

num_ref_idx_active_override_flag

在图像参数集中我们看到已经出现句法元素num_ref_idx_l0_active_minus1和

num_ref_idx_l1_active_minus1指定当前参考帧队列中实际可用的参考帧的数目。

在片头可以重载这对句法元素以给某特定图像更大的灵活度。

这个句法元素就是指明片头是否会重载如果该句法元素等于1

下面会出现新的num_ref_idx_l0_active_minus1和

num_ref_idx_l0_active_minus1、num_ref_idx_l1_active_minus1

如上个句法元素中所介绍这是重载的num_ref_idx_l0_active_minus1

cabac_init_idc

SliceQPY26pic_init_qp_minus26slice_qp_delta

块头三层给出的前两层各自给出一个偏移值这个句法元素就是片层的偏移。

sp_for_switch_flag

与slice_qp_delta的与语义相似用在SI和SP中由下式计算

QSY26pic_init_qs_minus26slice_qs_delta

H.264规定一套可以在解码器端独立地计算图像中各边界的滤波强度进行滤波的算法。

除了解码器独立计算之外编码器也可以传递句法元素来干涉滤波强度这个句法元素指定了在块的边界是否要用滤波同时指明那个块的边界不用块滤波。

FilterOffsetAslice_alpha_c0_offset_div2

slice_alpha_c0_offset_div2值的范围是[-6,6]。

Min(slice_group_change_cycle×SliceGroupChangeRate,

PicSizeIn

Ceil(Log2(PicSizeInMapUnits÷SliceGroupChangeRate1))位比特表示

[0,Ceil(PicSizeInMapUnits÷SliceGroupChangeRate)]。

每一个使用帧间预测的图像都会引用前面已解码的图像作为参考帧。

如前文所述编码器给每个参考帧都会分配一个唯一性的标识

即句法元素frame_num。

但是当编码器要指定当前图像的参考图像时并不是直接指定该图像的frame_num值而是使用通过下面步骤最终得出的ref_id号如图6.8所示。

其中从frame_num到变换到变量PicNum主要是考虑到场模式的需要当序列中允许出现场时每个非场的图像帧或帧场自适应

定一个标识

PicNum的值通常都比较大而在帧间预测时需要为每个运动矢量都指明相对应的参考帧的标识如果这个标识选用PicNum开销就会比

较大所以H.264又将PicNum映射为一个更小的变量ref_id。

在编码器和解码器都同步地维护一个参考帧队列每解码一个片就将该队列刷新一次把各图像按照特定的规则进行排序排序后各图像在队列中的序号就是该图像的ref_id值。

在下文中我们可以看到在宏块层表示参考图像的标识就是ref_id维护队列时两个重要操作重排序Reordering和

ref_pic_list_reordering_flag_l0

指明是否进行重排序操作。

这个句法元素等于1时表明紧跟着会有一系列句法元素用于参考帧队列的重排序。

ref_pic_list_reordering_flag_l1

与句法元素

abs_diff_pic_num_minus1或long_term_pic_num配合指明执行哪种重排序操作具体语义见表6.23。

在对短期参考帧重排序时指明重排序图像与当前图像预测值的差值取值范围是[0,

MaxPicNum1]见表

从上文可以看到每组reordering_of_pic_nums_idc、

abs_diff_pic_num_minus1或reordering_of_pic_nums_idc、

long_term_pic_num只能对一个图像操作而通常情况下都需要对一组图像重排序所以在码流中一般会有个循环反复出现这些重排序的句法元素如图6.9所示循环直到reordering_of_pic_nums_idc等于3结束我们在表6.22中也可以看到这种情况。

给出参考帧列表中参考图像所有亮度的加权系数取值范围是[0,7]。

给出参考帧列表中参考图像所有色度的加权系数取值范围是[0,7]。

luma_weight_10_flag

其值等于1时指的是在参考图像列表0中的亮度的加权系数存在等于0时在参考图像列表0中的亮度的加权系数不存在。

luma_weight_10[i]

用参考序列0预测亮度值时所用的加权系数取值范围是[-128,127]。

如果luma_weight_10_flag

is0对于

RefPicList0[i]的luma_weight_10[i]

luma_offset_10[i]

用参考序列0预测亮度值时所用的加权系数的额外偏移。

luma_offset_10[i]

luma_weight_10_flag0对于RefPicList0[i]的luma_offset_10[i]0。

chroma_weight_10_flag、chroma_weight_10[i][j]、

chroma_offset_10[i][j]与上述三个类似不同的是这三个句法元素是用在色度预测。

luma_weight_11_flag、luma_weight_11、luma_offset_11、

chroma_weight_11_flag、chroma_weight_11、chroma_offset_11等句法元素与luma_weight_10_flag、luma_weight_10、luma_offset_10、

chroma_weight_10_flag、chroma_weight_10、chroma_offset_10的语义相

前文介绍的重排序Reordering操作是对参考帧队列重新排序

仅在当前图像是IDR图像时出现这个句法元素指明是否要将前面已解码的图像全部输出。

图像时出现这一句法元素。

这个句法元素指明是否使用长期参考这个机制。

如果取值为1表明使用长期参考并且每个IDR图像被解码后自动成为长期参考帧否则取值为0IDR图像被解码后自动成为短期参考帧。

adaptive_ref_pic_marking_mode_flag

memory_management_control_operation

在自适应标记

Marking模式中指明本次操作的具体内容具体语义见表6.25。

表6.25

memory_management_control_operation等于3或1时由这个句法元素可以计算得到需要操作的图像在短期参考队列中的序号。

参考帧队列中必须存在这个图像。

long_term_pic_num

当memory_management_control_operation值等于2时从此句法元素中得到所要操作的长期参考图像的序号。

long_term_frame_idx

当memory_management_control_operation等

此句法元素的值减1指明长期参考队列的最大数目。

max_long_term_frame_idx_plus1的取值范围是

数据字节对齐即数据从下一个字节的第一个比特开始如果还没有字节对齐将出现若干个cabac_alignment_one_bit作为填充。

mb_skip_run

当图像采用帧间预测编码时H.264允许在图像平坦的区域使用“跳跃”块“跳跃”块本身不携带任何数据解码器通过周围已重建的宏块的数据来恢复“跳跃”块。

当熵编码为CAVLC或CABAC

时“跳跃”块的表示方法不同。

当entropy_coding_mode_flag为1即熵编码为CABAC时是每个“跳跃”块都会有句法元素mb_skip_flag指明

当entropy_coding_mode_flag等于0即熵编码为CAVLC时用一种行程的方法给出紧连着的“跳跃”块的数目即句法元素mb_skip_run。

mb_skip_run的取值范围[0,PicSizeInMbs

mb_skip_flag

属的宏块对是帧模式还是场模式。

mb_field_decoding_flag等于0则当前宏块对是帧宏块对等于1该宏块对是一个场宏块对。

如果一个宏块对的两个宏块句法结构中都没有出现这个句法元素即它们都是“跳

这个宏块对的mb_field_decoding_flag的值等于左边的宏块对的

mb_field_decoding_flag的值否则这个宏块对的mb_field_decoding_flag的值等于上边同属于一个片的宏块对的mb_field_decoding_flag的值如果当前宏块对的左边和上方都没有邻居宏块对这个宏块对的mb_field_decoding_flag的值等于0即帧模式。

mb_type

指明当前宏块的类型。

H.264规定不同的片中允许出现的宏块类型也不同。

在各种片类型中允许出现的宏块种类见表6.26。

可以看到I片中只允许出现I宏块而P片中既可以出现P宏块也可以出现I宏块。

也就是说在帧间预测的图像中也可以包括帧内预测的图像。

其他片也有类似情况。

更进一步来看H.264也定义了比以往视频编码标准更多的宏块类型。

具体来说在帧间预测模式下宏块可以有7种运动矢量的划分方法。

在帧内预测模式下如果是帧内16×16预测宏块有4种预测方法即4种类型如果是帧内4×4预测这时每个4×4块可以有9种预测方法整个宏块共有144种类型。

mb_type并不能描述以上所有有关宏块类型的信息。

mb_type作为出现在宏块层的第一个句法元素它描述跟整个宏块有关的基本的类型信息。

在不同的片中mb_type的定义是不同的下面我们分别讨论

表中Intra_4×4表示使用帧内4×4预测Intra_16×16表示使用帧内

16×16预测。

当使用帧内16×16时类型名称由了如下的结构组成

I_16×16_x_y_z

其中x对应于表中“帧内16×16的预测模式”字段的值y对应于表中“色度CBP”字段的值z对应于表中“亮度CBP”的值。

①帧内16×16的预测模式当使用帧内16×16预测时指定使用何种预测方式帧内16×16共有4种预测模式。

②CodedBlockPatternLuma指定当前宏块色度分量的CBP

CBPCodedBlockPattern是指子宏块残差的编码方案。

该变量详细语

义见coded_block_pattern条目。

③亮度CBP指定当前宏块亮度分量的CBP详细语义见coded_block_pattern条目。

我们看到帧内16×16宏块类型的mb_type语义原比其他宏块类型的复杂这是因为当使用帧内16×16时整个宏块是一个统一的整体

宏块中各子宏块、4×4小块的预测模式信息都是相同的所以可以把这些信息放入mb_type以减少码流。

其他宏块类型的这些信息必须在各子块中另外用句法元素指明。

在表6.28中Pred_L0表示用参考列表L0即前向预测。

P片中的宏块类型可参见表6.28和表6.27。

当mb_type值为04时mb_type的含义见表6.28当mb_type值为530时mb_type的含义见表6.27用

mb_type值减5所得值来进行查找。

预测模式mb_typen预测模式是mb_type的函数n是宏块的第n个分区。

B片中的宏块类型可参见表6.29和表6.27。

如果当前宏块是属于B片且mb_type值为022mb_type的含义见表6.29当mb_type值为2348

时mb_type的含义见表6.27用mb_type值减23所得值来进行查找。

表中Pred_L0表示使用L0即前向预测Pred_L1表示使用L1

即后向预测Bipred表示双向预测Direct表示直接预测模式。

预测模式mb_type,n是mb_type的函数n是宏块的第n个分区。

pcm_byte[i]

像素值。

前256个pcm_byte[i]的值代表亮度像素的值下一个(256×(ChromaFormatFactor1))/2个pcm_byte[i]的值代表Cb分量的值。

最后一个(256×(Chroma

coded_block_pattern

即CBP指亮度和色度分量的各小块的残差的编码方案所谓编码方案有以下几种

1所有残差包括DC、AC都编码

这个句法元素同时隐含了一个宏块中亮度、色度分量的CBP所以第一步必须先分别解出各分量各自CBP的值。

其中两个色度分量的CBP是相同的。

变量CodedBlockPatternLuma是亮度分量的CBP变量CodedBlocPatternChroma是色度分量的CBP。

CodedBlockPatternLumacoded_block_pattern

CodedBlockPatternChromacoded_block_pattern

对于Intra_16×16宏块类型CodedBlockPatternLuma

CodedBlockPatternChroma的值不是由本句法元素给出而是通过mb_type得到。

①CodedBlockPatternLuma是一个16位的变量其中只有最低四位有定义。

由于非Intra_16×16的宏块不单独编码DC系数所以这个变量只指明两种编码方案残差全部编码或全部不编码。

变量的最低位比特从最低位开始每一位对应一个子宏块该位等于1时表明对应子宏块残差系数被传送该位等于0时表明对应子宏块残差全部不被传送解码器把这些残差系数赋为0。

②CodedBlockPatternChroma当值为0、1、2时有定义见表

表6.30

在宏块层中的量化参数的偏移值。

mb_qp_delta值的范围是[-26,25]。

量化参数是在图像参数集、片头、宏块分三层给出的最终用于解码的量化参数由以下公式得到

其中是当前宏块按照解码顺序排列的前一个宏块的量化参数我们可以看到mb_qp_delta所指示的偏移是前后两个宏块之间的偏移。

片中第一个宏块的是由下式给出

prev_intra4×4_pred_mode_flag[luma4×4BlkIdx]

rem_intra4×4_pred_mode[luma4×4BlkIdx]

prev_intra4×4_pred_mode_flag用来指明帧内预测中亮度分量的预测模式的预测值是否是实际预测模式。

如果是就不需另外再传预测模式

如果不是就由rem_intra4×4_pred_mode指定实际预测模式。

用参考帧列表L0进行预测时即前向预测时参考图像在参考帧列表中的序号。

其中mbPartIdx是宏块分区的序号。

如果当前宏块是非场宏块则ref_idx_10[mbPartIdx]值的范围是[0,

如果当前宏块是场宏块宏块所在图像是场当图像是帧场自适应时当前宏块处于场编码的宏块对ref_idx_10[mbPartIdx]值的范围

是0到2×num_ref_idx_10_active_minus11如前所述此时参考帧队列的帧都将拆成场故参考队列长度加倍。

间的差。

mbPartIdx是宏块分区的序号。

compIdx0时为水平运动矢量compIdx1时为垂直运动矢量。

指明子宏块的预测类型在不同的宏块类型中这个句法元素的语义不一样。

1P宏块

mvd_10[mbPartIdx][subMbPartIdx][compIdx]

与10节中定义

mvd_10相同除了subMbPartIdx子宏块中的索引值。

mvd_11[mbPartIdx][subMbPartIdx][compIdx]

coeff_token

如果trailing_ones_sign_flag0相应的拖尾系数是1

如果trailing_ones_sign_flag1相应的拖尾系数是-1。

total_zeros

如果significant_coeff_flag[i]0在位置为i处的变换系数为零

如果significant_coeff_flag[i]1在位置为i处的变换系数不为零。

如果last_significant_coeff_flag[i]1这个块中随后的系数都为零

coeff_sign_flag[i]

的句法是经过精心设计的构成句法的各句法元素既相互依赖又相互独立。

依赖是为了减少冗余信息提高编码效率而独立是为了使通信更加可靠在错误发生时限制错误的扩散。

但是依赖和独立又是矛盾的往往要在它们之间作取舍。

在实现H.264的编解码器时同样有速度和健壮性这样一组矛盾的关系既要在现有硬件平台上提高编解码的速度又要作充分的安全检查建立异常处理机制。

如果能详细考察句法元素间的依赖与独立关系充分利用H.264各句法

四、H.264语句语义代码实现解析

以下是一个demo例子实现读取out.h264的H264流的语句语义。

github地址为https://github.com/wangyongyao1989/WyFFmpeg/tree/main/h264

代码截图

com.example.myyffmpeg.fragment;import

android.os.Bundle;

android.widget.FrameLayout;import

import

androidx.lifecycle.ViewModelProviders;import

com.example.myyffmpeg.FFViewModel;

import

com.example.myyffmpeg.databinding.FragmentH264LayoutBinding;

import

com.wangyongyao.common.utils.FileUtils;

import

com.wangyongyao.h264.H264CallJni;

import

com.wangyongyao.h264.view.X264CameraPreView;/***

author

https://github.com/wangyongyao1989*

Create

com.example.myyffmpeg.fragment*/

public

H264Fragment.class.getSimpleName();private

Button

mX264CameraPreView;Overridepublic

View

FragmentH264LayoutBinding.inflate(inflater);return

mBinding.getRoot();}Overridepublic

void

mBinding.x264Show;}Overridepublic

void

ViewModelProviders.of(requireActivity()).get(FFViewModel.class);}Overridepublic

void

{mH264Back.setOnClickListener(view

{mFfViewModel.getSwitchFragment().postValue(FFViewModel.FRAGMENT_STATUS.MAIN);});mBtn1.setOnClickListener(view

{String

FileUtils.getModelFilePath(getActivity(),

out.h264);//向JNI层传入out.h264文件的路径mH264CallJni.testH264(h264FilePath);});mBtn2.setOnClickListener(view

{if

X264CameraPreView(getActivity());}mX264Show.addView(mX264CameraPreView);});}}

JNI层代码

https://github.com/wangyongyao1989

Created

com/wangyongyao/h264/H264CallJni;H264NaluParse

JNIEXPORT

env-GetStringUTFChars(dataPath,

cDataPath);if

H264NaluParse();}h264NaluParse-setHevcNalDataPath(cDataPath);env-ReleaseStringUTFChars(dataPath,

cDataPath);}static

env-FindClass(java_call_jni_class);//

注册native方法jint

env-FindClass(java_call_jni_class);if

(env

{env-UnregisterNatives(clazz);}}

C/C层代码

H264NaluParse.cpp中获取从Java层传入的文件路径之后打开文件并读取out.h264数据到std::vectoruint8_t

buffer集合中

https://github.com/wangyongyao1989

Created

h264include/h264nal/h264_bitstream_parser.hH264NaluParse::H264NaluParse()

new

h264nal::H264BitstreamParserState;

}H264NaluParse::~H264NaluParse()

{release();

H264NaluParse::setHevcNalDataPath(const

char

buffer(size);fread(reinterpret_castchar

*(buffer.data()),

infp);fclose(infp);LOGE(buffer.data()

:%d,

bitstreamstd::unique_ptrh264nal::H264BitstreamParser::BitstreamState

bitstream

h264nal::H264BitstreamParser::ParseBitstream(buffer.data(),

buffer.size(),

bitstream_parser_state-GetSps(0)-sps_data-pic_height_in_map_units_minus1;uint32_t

bitstream_parser_state-GetSps(0)-sps_data-pic_width_in_mbs_minus1;uint32_t

frame_mbs_only_flag

bitstream_parser_state-GetSps(0)-sps_data-frame_mbs_only_flag;//

计算宽高int

(pic_height_in_map_units_minus1

frame_mbs_only_flag);//宽高LOGE(SPS:height

%d,

width);//色度格式LOGE(SPS:chroma_format_idc

%d,bitstream_parser_state-GetSps(0)-sps_data-chroma_format_idc);uint32_t

frameRate;uint32_t

bitstream_parser_state-GetSps(0)-sps_data-vui_parameters-time_scale;if

{uint32_t

bitstream_parser_state-GetSps(0)-sps_data-vui_parameters-num_units_in_tick;uint32_t

timeScale

bitstream_parser_state-GetSps(0)-sps_data-vui_parameters-time_scale;if

(numUnitsInTick

30;}//帧率LOGE(SPS:KEY_FRAME_RATE

%d,

bitstream_parser_state;bitstream_parser_state

nullptr;}

该类解析出H.264流中的Nalu存放在std::vectorNaluIndex

BitstreamState结构体

assignmentsBitstreamState(const

BitstreamState)

delete;BitstreamState(BitstreamState)

operator(const

unitsstd::vectorstd::unique_ptrstruct

H264NalUnitParser::NalUnitStatenal_units;};

NaluIndex结构体

../h264include/h264nal/h264_bitstream_parser.h#include

stdio.h#include

../h264include/h264nal/h264_bitstream_parser_state.h

#include

../h264include/h264nal/h264_common.h

#include

../h264include/h264nal/h264_nal_unit_parser.hnamespace

The

http://www.itu.int/rec/T-REC-H.264std::vectorH264BitstreamParser::NaluIndex

H264BitstreamParser::FindNaluIndices(const

uint8_t*

reads/checks.std::vectorNaluIndex

sequences;if

kNaluShortStartSequenceSize;for

(size_t

sequences.rend())it-payload_size

index.start_offset

it-payload_start_offset;sequences.push_back(index);i

3;}

sequences.rend())it-payload_size

length

std::unique_ptrH264BitstreamParser::BitstreamState

H264BitstreamParser::ParseBitstream(const

uint8_t*

length,H264BitstreamParserState*

add_checksum)

std::make_uniqueBitstreamState();//

(1)

H264NalUnitParser::ParseNalUnit(data[nalu_index.payload_start_offset],

nalu_index.payload_size,bitstream_parser_state,

add_checksum);if

nalu_index.payload_start_offset;nal_unit-length

nalu_index.payload_size;bitstream-nal_units.push_back(std::move(nal_unit));}return

bitstream;

}std::unique_ptrH264BitstreamParser::BitstreamState

H264BitstreamParser::ParseBitstream(const

uint8_t*

std::make_uniqueBitstreamState();//

parse

add_offset;bitstream-add_length

add_length;bitstream-add_parsed_length

add_parsed_length;bitstream-add_checksum

add_checksum;return

H264BitstreamParser::BitstreamState::fdump(FILE*

outfp,int

从H.264流中解压缩RBSP并从提供的缓冲区解析比特流状态。

FindNaluIndices()函数

通过0x000001或0x00000001起始码为标志切割出Nalu

/**

../h264include/h264nal/h264_nal_unit_header_parser.h#include

stdio.h#include

../h264include/h264nal/h264_bitstream_parser_state.h

#include

../h264include/h264nal/h264_common.hnamespace

h264nal

http://www.itu.int/rec/T-REC-H.264//

Unpack

buffer.std::unique_ptrH264NalUnitHeaderParser::NalUnitHeaderStateH264NalUnitHeaderParser::ParseNalUnitHeader(const

uint8_t

bit_buffer(unpacked_buffer.data(),

ParseNalUnitHeader(bit_buffer);}bool

H264NalUnitHeaderParser::GetNalUnitType(const

uint8_t

ParseNalUnitHeader(bitBuffer);if

(!naluHeader)

static_castNalUnitType(naluHeader-nal_unit_type);return

true;}std::unique_ptrH264NalUnitHeaderParser::NalUnitHeaderStateH264NalUnitHeaderParser::ParseNalUnitHeader(rtc264::BitBuffer

*bit_buffer)

std::make_uniqueNalUnitHeaderState();//

forbidden_zero_bit

(!bit_buffer-ReadBits(nal_unit_header-forbidden_zero_bit,

1))

(!bit_buffer-ReadBits(nal_unit_header-nal_ref_idc,

2))

(!bit_buffer-ReadBits(nal_unit_header-nal_unit_type,

5))

||nal_unit_header-nal_unit_type

||nal_unit_header-nal_unit_type

21)

(!bit_buffer-ReadBits(nal_unit_header-svc_extension_flag,

1))

(nal_unit_header-svc_extension_flag

{//

nal_unit_header_svc_extension()nal_unit_header-nal_unit_header_svc_extension

H264NalUnitHeaderSvcExtensionParser::ParseNalUnitHeaderSvcExtension(bit_buffer);if

(nal_unit_header-nal_unit_header_svc_extension

nullptr)

(!bit_buffer-ReadBits(nal_unit_header-avc_3d_extension_flag,

1))

H264NalUnitHeaderParser::NalUnitHeaderState::fdump(FILE*

outfp,

indent_level_incr(indent_level);fdump_indent_level(outfp,

forbidden_zero_bit:

forbidden_zero_bit);fdump_indent_level(outfp,

nal_ref_idc:

nal_ref_idc);fdump_indent_level(outfp,

nal_unit_type:

indent_level);nal_unit_header_svc_extension-fdump(outfp,

indent_level);}}

avc_3d_extension_flag);}}indent_level

indent_level_decr(indent_level);fdump_indent_level(outfp,

});}

../h264include/h264nal/h264_sps_parser.h#define

inttypes.h

../h264include/h264nal/h264_common.h

#include

../h264include/h264nal/h264_vui_parameters_parser.hnamespace

h264nal

http://www.itu.int/rec/T-REC-H.264//

Unpack

buffer.std::unique_ptrH264SpsDataParser::SpsDataStateH264SpsDataParser::ParseSpsData(const

uint8_t

bit_buffer(unpacked_buffer.data(),

ParseSpsData(bit_buffer);}std::unique_ptrH264SpsDataParser::SpsDataStateH264SpsDataParser::ParseSpsData(rtc264::BitBuffer

*bit_buffer)

std::make_uniqueSpsDataState();//

profile_idc

(!bit_buffer-ReadBits(sps_data-profile_idc,

8))

(!bit_buffer-ReadBits(sps_data-constraint_set0_flag,

1))

(!bit_buffer-ReadBits(sps_data-constraint_set1_flag,

1))

(!bit_buffer-ReadBits(sps_data-constraint_set2_flag,

1))

(!bit_buffer-ReadBits(sps_data-constraint_set3_flag,

1))

(!bit_buffer-ReadBits(sps_data-constraint_set4_flag,

1))

(!bit_buffer-ReadBits(sps_data-constraint_set5_flag,

1))

(!bit_buffer-ReadBits(sps_data-reserved_zero_2bits,

2))

(!bit_buffer-ReadBits(sps_data-level_idc,

8))

(!bit_buffer-ReadExponentialGolomb((sps_data-seq_parameter_set_id)))

{return

(!bit_buffer-ReadExponentialGolomb((sps_data-chroma_format_idc)))

{return

(!bit_buffer-ReadBits(sps_data-separate_colour_plane_flag,

1))

(!bit_buffer-ReadExponentialGolomb((sps_data-bit_depth_luma_minus8)))

{return

(!bit_buffer-ReadExponentialGolomb((sps_data-bit_depth_chroma_minus8)))

{return

qpprime_y_zero_transform_bypass_flag

u(1)if

(!bit_buffer-ReadBits(sps_data-qpprime_y_zero_transform_bypass_flag,1))

{return

seq_scaling_matrix_present_flag

u(1)if

(!bit_buffer-ReadBits(sps_data-seq_scaling_matrix_present_flag,

1))

(sps_data-seq_scaling_matrix_present_flag)

{for

seq_scaling_list_present_flag[i]

u(1)if

(!bit_buffer-ReadBits(bits_tmp,

1))

nullptr;}sps_data-seq_scaling_list_present_flag.push_back(bits_tmp);if

(sps_data-seq_scaling_list_present_flag[i])

{//

sps_data-scaling_list(bit_buffer,

16,sps_data-UseDefaultScalingMatrix4x4Flag);}

else

sps_data-scaling_list(bit_buffer,

64,sps_data-UseDefaultScalingMatrix4x4Flag);}}}}}//

ue(v)if

(!bit_buffer-ReadExponentialGolomb((sps_data-log2_max_frame_num_minus4)))

{return

(!bit_buffer-ReadExponentialGolomb((sps_data-pic_order_cnt_type)))

{return

log2_max_pic_order_cnt_lsb_minus4

ue(v)if

(!bit_buffer-ReadExponentialGolomb((sps_data-log2_max_pic_order_cnt_lsb_minus4)))

{return

delta_pic_order_always_zero_flag

u(1)if

(!bit_buffer-ReadBits(sps_data-delta_pic_order_always_zero_flag,

1))

(!bit_buffer-ReadSignedExponentialGolomb((sps_data-offset_for_non_ref_pic)))

{return

(!bit_buffer-ReadSignedExponentialGolomb((sps_data-offset_for_top_to_bottom_field)))

{return

num_ref_frames_in_pic_order_cnt_cycle

ue(v)if

(!bit_buffer-ReadExponentialGolomb((sps_data-num_ref_frames_in_pic_order_cnt_cycle)))

{return

sps_data-num_ref_frames_in_pic_order_cnt_cycle;i)

{//

(!bit_buffer-ReadSignedExponentialGolomb(golomb_tmp))

{return

nullptr;}sps_data-offset_for_ref_frame.push_back(golomb_tmp);}}//

max_num_ref_frames

(!bit_buffer-ReadExponentialGolomb((sps_data-max_num_ref_frames)))

{return

gaps_in_frame_num_value_allowed_flag

u(1)if

(!bit_buffer-ReadBits(sps_data-gaps_in_frame_num_value_allowed_flag,1))

{return

(!bit_buffer-ReadExponentialGolomb((sps_data-pic_width_in_mbs_minus1)))

{return

(!bit_buffer-ReadExponentialGolomb((sps_data-pic_height_in_map_units_minus1)))

{return

(!bit_buffer-ReadBits(sps_data-frame_mbs_only_flag,

1))

(!sps_data-frame_mbs_only_flag)

{//

(!bit_buffer-ReadBits(sps_data-mb_adaptive_frame_field_flag,

1))

(!bit_buffer-ReadBits(sps_data-direct_8x8_inference_flag,

1))

(!bit_buffer-ReadBits(sps_data-frame_cropping_flag,

1))

(!bit_buffer-ReadExponentialGolomb((sps_data-frame_crop_left_offset)))

{return

(!bit_buffer-ReadExponentialGolomb((sps_data-frame_crop_right_offset)))

{return

(!bit_buffer-ReadExponentialGolomb((sps_data-frame_crop_top_offset)))

{return

(!bit_buffer-ReadExponentialGolomb((sps_data-frame_crop_bottom_offset)))

{return

(!bit_buffer-ReadBits((sps_data-vui_parameters_present_flag),

1))

(sps_data-vui_parameters_present_flag)

{//

vui_parameters()sps_data-vui_parameters

H264VuiParametersParser::ParseVuiParameters(bit_buffer);if

nullptr)

H264SpsDataParser::SpsDataState::getChromaArrayType()

noexcept

H264SpsDataParser::SpsDataState::scaling_list(rtc264::BitBuffer

*bit_buffer,

sizeOfScalingList,std::vectoruint32_t

noexcept

(!bit_buffer-ReadSignedExponentialGolomb(delta_scale))

{return

(useDefaultScalingMatrixFlag.size()

{useDefaultScalingMatrixFlag.push_back(0);}useDefaultScalingMatrixFlag[i]

nextScale

{scalingList.push_back(0);}scalingList[j]

(nextScale

buffer.std::shared_ptrH264SpsParser::SpsState

uint8_t

bit_buffer(unpacked_buffer.data(),

ParseSps(bit_buffer);}std::shared_ptrH264SpsParser::SpsState

H264SpsParser::ParseSps(rtc264::BitBuffer

*bit_buffer)

seq_parameter_set_data()sps-sps_data

H264SpsDataParser::ParseSpsData(bit_buffer);if

(sps-sps_data

nullptr;}rbsp_trailing_bits(bit_buffer);return

sps;}uint32_t

H264SpsParser::SpsState::getChromaArrayType()

noexcept

sps_data-getChromaArrayType();}#ifdef

FDUMP_DEFINEvoid

H264SpsDataParser::SpsDataState::fdump(FILE*

outfp,int

indent_level_incr(indent_level);fdump_indent_level(outfp,

profile_idc:

profile_idc);fdump_indent_level(outfp,

%i,

constraint_set0_flag);fdump_indent_level(outfp,

%i,

constraint_set1_flag);fdump_indent_level(outfp,

%i,

constraint_set2_flag);fdump_indent_level(outfp,

%i,

constraint_set3_flag);fdump_indent_level(outfp,

%i,

constraint_set4_flag);fdump_indent_level(outfp,

%i,

constraint_set5_flag);fdump_indent_level(outfp,

reserved_zero_2bits:

reserved_zero_2bits);fdump_indent_level(outfp,

level_idc:

level_idc);fdump_indent_level(outfp,

%i,

%i,separate_colour_plane_flag);}fdump_indent_level(outfp,

%i,

bit_depth_luma_minus8);fdump_indent_level(outfp,

%i,

bit_depth_chroma_minus8);fdump_indent_level(outfp,

qpprime_y_zero_transform_bypass_flag:

%i,qpprime_y_zero_transform_bypass_flag);fdump_indent_level(outfp,

seq_scaling_matrix_present_flag:

%i,seq_scaling_matrix_present_flag);fdump_indent_level(outfp,

{);for

UseDefaultScalingMatrix4x4Flag)

{fprintf(outfp,

UseDefaultScalingMatrix8x8Flag)

{fprintf(outfp,

delta_scale);}fdump_indent_level(outfp,

%i,

log2_max_frame_num_minus4);fdump_indent_level(outfp,

pic_order_cnt_type:

log2_max_pic_order_cnt_lsb_minus4:

%i,log2_max_pic_order_cnt_lsb_minus4);}

else

delta_pic_order_always_zero_flag:

%i,delta_pic_order_always_zero_flag);fdump_indent_level(outfp,

%i,

offset_for_non_ref_pic);fdump_indent_level(outfp,

offset_for_top_to_bottom_field:

%i,offset_for_top_to_bottom_field);fdump_indent_level(outfp,

num_ref_frames_in_pic_order_cnt_cycle:

%i,num_ref_frames_in_pic_order_cnt_cycle);fdump_indent_level(outfp,

offset_for_ref_frame

max_num_ref_frames);fdump_indent_level(outfp,

gaps_in_frame_num_value_allowed_flag:

%i,gaps_in_frame_num_value_allowed_flag);fdump_indent_level(outfp,

%i,

pic_width_in_mbs_minus1);fdump_indent_level(outfp,

pic_height_in_map_units_minus1:

%i,pic_height_in_map_units_minus1);fdump_indent_level(outfp,

frame_mbs_only_flag:

%i,mb_adaptive_frame_field_flag);}fdump_indent_level(outfp,

%i,

direct_8x8_inference_flag);fdump_indent_level(outfp,

frame_cropping_flag:

frame_crop_left_offset);fdump_indent_level(outfp,

%i,

frame_crop_right_offset);fdump_indent_level(outfp,

%i,

frame_crop_top_offset);fdump_indent_level(outfp,

%i,

frame_crop_bottom_offset);}fdump_indent_level(outfp,

%i,vui_parameters_present_flag);if

indent_level);vui_parameters-fdump(outfp,

indent_level_decr(indent_level);fdump_indent_level(outfp,

});}void

H264SpsParser::SpsState::fdump(FILE*

outfp,

indent_level_incr(indent_level);fdump_indent_level(outfp,

indent_level);sps_data-fdump(outfp,

indent_level_decr(indent_level);fdump_indent_level(outfp,

});}#endif

../h264include/h264nal/h264_pps_parser.h#include

stdio.h#include

../h264include/h264nal/h264_common.hnamespace

h264nal

http://www.itu.int/rec/T-REC-H.264//

Unpack

buffer.std::shared_ptrH264PpsParser::PpsState

uint8_t

bit_buffer(unpacked_buffer.data(),

ParsePps(bit_buffer,

chroma_format_idc);}std::shared_ptrH264PpsParser::PpsState

H264PpsParser::ParsePps(rtc264::BitBuffer

*bit_buffer,

parameterspps-chroma_format_idc

chroma_format_idc;//

(!bit_buffer-ReadExponentialGolomb((pps-pic_parameter_set_id)))

{return

(!bit_buffer-ReadExponentialGolomb((pps-seq_parameter_set_id)))

{return

(!bit_buffer-ReadBits((pps-entropy_coding_mode_flag),

1))

bottom_field_pic_order_in_frame_present_flag

u(1)if

(!bit_buffer-ReadBits((pps-bottom_field_pic_order_in_frame_present_flag),

1))

(!bit_buffer-ReadExponentialGolomb((pps-num_slice_groups_minus1)))

{return

(!bit_buffer-ReadExponentialGolomb((pps-slice_group_map_type)))

{return

pps-num_slice_groups_minus1;iGroup)

{//

(!bit_buffer-ReadExponentialGolomb(golomb_tmp))

{return

nullptr;}pps-run_length_minus1.push_back(golomb_tmp);}}

else

pps-num_slice_groups_minus1;iGroup)

{//

(!bit_buffer-ReadExponentialGolomb(golomb_tmp))

{return

nullptr;}pps-top_left.push_back(golomb_tmp);//

bottom_right[iGroup]

(!bit_buffer-ReadExponentialGolomb(golomb_tmp))

{return

nullptr;}pps-bottom_right.push_back(golomb_tmp);}}

else

slice_group_change_direction_flag

u(1)if

(!bit_buffer-ReadBits((pps-slice_group_change_direction_flag),

1))

(!bit_buffer-ReadExponentialGolomb((pps-slice_group_change_rate_minus1)))

{return

(!bit_buffer-ReadExponentialGolomb((pps-pic_size_in_map_units_minus1)))

{return

(!bit_buffer-ReadBits(bits_tmp,

slice_group_id_len))

nullptr;}pps-slice_group_id.push_back(bits_tmp);}}//

ue(v)if

(!bit_buffer-ReadExponentialGolomb((pps-num_ref_idx_l0_active_minus1)))

{return

(!bit_buffer-ReadExponentialGolomb((pps-num_ref_idx_l1_active_minus1)))

{return

(!bit_buffer-ReadBits((pps-weighted_pred_flag),

1))

(!bit_buffer-ReadBits((pps-weighted_bipred_idc),

2))

(!bit_buffer-ReadSignedExponentialGolomb((pps-pic_init_qp_minus26)))

{return

(!bit_buffer-ReadSignedExponentialGolomb((pps-pic_init_qs_minus26)))

{return

(!bit_buffer-ReadSignedExponentialGolomb((pps-chroma_qp_index_offset)))

{return

deblocking_filter_control_present_flag

u(1)if

(!bit_buffer-ReadBits((pps-deblocking_filter_control_present_flag),1))

{return

(!bit_buffer-ReadBits((pps-constrained_intra_pred_flag),

1))

(!bit_buffer-ReadBits((pps-redundant_pic_cnt_present_flag),

1))

(!bit_buffer-ReadBits((pps-transform_8x8_mode_flag),

1))

pic_scaling_matrix_present_flag

u(1)if

(!bit_buffer-ReadBits((pps-pic_scaling_matrix_present_flag),

1))

(pps-pic_scaling_matrix_present_flag)

{uint32_t

max_pic_scaling_list_present_flag

((chroma_format_idc

pps-transform_8x8_mode_flag;for

(uint32_t

max_pic_scaling_list_present_flag;

{//

(!bit_buffer-ReadBits(bits_tmp,

1))

nullptr;}pps-pic_scaling_list_present_flag.push_back(bits_tmp);if

(pps-pic_scaling_list_present_flag[i])

{//

16,pps-UseDefaultScalingMatrix4x4Flag);}

else

64,pps-UseDefaultScalingMatrix4x4Flag);}}}}//

se(v)if

(!bit_buffer-ReadSignedExponentialGolomb((pps-second_chroma_qp_index_offset)))

{return

nullptr;}}rbsp_trailing_bits(bit_buffer);return

pps;}uint32_t

H264PpsParser::PpsState::getSliceGroupIdLen()

noexcept

Ceil(Log2(num_slice_groups_minus1

1))

static_castuint32_t(std::ceil(std::log2(1.0

1)));}//

H264PpsParser::PpsState::scaling_list(rtc264::BitBuffer

*bit_buffer,

sizeOfScalingList,std::vectoruint32_t

noexcept

(!bit_buffer-ReadSignedExponentialGolomb(delta_scale))

{return

(useDefaultScalingMatrixFlag.size()

{useDefaultScalingMatrixFlag.push_back(0);}useDefaultScalingMatrixFlag[i]

nextScale

{scalingList.push_back(0);}scalingList[j]

(nextScale

H264PpsParser::PpsState::fdump(FILE*

outfp,

indent_level_incr(indent_level);fdump_indent_level(outfp,

%i,

pic_parameter_set_id);fdump_indent_level(outfp,

%i,

seq_parameter_set_id);fdump_indent_level(outfp,

%i,

entropy_coding_mode_flag);fdump_indent_level(outfp,

bottom_field_pic_order_in_frame_present_flag:

%i,bottom_field_pic_order_in_frame_present_flag);fdump_indent_level(outfp,

%i,

slice_group_change_direction_flag:

%i,slice_group_change_direction_flag);fdump_indent_level(outfp,

slice_group_change_rate_minus1:

%i,slice_group_change_rate_minus1);}

else

%i,pic_size_in_map_units_minus1);fdump_indent_level(outfp,

slice_group_id

%i,num_ref_idx_l0_active_minus1);fdump_indent_level(outfp,

%i,num_ref_idx_l1_active_minus1);fdump_indent_level(outfp,

weighted_pred_flag:

weighted_pred_flag);fdump_indent_level(outfp,

weighted_bipred_idc:

weighted_bipred_idc);fdump_indent_level(outfp,

pic_init_qp_minus26:

pic_init_qp_minus26);fdump_indent_level(outfp,

pic_init_qs_minus26:

pic_init_qs_minus26);fdump_indent_level(outfp,

%i,

chroma_qp_index_offset);fdump_indent_level(outfp,

deblocking_filter_control_present_flag:

%i,deblocking_filter_control_present_flag);fdump_indent_level(outfp,

%i,constrained_intra_pred_flag);fdump_indent_level(outfp,

redundant_pic_cnt_present_flag:

%i,redundant_pic_cnt_present_flag);fdump_indent_level(outfp,

%i,

transform_8x8_mode_flag);fdump_indent_level(outfp,

pic_scaling_matrix_present_flag:

%i,pic_scaling_matrix_present_flag);fdump_indent_level(outfp,

{);for

UseDefaultScalingMatrix4x4Flag)

{fprintf(outfp,

UseDefaultScalingMatrix8x8Flag)

{fprintf(outfp,

delta_scale);fdump_indent_level(outfp,

%i,second_chroma_qp_index_offset);indent_level

indent_level_decr(indent_level);fdump_indent_level(outfp,

});}

h264nalh264_slice_header_parser.cc

/**

../h264include/h264nal/h264_slice_header_parser.h#define

inttypes.h

../h264include/h264nal/h264_bitstream_parser_state.h

#include

../h264include/h264nal/h264_common.h

#include

../h264include/h264nal/h264_dec_ref_pic_marking_parser.h

#include

../h264include/h264nal/h264_pps_parser.h

#include

../h264include/h264nal/h264_pred_weight_table_parser.h

#include

../h264include/h264nal/h264_ref_pic_list_modification_parser.h

#include

../h264include/h264nal/h264_sps_parser.h

#include

../webrtc/bit_buffer.hnamespace

h264nal

http://www.itu.int/rec/T-REC-H.264//

Unpack

buffer.std::unique_ptrH264SliceHeaderParser::SliceHeaderStateH264SliceHeaderParser::ParseSliceHeader(const

uint8_t

bit_buffer(unpacked_buffer.data(),

nal_ref_idc,

nal_unit_type,bitstream_parser_state);}std::unique_ptrH264SliceHeaderParser::SliceHeaderStateH264SliceHeaderParser::ParseSliceHeader(rtc264::BitBuffer

*bit_buffer,

std::make_uniqueSliceHeaderState();//

input

parametersslice_header-nal_ref_idc

nal_ref_idc;slice_header-nal_unit_type

nal_unit_type;//

(!bit_buffer-ReadExponentialGolomb((slice_header-first_mb_in_slice)))

{return

(!bit_buffer-ReadExponentialGolomb((slice_header-slice_type)))

{return

(!bit_buffer-ReadExponentialGolomb((slice_header-pic_parameter_set_id)))

{return

slice_header-pic_parameter_set_id;if

(bitstream_parser_state-pps.find(pps_id)

bitstream_parser_state-pps.end())

{//

bitstream_parser_state-pps[pps_id];uint32_t

sps_id

(bitstream_parser_state-sps.find(sps_id)

bitstream_parser_state-sps.end())

{//

bitstream_parser_state-sps[sps_id];auto

sps_data

sps-sps_data;slice_header-separate_colour_plane_flag

sps_data-separate_colour_plane_flag;if

(slice_header-separate_colour_plane_flag)

{//

(!bit_buffer-ReadBits((slice_header-colour_plane_id),

2))

u(v)slice_header-log2_max_frame_num_minus4

sps_data-log2_max_frame_num_minus4;uint32_t

frame_num_len

slice_header-getFrameNumLen(slice_header-log2_max_frame_num_minus4);if

(!bit_buffer-ReadBits((slice_header-frame_num),

frame_num_len))

nullptr;}slice_header-frame_mbs_only_flag

sps_data-frame_mbs_only_flag;if

(!slice_header-frame_mbs_only_flag)

{//

(!bit_buffer-ReadBits((slice_header-field_pic_flag),

1))

(!bit_buffer-ReadBits((slice_header-bottom_field_flag),

1))

(!bit_buffer-ReadExponentialGolomb((slice_header-idr_pic_id)))

{return

nullptr;}}slice_header-pic_order_cnt_type

(slice_header-pic_order_cnt_type

{uint32_t

log2_max_pic_order_cnt_lsb_minus4

sps_data-log2_max_pic_order_cnt_lsb_minus4;//

pic_order_cnt_lsb

slice_header-getPicOrderCntLsbLen(log2_max_pic_order_cnt_lsb_minus4);if

(!bit_buffer-ReadBits((slice_header-pic_order_cnt_lsb),pic_order_cnt_lsb_len))

{return

nullptr;}slice_header-bottom_field_pic_order_in_frame_present_flag

pps-bottom_field_pic_order_in_frame_present_flag;if

(slice_header-bottom_field_pic_order_in_frame_present_flag

{//

(!bit_buffer-ReadSignedExponentialGolomb((slice_header-delta_pic_order_cnt_bottom)))

{return

nullptr;}}}slice_header-delta_pic_order_always_zero_flag

sps_data-delta_pic_order_always_zero_flag;if

((slice_header-pic_order_cnt_type

(!slice_header-delta_pic_order_always_zero_flag))

{//

(!bit_buffer-ReadSignedExponentialGolomb(sgolomb_tmp))

{return

nullptr;}slice_header-delta_pic_order_cnt.push_back(sgolomb_tmp);if

(slice_header-bottom_field_pic_order_in_frame_present_flag

{//

(!bit_buffer-ReadSignedExponentialGolomb(sgolomb_tmp))

{return

nullptr;}slice_header-delta_pic_order_cnt.push_back(sgolomb_tmp);}}slice_header-redundant_pic_cnt_present_flag

pps-redundant_pic_cnt_present_flag;if

(slice_header-redundant_pic_cnt_present_flag)

{//

(!bit_buffer-ReadExponentialGolomb((slice_header-redundant_pic_cnt)))

{return

(!bit_buffer-ReadBits((slice_header-direct_spatial_mv_pred_flag),1))

{return

num_ref_idx_active_override_flag

u(1)if

(!bit_buffer-ReadBits((slice_header-num_ref_idx_active_override_flag),1))

{return

(slice_header-num_ref_idx_active_override_flag)

{//

(!bit_buffer-ReadExponentialGolomb((slice_header-num_ref_idx_l0_active_minus1)))

{return

(!bit_buffer-ReadExponentialGolomb((slice_header-num_ref_idx_l1_active_minus1)))

{return

ref_pic_list_mvc_modification()

#ifdef

ref_pic_list_mvc_modification()fprintf(stderr,error:

unimplemented

ref_pic_list_modification(slice_type)slice_header-ref_pic_list_modification

H264RefPicListModificationParser::ParseRefPicListModification(bit_buffer,

(slice_header-ref_pic_list_modification

nullptr)

nullptr;}}slice_header-weighted_pred_flag

pps-weighted_pred_flag;slice_header-weighted_bipred_idc

((slice_header-weighted_pred_flag

SliceType::P)

||((slice_header-weighted_bipred_idc

SliceType::B)

num_ref_idx_l0_active_minus1,//

num_ref_idx_l1_active_minus1)uint32_t

ChromaArrayType

sps_data-getChromaArrayType();slice_header-pred_weight_table

H264PredWeightTableParser::ParsePredWeightTable(bit_buffer,

ChromaArrayType,

slice_header-slice_type,slice_header-num_ref_idx_l0_active_minus1,slice_header-num_ref_idx_l1_active_minus1);if

(slice_header-pred_weight_table

nullptr)

dec_ref_pic_marking(nal_unit_type)slice_header-dec_ref_pic_marking

H264DecRefPicMarkingParser::ParseDecRefPicMarking(bit_buffer,

(slice_header-dec_ref_pic_marking

nullptr)

nullptr;}}slice_header-entropy_coding_mode_flag

pps-entropy_coding_mode_flag;if

(slice_header-entropy_coding_mode_flag

SliceType::I)

(!bit_buffer-ReadExponentialGolomb((slice_header-cabac_init_idc)))

{return

(!bit_buffer-ReadSignedExponentialGolomb((slice_header-slice_qp_delta)))

{return

(!bit_buffer-ReadBits((slice_header-sp_for_switch_flag),

1))

(!bit_buffer-ReadSignedExponentialGolomb((slice_header-slice_qs_delta)))

{return

nullptr;}}slice_header-deblocking_filter_control_present_flag

pps-deblocking_filter_control_present_flag;if

(slice_header-deblocking_filter_control_present_flag)

{//

(!bit_buffer-ReadExponentialGolomb((slice_header-disable_deblocking_filter_idc)))

{return

(slice_header-disable_deblocking_filter_idc

{//

(!bit_buffer-ReadSignedExponentialGolomb((slice_header-slice_alpha_c0_offset_div2)))

{return

(!bit_buffer-ReadSignedExponentialGolomb((slice_header-slice_beta_offset_div2)))

{return

nullptr;}}}slice_header-num_slice_groups_minus1

pps-num_slice_groups_minus1;slice_header-slice_group_map_type

((slice_header-num_slice_groups_minus1

(slice_header-slice_group_map_type

(slice_header-slice_group_map_type

5))

u(v)slice_header-pic_width_in_mbs_minus1

sps_data-pic_width_in_mbs_minus1;slice_header-pic_height_in_map_units_minus1

sps_data-pic_height_in_map_units_minus1;slice_header-slice_group_change_rate_minus1

pps-slice_group_change_rate_minus1;uint32_t

slice_header-getSliceGroupChangeCycleLen(slice_header-pic_width_in_mbs_minus1,slice_header-pic_height_in_map_units_minus1,slice_header-slice_group_change_rate_minus1);//

Rec.

(!bit_buffer-ReadBits((slice_header-slice_group_change_cycle),slice_group_change_cycle_len))

{return

H264SliceHeaderParser::SliceHeaderState::getFrameNumLen(uint32_t

noexcept

H264SliceHeaderParser::SliceHeaderState::getPicOrderCntLsbLen(uint32_t

log2_max_pic_order_cnt_lsb_minus4)

noexcept

log2_max_pic_order_cnt_lsb_minus4

bits.return

log2_max_pic_order_cnt_lsb_minus4

4;}uint32_t

H264SliceHeaderParser::SliceHeaderState::getSliceGroupChangeCycleLen(uint32_t

uint32_t

pic_height_in_map_units_minus1,uint32_t

slice_group_change_rate_minus1)

noexcept

getPicSizeInMapUnits(pic_width_in_mbs_minus1,

pic_height_in_map_units_minus1);uint32_t

SliceGroupChangeRate

getSliceGroupChangeRate(slice_group_change_rate_minus1);return

(PicSizeInMapUnits

H264SliceHeaderParser::SliceHeaderState::getPicWidthInMbs(uint32_t

noexcept

H264SliceHeaderParser::SliceHeaderState::getPicHeightInMapUnits(uint32_t

pic_height_in_map_units_minus1)

noexcept

H264SliceHeaderParser::SliceHeaderState::getPicSizeInMapUnits(uint32_t

pic_width_in_mbs_minus1,uint32_t

pic_height_in_map_units_minus1)

noexcept

getPicWidthInMbs(pic_width_in_mbs_minus1);uint32_t

PicHeightInMapUnits

getPicHeightInMapUnits(pic_height_in_map_units_minus1);return

PicWidthInMbs

H264SliceHeaderParser::SliceHeaderState::getSliceGroupChangeRate(uint32_t

slice_group_change_rate_minus1)

noexcept

H264SliceHeaderParser::SliceHeaderState::fdump(FILE*

outfp,int

indent_level_incr(indent_level);fdump_indent_level(outfp,

first_mb_in_slice:

first_mb_in_slice);fdump_indent_level(outfp,

slice_type:

slice_type);fdump_indent_level(outfp,

%i,

colour_plane_id);}fdump_indent_level(outfp,

frame_num:

(bottom_field_pic_order_in_frame_present_flag

!field_pic_flag)

%i,delta_pic_order_cnt_bottom);}}if

(pic_order_cnt_type

!delta_pic_order_always_zero_flag)

delta_pic_order_cnt

(redundant_pic_cnt_present_flag)

redundant_pic_cnt:

%i,direct_spatial_mv_pred_flag);}if

((slice_type

num_ref_idx_active_override_flag:

%i,num_ref_idx_active_override_flag);if

(num_ref_idx_active_override_flag)

%i,num_ref_idx_l0_active_minus1);if

((slice_type

%i,num_ref_idx_l1_active_minus1);}}}fdump_indent_level(outfp,

indent_level);ref_pic_list_modification-fdump(outfp,

indent_level);if

indent_level);pred_weight_table-fdump(outfp,

indent_level);}if

indent_level);dec_ref_pic_marking-fdump(outfp,

indent_level);}if

cabac_init_idc);}fdump_indent_level(outfp,

slice_qp_delta:

sp_for_switch_flag);}fdump_indent_level(outfp,

slice_qs_delta:

(deblocking_filter_control_present_flag)

%i,disable_deblocking_filter_idc);if

%i,slice_alpha_c0_offset_div2);fdump_indent_level(outfp,

%i,

slice_group_change_cycle);}indent_level

indent_level_decr(indent_level);fdump_indent_level(outfp,

});}

h264nalh264_ref_pic_list_modification_parser.cc:

/**

../h264include/h264nal/h264_ref_pic_list_modification_parser.h#define

inttypes.h

../h264include/h264nal/h264_common.hnamespace

h264nal

http://www.itu.int/rec/T-REC-H.264//

Unpack

buffer.std::unique_ptrH264RefPicListModificationParser::RefPicListModificationStateH264RefPicListModificationParser::ParseRefPicListModification(const

uint8_t

bit_buffer(unpacked_buffer.data(),

ParseRefPicListModification(bit_buffer,

slice_type);}std::unique_ptrH264RefPicListModificationParser::RefPicListModificationStateH264RefPicListModificationParser::ParseRefPicListModification(rtc264::BitBuffer

*bit_buffer,

std::make_uniqueRefPicListModificationState();//

store

valuesref_pic_list_modification-slice_type

slice_type;if

ref_pic_list_modification_flag_l0

u(1)if

(!bit_buffer-ReadBits((ref_pic_list_modification-ref_pic_list_modification_flag_l0),1))

{return

(ref_pic_list_modification-ref_pic_list_modification_flag_l0)

{do

modification_of_pic_nums_idc[i]

ue(v)if

(!bit_buffer-ReadExponentialGolomb(golomb_tmp))

{return

nullptr;}ref_pic_list_modification-modification_of_pic_nums_idc.push_back(golomb_tmp);if

((ref_pic_list_modification-modification_of_pic_nums_idc.back()

||(ref_pic_list_modification-modification_of_pic_nums_idc.back()

1))

(!bit_buffer-ReadExponentialGolomb(golomb_tmp))

{return

nullptr;}ref_pic_list_modification-abs_diff_pic_num_minus1.push_back(golomb_tmp);}

else

(ref_pic_list_modification-modification_of_pic_nums_idc.back()

{//

(!bit_buffer-ReadExponentialGolomb(golomb_tmp))

{return

nullptr;}ref_pic_list_modification-long_term_pic_num.push_back(golomb_tmp);}}

while

(ref_pic_list_modification-modification_of_pic_nums_idc.back()

!3);}}if

ref_pic_list_modification_flag_l1

u(1)if

(!bit_buffer-ReadBits((ref_pic_list_modification-ref_pic_list_modification_flag_l1),1))

{return

(ref_pic_list_modification-ref_pic_list_modification_flag_l1)

{do

modification_of_pic_nums_idc[i]

ue(v)if

(!bit_buffer-ReadExponentialGolomb(golomb_tmp))

{return

nullptr;}ref_pic_list_modification-modification_of_pic_nums_idc.push_back(golomb_tmp);if

((ref_pic_list_modification-modification_of_pic_nums_idc.back()

||(ref_pic_list_modification-modification_of_pic_nums_idc.back()

1))

(!bit_buffer-ReadExponentialGolomb(golomb_tmp))

{return

nullptr;}ref_pic_list_modification-abs_diff_pic_num_minus1.push_back(golomb_tmp);}

else

(ref_pic_list_modification-modification_of_pic_nums_idc.back()

{//

(!bit_buffer-ReadExponentialGolomb(golomb_tmp))

{return

nullptr;}ref_pic_list_modification-long_term_pic_num.push_back(golomb_tmp);}}

while

(ref_pic_list_modification-modification_of_pic_nums_idc.back()

!3);}}return

ref_pic_list_modification;}#ifdef

FDUMP_DEFINEvoid

H264RefPicListModificationParser::RefPicListModificationState::fdump(FILE*

outfp,

indent_level_incr(indent_level);fdump_indent_level(outfp,

ref_pic_list_modification_flag_l0:

%i,ref_pic_list_modification_flag_l0);fdump_indent_level(outfp,

ref_pic_list_modification_flag_l1:

%i,ref_pic_list_modification_flag_l1);if

(modification_of_pic_nums_idc.size()

{);for

(abs_diff_pic_num_minus1.size()

{);for

indent_level_decr(indent_level);fdump_indent_level(outfp,

});}

h264nalh264_pred_weight_table_parser.cc

对应的语句语义为第三节中的加权预测的语义具体代码可去githubhttps://github.com/wangyongyao1989/WyFFmpeg/tree/main/h264

h264_dec_ref_pic_marking_parser.cc

对应的语句语义为第三节中的参考图像序列标记Marking操作的语义具体代码可去githubhttps://github.com/wangyongyao1989/WyFFmpeg/tree/main/h264

如上述代码中的语句语义是根据基于H.264标准的2012版本。

参考资料

https://github.com/wangyongyao1989/WyFFmpeg/tree/main/h264

H.264



SEO优化服务概述

作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。

百度官方合作伙伴 白帽SEO技术 数据驱动优化 效果长期稳定

SEO优化核心服务

网站技术SEO

  • 网站结构优化 - 提升网站爬虫可访问性
  • 页面速度优化 - 缩短加载时间,提高用户体验
  • 移动端适配 - 确保移动设备友好性
  • HTTPS安全协议 - 提升网站安全性与信任度
  • 结构化数据标记 - 增强搜索结果显示效果

内容优化服务

  • 关键词研究与布局 - 精准定位目标关键词
  • 高质量内容创作 - 原创、专业、有价值的内容
  • Meta标签优化 - 提升点击率和相关性
  • 内容更新策略 - 保持网站内容新鲜度
  • 多媒体内容优化 - 图片、视频SEO优化

外链建设策略

  • 高质量外链获取 - 权威网站链接建设
  • 品牌提及监控 - 追踪品牌在线曝光
  • 行业目录提交 - 提升网站基础权威
  • 社交媒体整合 - 增强内容传播力
  • 链接质量分析 - 避免低质量链接风险

SEO服务方案对比

服务项目 基础套餐 标准套餐 高级定制
关键词优化数量 10-20个核心词 30-50个核心词+长尾词 80-150个全方位覆盖
内容优化 基础页面优化 全站内容优化+每月5篇原创 个性化内容策略+每月15篇原创
技术SEO 基本技术检查 全面技术优化+移动适配 深度技术重构+性能优化
外链建设 每月5-10条 每月20-30条高质量外链 每月50+条多渠道外链
数据报告 月度基础报告 双周详细报告+分析 每周深度报告+策略调整
效果保障 3-6个月见效 2-4个月见效 1-3个月快速见效

SEO优化实施流程

我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:

1

网站诊断分析

全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。

2

关键词策略制定

基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。

3

技术优化实施

解决网站技术问题,优化网站结构,提升页面速度和移动端体验。

4

内容优化建设

创作高质量原创内容,优化现有页面,建立内容更新机制。

5

外链建设推广

获取高质量外部链接,建立品牌在线影响力,提升网站权威度。

6

数据监控调整

持续监控排名、流量和转化数据,根据效果调整优化策略。

SEO优化常见问题

SEO优化一般需要多长时间才能看到效果?
SEO是一个渐进的过程,通常需要3-6个月才能看到明显效果。具体时间取决于网站现状、竞争程度和优化强度。我们的标准套餐一般在2-4个月内开始显现效果,高级定制方案可能在1-3个月内就能看到初步成果。
你们使用白帽SEO技术还是黑帽技术?
我们始终坚持使用白帽SEO技术,遵循搜索引擎的官方指南。我们的优化策略注重长期效果和可持续性,绝不使用任何可能导致网站被惩罚的违规手段。作为百度官方合作伙伴,我们承诺提供安全、合规的SEO服务。
SEO优化后效果能持续多久?
通过我们的白帽SEO策略获得的排名和流量具有长期稳定性。一旦网站达到理想排名,只需适当的维护和更新,效果可以持续数年。我们提供优化后维护服务,确保您的网站长期保持竞争优势。
你们提供SEO优化效果保障吗?
我们提供基于数据的SEO效果承诺。根据服务套餐不同,我们承诺在约定时间内将核心关键词优化到指定排名位置,或实现约定的自然流量增长目标。所有承诺都会在服务合同中明确约定,并提供详细的KPI衡量标准。

SEO优化效果数据

基于我们服务的客户数据统计,平均优化效果如下:

+85%
自然搜索流量提升
+120%
关键词排名数量
+60%
网站转化率提升
3-6月
平均见效周期

行业案例 - 制造业

  • 优化前:日均自然流量120,核心词无排名
  • 优化6个月后:日均自然流量950,15个核心词首页排名
  • 效果提升:流量增长692%,询盘量增加320%

行业案例 - 电商

  • 优化前:月均自然订单50单,转化率1.2%
  • 优化4个月后:月均自然订单210单,转化率2.8%
  • 效果提升:订单增长320%,转化率提升133%

行业案例 - 教育

  • 优化前:月均咨询量35个,主要依赖付费广告
  • 优化5个月后:月均咨询量180个,自然流量占比65%
  • 效果提升:咨询量增长414%,营销成本降低57%

为什么选择我们的SEO服务

专业团队

  • 10年以上SEO经验专家带队
  • 百度、Google认证工程师
  • 内容创作、技术开发、数据分析多领域团队
  • 持续培训保持技术领先

数据驱动

  • 自主研发SEO分析工具
  • 实时排名监控系统
  • 竞争对手深度分析
  • 效果可视化报告

透明合作

  • 清晰的服务内容和价格
  • 定期进展汇报和沟通
  • 效果数据实时可查
  • 灵活的合同条款

我们的SEO服务理念

我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。

提交需求或反馈

Demand feedback