Showing Posts From
H264
- 31 May, 2022
UCConfig学习笔记之UCConfig Mode 0
在参考文档1中,对UCConfig Mode 0的定义是:Non‐scalable single layer AVC bitstream with Simulcast (number of simulcast streams >= 1).。也就是说UCConfig Mode 0不需要支持SVC的分层,常见的AVC编码器的码流可以归属于这一类。但是需要注意的是,尽管Mode0不需要支持SVC分层,但是同样对输出的码流NAL Unit的结构有明确的的要求,最显著的就是需要包含SVC特有的Prefix NAL Unit。 分层结构 UCConfig Mode 0对应的编码模式既然是AVC,也就不存在分层的概念。所以在编码的结构上只包含一个层。 !Untitled.png - 实际上这种模式的编码结构也是H.264编码器最常见的编码结构:I帧后的第一个P帧的解码仅依赖于前面的P帧,此后的P帧则依赖于I帧和它之前的P帧,所以整个GOP中任何一个P帧丢失,这个GOP后面的P帧都无法正常解码了。 对应到SigmaStar的Webcam方案(如SSD268G、SSC9351等),实际上就是所谓的NormalP编码模式,这种编码模式也是该方案默认的编码模式: !Untitled.png 码流结构需求 除了以上的编码结构以外,UCConfig Mode 0对于编码器输出的码流也有明确的要求: - UCConfig Mode 0下,尽管不需要支持SVC的分层结构,但对于其输出的码流而言,同样要求在每个图像压缩数据所在的NAL Unit之前包含一个Prefix NAL Unit;使用这个Prefix NAL Unit中的priority_id来标记这个码流的相对优先级,0表示最高优先级,1表示次高优先级,以此类推。 - 这样如果一个节点同时发送多路UCConfig Mode 0给中央服务器,服务器在收到多条流以后就可以通过这个priority_id来判断各条流的优先级; - 在每个Prefix NAL Unit中,dependency_id, quality_id和temporal_id均必须为0;no_inter_layer_pred_flag,discardable_flag和output_flag必须为1;use_ref_base_pic_flag必须为1。 - 对于不支持SVC模式的解码器而言,接收到的Streaming流数据中如果遇到Prefix NAL Unit,解码器会直接把这个NAL Unit丢弃掉,因此不支持SVC的解码器也可以对符合UCConfig Mode 0规范的码流成功解码。 参考文档: - H.264 AVC/SVC UCConfig Mode Specification V1.1
- 27 May, 2022
UCConfig学习笔记之UCConfig Mode 1
在参考文档1中,对UCConfig Mode 1的定义是:SVC temporal scalability with hierarchical P with Simulcast (number of simulcast streams >= 1)。也就是说需要编码器能够支持SVC模式的帧率扩展模式。即编码器输出的一路流中可以包含多种不同帧率的分层支持。 编码分层结构 为了能够支持以上的不同帧率的分层架构,需要在编码器的参考帧依赖结构上做一些针对性的设计,也就是文档1中所提到的Hierarchical P prediction structure。 按照分层的数量,Mode1可以分为两层、三层和四层帧率分层结构。 !二层帧率分层结构 - 可以在最大帧率和1/2最大帧率两种分层中进行切换。 - 在最大帧率为30fps的情况下,如果只接收Layer0(也就是Base Layer),那么接收的帧率就是15fps;如果同时接收Layer0(15fps)+Layer1(15fps),那么总的接收帧率就是30fps; !三层帧率分层结构 - 可以在最大帧率、1/2最大帧率和1/4最大帧率三种分层中进行切换。 - 在最大帧率为30fps的情况下,如果只接收Layer0(也就是Base Layer),那么接收的帧率就是7.5fps;如果同时接收Layer0(7.5fps)+Layer1(7.5fps),那么总的接收帧率就是15fps;如果同时接收Layer0(7.5fps)+Layer1(7.5fps)+Layer2(15fps),那么总的接收帧率就是30fps。 !四层帧率分层结构 - 可以在最大帧率、1/2最大帧率、1/4最大帧率、1/8最大帧率四种分层中进行切换。 - 在最大帧率为60fps的情况下,如果只接收Layer0(也就是Base Layer),那么接收的帧率就是7.5fps;如果同时接收Layer0(7.5fps)+Layer1(7.5fps),那么总的接收帧率就是15fps;如果同时接收Layer0(7.5fps)+Layer1(7.5fps)+Layer2(15fps),那么总的接收帧率就是30fps;如果同时接收Layer0(7.5fps)+Layer1(7.5fps)+Layer2(15fps)+Layer3(30fps),那么总的接收帧率就是60fps。 码流结构需求 除了以上的编码结构以外,UCConfig Mode 1对于编码器输出的码流也有明确的要求: - 每个包含IDR(NAL Unit Type=1)和non-IDR(NAL Unit Type=5)帧编码数据的NAL Unit之前,都必须要加一个Prefix NAL Unit(NAL Unit Type=14)。在这个Prefix NAL Unit中使用priority_id元素来标记其后面跟的图像编码数据分层的优先级:0表示Base Layer,1表示第一个扩展层,2表示第二个扩展层,以此类推。 - 此外NAL Unit Type=2,3,20的这三种NAL Unit不能出现在这种类型的编码流中。 - 同时,在这个Prefix NAL Unit中,使用Temporal_id来指定帧率分层的结构:0代表Base Layer的数据,1代表第一个帧率扩展层的数据,2代表第二个帧率扩展层的数据。 - 在文档2中定义,UCConfig Mode 1的码流中所包含的Prefix NAL Unit,其Temporal_id与priority_id元素的值必须相同。但是在文档1中并没有这个要求。但是客观地讲,对于UCConfig Mode 1的码流而言,因为其中只应该有帧率方面的扩展层,不应该包含其他的分辨率和图像质量等的分层,因此这个要求应该是合理的。 - 所有Prefix NAL Unit中的dependency_id和quality_id必须设置为0。no_inter_layer_pred_flag,discardable_flag和output_flag必须设置为1。use_ref_base_pic_flag必须设置为0. - 这个Prefix NAL Unit是SVC扩展独有的NAL Unit类型,因此如果一个不支持SVC的Unit收到SVC的码流以后,会把这个Prefix NAL Unit直接丢弃,但是仍然能够成功的对SVC的码流进行解码播放。 参考资料 - Unified Communication Specification for H.264 AVC and SVC UCConfig Modes V 1.1; - Microsoft Skype for Business H.264 Video Encoder Specification;
- 20 May, 2022
《Microsoft Skype for Business H.264 Video Encoder Specification》学习笔记
对于要通过Mircosoft的Teams或者Skype For Business认证的视频会议系统,要使用H.264来进行图像传输的情况,就需要对图像视频压缩所使用的H.264编码器进行Teams和Skype For Business的认证,才能打上对应的认证Logo。而这个对于H.264编码器进行认证的规范指导文件就是《Microsoft Skype for Business H.264 Video Encoder Specification》,文档编号为H105958。 - 注意:这个规范文件和认证流程针对的是单纯的H.264编码器,而不是整个摄像头系统。所有的指标、功能性要求以及进行测试和验证的流程,都是针对链路上所使用的H.264编码器。 在该规范文档中,把要通过Teams和Skype For Business认证的H.264编码器分为以下三种情况: - Category 1:USB Camera内部包含的H.264编码器; - Category 2:笔记本、平板电脑和手机中集成的摄像头内部自带的H.264编码器; - Category 3:通用的H.264硬件编码器。 如同其他所有的Teams认证的规范文档,通过Teams的H.264 Encoder的认证,同样存在Standard和Premium两种认证规格,后者的指标和功能要求更加严格一些。而只要通过Standard的指标要求,就可以打上Teams的认证Logo。 无论对于Standard还是Premium类型的认证而言,对于H.264编码器的基本要求就是能够支持UCConfig Mode 1,也就是需要H.264编码器至少能够支持SVC的Temporal Layer。所以那些不支持SVC模式的编码器就可以洗洗睡了:(4.1)Encoders must support UCConfig Mode 1 and the corresponding requirements outlined below in order to participate in the Skype for Business Logo program。另外要通过这个认证,需要编码器支持的最大分辨率至少要是1080P。 - UCConfig Mode 1的定义:SVC temporal scalability with hierarchical P with Simulcast (number of simulcast streams >= 1). H.264编码器进行Teams认证的测试流程 微软为了进行这个H.264编码器的一致性测试,专门提供了一个测试工具:Microsoft Skype Video Encoding Conformance (MLVEC) toolkit。这个工具主要分为两个部分:H.264的码流产生器(BitStream Generator)和码流一致性验证器(Conformance Verifier)。 !Untitled.png BitStream Generator: - BitStream Generator的输入有两个:一个是Skype Business进行测试认证的录像片段(不同分辨率、不同场景),也就是上面的Skype Logo Clips;另外一个就是Config Scripts,在其中定义了测试编码器需要设置编码器的参数和工作流程,编码器按照该脚本的命令进行工作。 - 对于USB Camera而言,要进行这个测试肯定就没那么容易了,因为没有办法很容易的把这些认证录像片段方便的送入USB Camera的编码器中进行编码。所以针对这个问题,文档中明确规定,对于这类USB Camera的认证而言,Camera的生产厂家,要自己想办法(例如通过一个专门的开发板)把测试录像片段送入Camera内部的编码器,并按照要求自行完成码流的生成。(5.3)Tethered USB webcams usually don’t have a possibility to feed the pre-recorded clips into the hardware encoder. Due to this we are currently requiring these tests to be run on a development kit which allows feeding the pre-recorded clips into the encoder. - BitStream Generator的输出就是各种不同测试参数状态下的码流文件,以及运行中所产生的的log。 Conformance Verifier: - Conformance Verifier读取BitStream Generator所产生的码率文件和运行log,基于其内部的功能性分析工具进行判断,看编码器所产生的的码率及其运行过程的指标性数据,是否符合Standard和Premium的标准,给出最终的测试判定报告。 H.264编码器认证需求 - Aspect ratios and image resolutions:对于编码器能够支持的图像长宽比和分辨率的要求,三个Category的编码器有不同的长宽比和分辨率编码测试要求; !Untitled.png !Untitled.png - Frame rate:不同分辨率下的编码帧率要求 !Untitled.png - Video preview:对于Preview视频的输出需求。内置H.264编码器的USB Camera需要能够同时提供一路小分辨率(640x480或者640x360 30fps)的YUV图像作为Preview的功能。 - 不是很清楚对于USB UVC camere而言,如何能够在传输H.264 main Streaming的同时,把这个YUV的preview video也传过去?具体应该怎么做? - Encoder latency:编码延迟指标,对于编码进行编码导致的Pipeline延迟不应该影响帧率,或者造成图像在传输和解码回放时出现抖动。 - Dynamic resolution change:编码器应该能够支持在Pipelien的编码器正常运行的过程中,动态的调整分辨率。且有一定的调整延迟指标。 - Dynamic profile/level change:编码器应该能够支持在Pipelien的编码器正常运行的过程中,根据具体情况动态调整编码的profile和level的设置。且有一定的调整延迟指标。 - Dynamic add/remove temporal layers:对于支持SVC扩展的编码器而言,能够在编码过程中,动态的增加或者删除帧率扩展层(temporal layer),且有一定的调整延迟指标。 - Bitstream Conformance:这部分对于编码器在各种模式下输出的码率的设置有明确的的要求。 - Quality Conformance:对编码器产生的码率,经过解压缩以后的图像质量有明确的要求。 其他 - 对于USB Camera而言,如果要通过Teams的这个H.264 Video Encoder认证,需要在USB Camera中支持UVC1.5规范:实际上UVC1.1已经可以通过Frame Based的方式来支持H.264的Payload了,但是把H.264当成一种独立的payload来进行支持的话,只能使用UVC1.5规范。不过UVC1.5的兼容性不大好,只有在Win8及其以后的系统中才能够支持。 参考资料: - Microsoft Skype for Business H.264 Video Encoder Specification,H105958 - Unified Communication Specification for H.264 AVC and SVC UCConfig Modes, V1.1
- 13 May, 2022
H.264基本概念总结之SVC
SVC:Scalable Video Coding,是H.264(AVC)视频编码算法的一个扩展。 SVC要解决的问题 H.264视频压缩算法是用来对图像数据进行压缩,以方便进行存储和通过网络传输。 在进行1对1传输的时候,使用标准的H.264(AVC)一般不存在问题: - 在接收端处理能力比较强、网络带宽也比较好的情况下,可以设置编码器输出一个图像质量更高、分辨率更大、帧率更高的图像,给接收端提供更好的观赏体验; - 而如果接收端处理能力有限,或者网络带宽不足以传输较好质量的压缩视频数据时,可以设置编码器输出的图像质量稍差一些,分辨率更低或者帧率更低,这样对网络传输要求的带宽更低,对解码器的处理能力也要求更低。 - 实际上在1对1通信的过程中,还可以在发送端与接收端的网络通信中,动态监测网络带宽的变化,对编码器进行动态的调整:网络质量更好的时候编码器输出码率更高、带宽更高的图像;而网络比较差的时候则输出码率更低、对带宽要求更低的图像。 但是,在一对多的视频通信应用场景中(最典型的就是视频会议、直播、在线点播等),一路摄像头采集的图像需要发给多个接收端,每个接收端的处理能力和网络通信状态都有差异,那么就对发给这些接收端的图像质量、分辨率、码率等提出不同的要求:处理能力更强、带宽更好的接收端期望能够收到码率更高、质量更好的图像,以尽可能保证用户体验;而处理能力有限、带宽较差的接收端至少期望能够收到一个码率更低但是确保播放过程中足够流畅的视频。 但是,对于标准的H.264(AVC)编码器而言,编码器的参数设置之后,输出的图像分辨率、帧率和图像质量等指标基本上就是固定的。 针对这个问题,最直接的解决办法就是:摄像头端的图像采集后,使用最高质量的视频压缩参数进行视频压缩,然后上传到中心服务器;在中心服务器上对这个高质量的图像进行各种不同分辨率、帧率、码率组合的转码操作;然后再根据接收端的网络带宽状况和处理能力,向不同的接收端分发不同的转码图像文件。 - 实际上,现在互联网上的点播系统(Youtube、B站等)的工作原理就是如此,主播的图像视频使用高质量编码参数压缩后上传到中心服务器,在中心服务器上进行转码,转码为不同的分辨率以支持不同的客户端设备。 以上解决方案的问题在于:在服务器端进行转码的操作在某些应用场合中太昂贵了!如果这个视频图像有成千上万个用户观看的话,在中心服务器上对上传视频进行转码操作是可行的,但是如果这个视频只有少数几个人(最典型的就是视频会议的应用)观看的话,还需要把每一路上传视频都进行转码并转发的话,对于中心服务器的压力就太大了。 - 想象一下,如果有8个人开会,那么就会有8路图像送到中心服务器同时进行各种分辨率和压缩质量的转码并分发,这对于中心服务器的压力会有多大。而付出这么大的计算量,却只能为8个人的小型会议提供服务,这种方案的性价比和流媒体的处理效率就太低了。 因此现在的问题就是,针对视频会议这类小型的一对多或者多对多的应用场景,如何在不通过中心服务器转码的情况下,能够实现对不同接收端提供不同质量和码率的视频分发?这就是H.264的SVC扩展所要解决的问题。 SVC解决以上问题的思路 SVC解决以上问题的思路就是: - 在视频图像的提供者也就是摄像头端,进行一次编码,这个编码输出的图像流可以从结构上分为多个部分,完整的图像流(也就是所有部分的组合)就表示是最高质量级别的图像,码率也最大;而把这个图像流中所包含的各个部分进行各种组合,保留一部分,去掉一部分,就可以组成各种针对不同类型、不同质量级别的子图像流。 - 摄像头端把压缩好的完整图像流上传到中心服务器,中心服务器不需要对这个图像进行重新转码,只需要根据图像接收端的处理能力和带宽情况,从这个完整的图像流中选择部分或者全部流数据到接收端。 - 接收端收到图像以后直接进行解码回放,处理能力强、网络带宽状况好的接收端收到的很有可能就是完整的图像流,解码后回放的图像效果也最好;而处理能力差、带宽较差的接收端可能就只能接收到完整图像流的一部分,解码后仍然可以得到一个分辨率、帧率或者图像质量更差的效果,但至少能保证回放的流畅度。 以上方案中提到的完整图像流的“部分”实际上就是SVC中的分层(Layer)。所有分层的组合形成了最高质量的图像,部分分层的组合则可以得到一个某些特性较差、对带宽要求也较低的图像。 以上方案的关键就在于视频编解码器: - 编码器端要能够按照以上的逻辑生成分层的视频图像流,在标准H.264的AVC规范里面是不支持的,AVC没有这个分层的概念; - 解码器端则既要能够实现对完整图像流的解码,也能够对完整图像流的多个分层部分的组合进行解码,输出不同质量属性的视频图像; 而满足H.264的SVC扩展属性的视频Codec则可以符合以上两个条件。 SVC的技术实现细节 SVC中的S表示Scalable,表示是可以扩展的。在SVC的标准中,在以下三个维度上提供了可扩展的选项: - Quality Scalability:图像压缩质量 - Temporal Scalability:帧率 - Spatial Scalability:分辨率 如上所述,SVC是以分层的实现来提供了对不同维度的可扩展支持。具体而言,一个完整的SVC图像流包含了一个Base Layer和多个Enhancement Layer。Base Layer表示这个图像流所能支持的最低视频图像属性的配置,每个Enhancement Layer代表在某个维度上进行的扩展增强支持。 !Untitled.png 因此,对于最差类型的处理能力和网络状况,可以直接发送一个Base Layer的数据;对于稍好点的接收端,可以发送一个Base Layer和一个或者多个Enhancement Layer的组合;而对于最好配置的接收端,可以把整个完整的SVC图像流发过去,得到最好的回放体验。 编码器所生成的SVC图像流的不同Layer的数据,在发送至中心服务器或者保存到本地文件中的时候,可以通过NALU Header来对不同Layer的数据区分。这样中心服务器在收到数据以后,就能知道这个数据是属于哪个Layer的数据。 Microsoft的UCConfig 微软针对他们的Teams和Skype For Business的认证体系,基于H.264的SVC标准,定义了5种UCConfig工作模式,分别针对不同类型的SVC Layer的可扩展组合,来满足视频会议系统对于SVC的应用需求: - UCConfig Mode 0: Non-Scalable Single Layer AVC Bitstream. - 不支持SVC扩展,实际上就是标准的H.264 AVC流。对于不支持SVC模式的H.264编码器的情况,只能选择这种工作模式; - 这种模式也可以支持在同一个传输流中包含多个不同分辨率的Streaming。即Simulcast。 - UCConfig Mode 1: SVC Temporal Scalability with Hierarchical P. - 多帧率扩展支持,每一条独立的传输流中包含有针对同一分辨率下的扩展帧率支持。 - UCConfig Mode 2q: SVC Temporal Scalability + Quality/SNR Scalability. - 在UCConfig Mode 1的基础上,增加了图像质量分层的扩展支持。一条独立的传输流中同时包含了针对同一分辨率的扩展帧率分层支持和扩展图像质量分层支持。 - UCConfig Mode 2s: SVC Temporal Scalability + Spatial Scalability. - 在UCConfig Mode 1的基础上,增加了多分辨率分层的扩展支持。一条独立的传输流中同时包含有对多分辨率的扩展分层支持和帧率扩展分层支持。 - UCConfig Mode 3: Full SVC Scalability (Temporal + SNR + Spatial). - UCConfig基于H.264 SVC规范定义的最高级别的扩展分层支持。在同一条独立的传输流中,同时包含了对多分辨率、多帧率和图像质量的扩展分层支持。 参考资料: - H.264 SVC – An Update on the H.264 Video Compression Standard - Mistral Solutions - Scalable Video Coding - Wikipedia - 技术干货 | H.264 SVC技术介绍及应用分析 - 知乎 (zhihu.com)
- 16 Mar, 2022
H.264基本概念总结之Slice与NALU
VCL与NAL VCL:Video Coding Layer,视频编码层。 NAL :Network Abstraction Layer, 即网络抽象层。 在 H.264/AVC 视频编码标准中,整个系统框架被分为了两个层面:视频编码层面(VCL, Video Coding Layer)和网络抽象层面(NAL, Network Abstract Layer)。其中,前者负责有效表示视频数据的内容;而后者则负责格式化数据并提供头信息,以保证数据适合各种信道和存储介质上的传输。 - 简单地说,所谓的VCL就是图像帧经过H.264算法进行视频编码后所产生的编码图像数据,所以在后面的NALU中所封装的数据包含有两种类型,VCL和non-VCL,VCL表示的就是图像编码数据,non-VCL则是非图像压缩数据; - 而所谓的NAL则是把H.264图像编码所产生字节流,进行合理和标准化的封装,以方便保存在存储介质上,或者通过网络等方式传输出去后,能够被播放端正确的解析、读取、解码、回放显示出来。 !Untitled.png Frame与Slice 每一个Frame在编码的时候分为一个或者多个Slice进行编码,而每个Slice内部又可以包含有多个宏块。H.264进行编码的时候就是以宏块为单位进行编码的。 具体而言,Frame与Slice之间的关系在实践中可能是: - 一个Frame只有一个Slice,这个Frame中所包含的宏块都在同一个Slice中进行编码; - 每个Frame中包含有N个Slice,每个Slice包含有固定的M个宏块,M和N均为整数。每个Slice经过编码后产生的字节流的大小根据这个Slice中图像的运动和细节表现而变化,可能差异较大。 - 每个Frame中包含有N个Slice,每个Slice中包含的宏块数量不定,但是经过编码后各个Slice缩成的编码字节流大小基本一致。 NALU NAL:Network Abstraction Layer。 NALU:Network Abstraction Layer Unit。 NALU是H.264编码产生数据进行保存和传输的基本单元,各个Slice编码后产生的数据使用NALU进行打包封装。实际上一个.h264文件就是有连续的很多个NALU组成。 - 当然并非所有的NALU中封装的都是Slice的编码数据。 一个标准的NALU总是包含有3个部分:start code(3个或者4个字节),nalu header(1个字节),nalu paylodf(不定长)。 每个NALU都固定的以0x00 0x00 0x01或者0x00 0x00 0x00 0x01开头,这个0x00 0x00 0x01或者0x00 0x00 0x00 0x01序列就是所谓的start code。 每个NALU开头的start code后面紧跟的那个字节就是nalu header。nalu header中包含有3个域: - forbidden_zero_bit(1bit):H.264规范中要求该位应该设置为0。 - nal_ref_idc(2bit):nalu的重要性指示位,标志该NALU的重要性。值越大,表示该NALU越重要,解码器在解码处理不过来的时候,可以丢掉重要性为0的NALU。 - nal_unit_type(5bit):用于表示这个NALU结构体中Payload部分包含的数据类型是什么。 !Untitled.png nal unit type=6表示这个NALU中包含的是SEI信息。 nal unit type=7表示这个NALU中包含的是SPS信息。 nal unit type=8表示这个NALU中包含的是PPS信息。 - 以上三种类型的相关信息整理在H.264基本概念总结之SPS,PPS,SEI中。 H.264对一帧图像进行编码后所产生的的图像压缩数据(实际上也就是所谓的VCL数据)则保存在nal unit type=1-5这五种类型的NALU中。 - 其他nal unit type=5,就表示当前的这个NALU中封装的是IDR帧的数据。 参考资料 1. Introduction to H.264: (1) NAL Unit | Yumi Chan's Blog 2. H.264/AVC 片——slice_RRRR_ChiAn的博客-CSDN博客 3. H.264再学习 -- 详解 H.264 NALU语法结构_不积跬步,无以至千里-CSDN博客_nalu payload 4. 编解码技术:H264 - NAL Unit | 何照江的博客 (hezhaojiang.github.io)
- 16 Mar, 2022
H.264基本概念总结之SPS,PPS,SEI
SPS - Sequence Parameter Set (SPS): This non-VCL NALU contains information required to configure the decoder such as profile, level, resolution, frame rate, which apply to a series of consecutive coded video pictures called a coded video sequence. SPS是指针对整个编码图像序列的全局参数信息,例如分辨率、帧率、H.264编码时使用的Profile和Level等。 与编码后的图像帧数据数据一样,SPS信息也被封装在NALU单元中。SPS所对应的NALU Header Type一般为0x67。所以当对接收到的264数据流进行解析,发现某个NALU是以0x00 0x00 0x00 0x01 0x67开头,就表示这个NALU中封装的信息是SPS信息。 PPS - Picture Parameter Set (PPS): Similar to the SPS, this non-VCL NALU contains information on entropy coding mode, slice groups, motion prediction, quantization parameters (QP), and deblocking filters, which apply to the decoding of one or more individual pictures within a coded video sequence. PPS是指针对编码图像序列中各个图像帧所依赖的参数信息,主要是对这帧图像进行H.264编码时使用的编码相关的参数,如熵编码模式、Slice分组模式、QP设置等。 与编码后的图像帧数据数据一样,PPS信息也被封装在NALU单元中。PPS所对应的NALU Header Type一般为0x68。所以当对接收到的264数据流进行解析,发现某个NALU是以0x00 0x00 0x00 0x01 0x68开头,就表示这个NALU中封装的信息是PPS信息。 SPS与PPS的位置 为了能够确保播放器对H.264编码数据进行正确的解码,在播放器的解码器正式开始工作之前,必须要对解码器使用PPS和SPS中包含的信息进行了正确的初始化。 而对于编码器而言,编码器输出的第一帧数据一般是PPS,然后是SPS,然后是I帧、P帧、B帧等。 对于这些数据作为流媒体通过网络等发送出去,或者保存在本地的H264文件中,一般则以SPS、PPS、I帧、P帧、B帧......这样的顺序进行处理。这样的话就可以确保接收端或者解码器端,能够按照正确的顺序先设置好解码器的运行参数,然后再进行图像解码的处理。 此外,SPS和PPS也可能出现在码流的中间位置,主要的原因可能是: - 解码器端可能是在流媒体数据传输的中间阶段才开始接收数据的,那么要能够对后续的流媒体数据进行正确解码,就需要在码流中间中间插入SPS和PPS信息,确保解码器能够得到正确的设置; - 对于这种情况,比较合理的做法应该是在每个I帧之前都包含有SPS和PPS信息。 - 编码器在编码的过程中改变了码流的参数(如图像的分辨率),这样解码器在收到新的PPS和SPS信息以后,就需要使用并设置新的PPS和SPS参数到解码器中; 如果编码器产生的媒体流文件是保存在本地的多媒体容器文件中进行封装,一般会把SPS和PPS信息放在封装格式的头信息中。这样解码器在解封装的时候就可以从中读取并设置与这个媒体封装文件相匹配的SPS和PPS信息。 SEI SEI:Supplemental Enhancement Information,补充增强信息,可以提供在多媒体流中同步传输额外的自定义信息的功能。 SEI把用户自定义的信息放入流媒体信息中一起传输,可以实现用户自定义信息与音视频流媒体播放的实时同步。 - 一个比较典型的例子是网络直播:在主播把音视频流媒体信息传输给观看者的同时,主播还可以发送自己的文字等即时通讯信息。虽然这些信息可以通过其他通信渠道传给观看者,但是因为音视频和即时通信是分开的,两个信息的同步呈现往往就会是比较大的问题。而如果把用户的即时通信信息放入SEI信息中,与多媒体信息一起封装在NALU中传给观看者,就可以保证这两类信息呈现的实时同步。 解码器端对于SEI信息的解析和处理是可选选项,在不关注SEI信息的时候,可以直接把包含SEI新的NALU丢弃掉。 既然SEI的信息是用户自定义的,那么只要编码/发送端与接收/解码端都是由同一个用户进行控制和实现,那么他就可以在SEI中封装自己想要放入的任何类型的信息。 SEI所对应的NALU Header Type的低5bit为0x06。所以当对接收到的多媒体数据流进行解析,发现某个NALU的header byte的低5位(NAL Unit Type)为0x06,就表示这个NALU中封装的信息是SEI信息。 参考资料: 1. H.264 video codec — Kurento 6.16.1-dev documentation (doc-kurento.readthedocs.io) 2. Network Abstraction Layer - Wikipedia 3. 2.h264的nalu单元解析:sps、pps、sei的概念_yanghangwww的博客-CSDN博客_h264 nalu单元 4. FFmpeg从入门到精通——进阶篇,SEI那些事儿 - 知乎 (zhihu.com)
- 12 May, 2020
H.264的两个基本概念:IDR,dts/pts
IDR帧与I帧之间的区别 IDR:Instantaneous Decoding Refresh。 I帧与IDR帧之间的区别涉及到H.264中不同帧类型的视频解码过程。 - 对于普通的I帧(及其IDR帧)而言,对其进行的视频解码不依赖于其他帧,对每一个I帧(及其IDR帧)解码都可以得到一张完整的图像。 - 对于每一个P帧而言,对其进行解码需要参考其前面的I帧或者P帧,才能成功的解码出来一帧完整的图像; - B帧的解码则更复杂一些,对其进行解码不仅要参考前面的I帧或者P帧,还有可能要参考其后面的P帧解码后的图像; 为了能够支持以上解码过程,H.264的解码算法需要维护一个参考帧列表DPB(Decorded Picture Buffer),实际上就是一个普通的缓存空间,用于存放每一帧完成解码的图像数据,因此: - I帧的解码不需要依赖于DPB中的内容,直接独立进行解码就可以产生一张完整的图像,填入DPB中,此后就可以作为其他P帧和B帧解码的参考; - P帧和B帧的解码则需要依赖于DPB中已经解码好的图像帧,解码完成后同样放入DPB中,作为后面的P帧和B帧的解码参考帧。 注意:P帧和B帧的解码不仅可能依赖于其前面紧邻的那个I帧,还有可能要依赖于更前面的帧。这一点就导致了I帧和IDR帧的细微差别: IDR帧是一种特殊的I帧,在IDR帧之后的所有P帧和B帧的解码都只会向前参考到这个IDR帧,而不会参考这个IDR帧之前的帧。因此在解码器在对一个IDR帧进行解码的时候,就可以直接把DPB中保存的所有缓存数据全部清空,这是很自然的道理:因为这个IDR帧后面的所有帧的解码都不会参考这个IDR帧之前的数据。 总结起来: - IDR帧一定是I帧,但I帧不一定是IDR帧。 - IDR帧会导致DPB被清空,而普通的I帧不会,因为其后面的帧解码有可能要参考到普通I帧前面的帧。 - 也正因为以上道理,在对视频流或者视频文件在播放过程中做seek操作的时候,一定要找到IDR帧开始进行解码播放,否则如果在I帧位置进行播放,有可能会因为其后面的帧解码时要依赖于这个I帧前面的帧而造成花屏。 dts与pts dts、pts 的概念如下所述: - dts(Decoding Time Stamp):即解码时间戳,这个时间戳的意义在于告诉播放器该在什么时候解码这一帧的数据。 - pts(Presentation Time Stamp):即显示时间戳,这个时间戳用来告诉播放器该在什么时候显示这一帧的数据。 实际上dts和pts的概念与B帧息息相关,当编解码器只有I帧和P帧的时候,视频解码和播放的顺序是完全一致的,因此dts与pts是相等的,这个时候讨论dts和pts就意义不大了,播放器只需要按照原来的顺序进行解码和显示就可以了。 但是如果引入了B帧,就会导致解码和显示的顺序不一样。这是因为: - B帧的解码需要依赖于其后面的帧,所以解码B帧的时候要先把其后面的帧解码才能对B帧成功解码,但是在播放的时候则需要按照原来的顺序进行播放,也就是说解码和播放显示的顺序不一致。 例如: 一个帧序列播放的顺序是:I B1 B2 P; - I帧可以独立解码,因此首先解码,I帧解码顺序为1,播放顺序为1; - B1和B2的解码需要依赖于I帧和后面的P帧,所以需要等P帧先解码; - P帧解码顺序为2,播放顺序为4; - B1的解码需要依赖于B2,因此B2先解码,B2的解码顺序为3,播放顺序为3; - B1的解码顺序为4,播放顺序为2。 也就是说: Frame: I B1 B2 P; dts: 1 4 3 2; pts: 1 2 3 4; 参考资料 1. 《音视频开发进阶指南》第一章; 2. H264中I帧和IDR帧的区别 3. 理解音视频PTS和DTS