音视频问题汇总–H264标准中u和ue的差别

问题背景

昨天小伙伴反馈一个问题,说我们的app和第三方客户IPC进行通信时候出现崩溃了,急需支援。

所以临危受命,3个小时完成突击,找到问题,紧急压测上线。在此记录一下该问题的排查过程。

后来拿到客户的IPC时候,进行本地验证,也是常用的三段论逐一排查:

  • 如果是生产端或发送端的问题,则在发送端送数据之时抓包;
  • 如果是消费端或接收端的问题,则在接收端收数据之时抓包;
  • 如果是传输段问题,则通过PC或者更换设备验证;

所以从发送端,接收端分别抓包,依次验证SPS,PPS参数,视频流分析,最后发现和抓包没有关系,属于app兼容性问题。

问题分析

然后通过抓取本地app的log,逐步分析,最初排查问题是线程崩溃

音视频问题汇总--H264标准中u和ue的差别

然后通过log,往回倒退,依次排查设置的参数,发现在其中一次设置时出现分辨率有明显的变化

音视频问题汇总--H264标准中u和ue的差别

最初怀疑对方发包异常,但是经过一通排查,然并不是。

所以重新开始从数据接收,解封包,解码以及排查,最后发现原来是H264 SPS解析时候异常了。

音视频问题汇总--H264标准中u和ue的差别

其中“祖传”代码中该值frame_cropping_flag采用了ue(payload_data, data_len, start_bit),这样正好IPC这边设置了chroma_format_idc,就会导致计算frame_crop_top_offset和frame_crop_bottom_offset错误。

找到问题很快就处理掉了,但是之前为啥没有出现问题呢?

分析了之前保存的抓包:大部分chroma_format_idc没有设置,所以crop都没有真正生效,所以隐藏bug一直没有暴雷。

补充知识

chroma_format_idc和frame_cropping_flag

依据H264 SPEC,可以看出chroma_format_idc读取方式是ue(v)和而frame_cropping_flag读取方式是u(1)

音视频问题汇总--H264标准中u和ue的差别

音视频问题汇总--H264标准中u和ue的差别

其中chroma_format_idc 指定亮度采样的色度采样。 chroma_format_idc 的值应在 0 到 3 的范围内(包括 0 和 3)。 当 chroma_format_idc 不存在时,应推断其等于 1(4:2:0 色度格式)。

音视频问题汇总--H264标准中u和ue的差别

frame_cropping_flag 等于 1 指定序列参数集中的下一个是帧裁剪偏移参数。frame_cropping_flag 等于 0 指定帧裁剪偏移参数不存在。而且只有High Profile及其以上时候才会设置为1,其他格式建议不进行设置,所以之前的坑没有爆。

音视频问题汇总--H264标准中u和ue的差别

u(1) VS ue(v)

H264的spec中指定了每个语法元素的解析过程。对于某些语法元素,使用由竖线分隔的两个描述符。在这些情况下,当 entropy_coding_mode_flag 等于 0 时应用左侧描述符,当 entropy_coding_mode_flag 等于 1 时应用右侧描述符。

音视频问题汇总--H264标准中u和ue的差别

其中u(n)表示使用 n 位的无符号整数。当语法表中n为“v”时,比特数以依赖于其他语法元素的值的方式变化。该描述符的解析过程由函数 read_bits( n ) 的返回值指定,该函数解释为无符号整数的二进制表示形式,并且首先写入最高有效位。

ue(v)无符号整数 Exp-Golomb 编码语法元素,左位在前。

关于u(1)和ue(v)的描述,在标准的第9章节有做详细介绍

音视频问题汇总--H264标准中u和ue的差别

音视频问题汇总--H264标准中u和ue的差别

音视频问题汇总--H264标准中u和ue的差别

如果感觉Spec理解困难,悄咪咪的告诉一个详细介绍指数哥伦布熵编码的地址,一般人我不告诉他:

https://www.zzsin.com/article/golomb.html

关于u(n)和ue(v)在FFMPEG中的实现,可以参考如下代码:

音视频问题汇总--H264标准中u和ue的差别

 

音视频问题汇总--H264标准中u和ue的差别

ff_cbs_read_unsigned()

ff_cbs_read_unsigned()函数用于从比特流中读取无符号整数。

音视频问题汇总--H264标准中u和ue的差别

ff_cbs_trace_syntax_element()

ff_cbs_trace_syntax_element() 函数用于跟踪从比特流读取语法元素或向比特流写入语法元素

音视频问题汇总--H264标准中u和ue的差别

cbs_read_ue_golomb()

cbs_read_ue_golomb()函数用于使用一元指数 (UE) 哥伦布码从比特流中读取无符号整数。

音视频问题汇总--H264标准中u和ue的差别

同时也参考了最新版本的webrtc,其实现过程是另外一种,不过基本类似:

音视频问题汇总--H264标准中u和ue的差别

我是一枚爱跑步的程序猿,维护公众号和知乎专栏《MediaStack》,有兴趣可以关注,一起学习音视频知识,时不时分享实战经验。

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。

(0)

相关推荐

发表回复

登录后才能评论