关于H.264 profile-level-id

我们在WebRTC开发中,如果采用的是H.264来作为视频流编码类型,就会面临一个问题,那就是编码端和解码端需要进行协商各自的编解码能力。例如,如果编码端使用了高级别的profile和level,或使用了解码器不支持的编码特性,那么对解码端来说就是个灾难了。

大家知道,H.264的Profile以及Level有好多种,而并不是每一种编码器或者解码器都支持每一个Profile和Level。实际应用当中,我们经常会看到一个3个字节的值(例如42801f),它是H.264 SPS信息的头三个字节,用来标识H.264的profile和level,这篇文章就是来简单记录和说明一下H.264的profile-level-id怎么来看。

H.264的Profile和Level有哪些?

这个就不赘述了,在以下2个链接有详尽的列表:
https://en.wikipedia.org/wiki/Advanced_Video_Coding#Profiles
https://en.wikipedia.org/wiki/Advanced_Video_Coding#Levels
虽然有这么多种Profiles和Levels,但是在WebRTC,或者实时流媒体处理中,常见的就只有几种。例如WebRTC默认使用的是OpenH264,它的编码器只支持Constrained Baseline + Level 5.2(见OpenH264 github首页说明)。

参考文档

典型的profile-level-id示例

profile-level-id常见于sdp中,例如,在chrome://webrtc-internals中,我们如果推送一个H.264编码的视频流,在local sdp中可以看到这样的profile-level-id:
在这里插入图片描述
这个profile-level-id在我们上面参考资料的RFC6184中的8.1 Media Type Registration一节中有比较详细的说明。

下面我举例子来说明一下怎么来看。就拿上图中出现的那几个值来说吧。包括以下四种:

42001f
42e01f
4d0032
640032

这3个字节都是16进制表示。第一个字节表示profile_idc(0x42, 0x4d, 0x64),第二个字节表示profile-iop,第三个字节表示level。其中第一个字节和第三个字节比较好理解,例如:

  • 42001f : 第一个字节0x42 = 十进制66,根据参考资料维基百科页面上得知,66对应Baseline Profile (BP, 66)。第三个字节0x1f = 十进制31,对应的Level就是3.1
  • 42e01f : 第一个字节和第三个字节同上,中间的0xe0我们一会儿说
  • 4d0032 : 第一个字节 0x4d = 十进制77 = Main Profile (MP, 77)。第三个字节0x32 = 十进制50,Level就是5.0
  • 640032 : 第一个字节 0x64 = 十进制100 = High Profile (HiP, 100)。第三个字节同上
    所以,第一个和第三个字节就很简单,一看就明白。

下面我们来看看中间的那个字节。

在RFC6184中介绍,第二个字节是profile-iop,它的每一位对应:constraint_set{0,1,2,3,4,5}_flag,共6位,最后2位是保留位,始终为0。

所以让我们回头看看上面的那个42e01f。首先通过第一个字节和第三个字节,我们知道它是Baseline Profile + Level 3.1,但是42001f和42e01f的差别是什么呢?那就要看第二个字节0xe0了,它的二进制是:

1 1 1 0 0 0 00

我们通过查询参考资料中ITU制定的那个文档的A.2.1.1 Constrained Baseline profile一节看到以下描述:

Decoders conforming to the Constrained Baseline profile at a specific level shall be capable of decoding all bitstreams in which all of the following are true:
– profile_idc is equal to 66 or constraint_set0_flag is equal to 1,
– constraint_set1_flag is equal to 1,
– level_idc and constraint_set3_flag represent a level less than or equal to the specified level.

意思是解码器在以下3个条件符合时具有解码所有比特流的能力:

  1. profile_idc是66或者constraint_set0_flag=1,OK,成立(profile_idc是0x42,也就是十进制66,constraint_set0_flag等于1)
  2. constraint_set1_flag=1,OK,成立(constraint_set1_flag等于1)
  3. 这一条我不是特别理解,level_idc(3.1) 和 constraint_set3_flag(0) 表示一个小于或者等于指定level的level?

所以通过猜想,42e01f应该是Constrained Baseline Profilee,而42001f是BaselineProfile,因为42001f至少不满足上面条件1和2。

另外,在WebRTC的移动端Native SDK源码中也可以找到2种profile和level的定义,源码分别位于:

\sdk\android\api\org\webrtc\VideoCodecInfo.java (Android Native SDK)
\sdk\objc\components\video_codec\RTCH264ProfileLevelId.mm (iOS Native SDK)

我们在代码中可以看到,它只定义了2种profile和level组合:

42e01f : Constrained Baseline Profile + Level 3.1
640c1f : Constrained High Profile + Level 3.1

顺便,我们看看640c1f中那个0x0c,它的二进制是:

0 0 0 0 1 1 00

查阅ITU文档(A.2.4.2 Constrained High profile一节),看到有一条描述:

profile_idc is equal to 100, constraint_set4_flag is equal to 1, constraint_set5_flag is equal to 1, and level_idc represents a level less than or equal to the specified level.

profile_idc等于100(即0x64),constraint_set4_flag和constraint_set5_flag要等于1(满足),所以640c表示的就是Constrained High Profile。

另外,也可以简单地通过上面参考资料中那个维基百科页面上来判断是什么profile,如下图:
在这里插入图片描述
constraint set x (x = 1,3,4, 4&5…)对应的就是constraint_set{0,1,2,3,4,5}_flag相应位的值需要是1

OK,至此,我们以后再见到profile-level-id,就可以很快知道它是什么含义了。

再随便来几个:
64001f (High Profile + Level 3.1)
640016 (High Profile + Level 2.2)
640c34 (Constrained High Profile + Level 5.2)
42801e (Baseline Profile + Level 3.0)

最后,在github上还有人用js写了一个profile-level-id解析工具,https://github.com/ibc/h264-profile-level-id,也可以协助我们理解profile-level-id。

  • 7
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值