WebRTC 是如何切帧的?

WebRTC在发送视频帧的时候,是会被切割成一个个小包的,作为网络传输,任何在网络中传输的包都应该小于MTU,这是常识。那么问题来了,假设需要发送一个又一个已压缩的H.264视频帧的时候,是如何切帧组包的呢?

H.264裸帧切割逻辑

首先,每一次WriteFrame时,我们塞入的都是一个完整的H.264裸帧,例如以下帧的Hex显示:

  • 该帧为一个H.264帧
  • 携带StartCode

那么,像这样的一个帧到了WebRTC内部,会怎么处理呢?

  • 首先,内部会先对该帧进行编码类型判别,要确认是H.264。
  • 然后,根据StartCode,对帧的每一个NALU进行一次切割,StartCode包括:00 00 00 01 与 00 00 01都算,切割完毕之后,得到所有切割后的Buffer块数量。
  • 假设有10个块,那就用一个数组容器将这9个块分别缓存起来,并将他们头部的 00 00 00 01 或 00 00 01 去除,剩下的字节等待下一步行动。
  • 那么,假设NALU超过MTU怎么办?那就只能根据MTU再进行二次切割。每一个NALU又被切割成多个NALU子分片,这些分片会被套上一个FU头,FU头部包含了NALU的类型(如I帧、P帧等)、NALU的长度、以及当前分片的序号和结束标志等信息,这些信息都可以用来重组NALU。
  • 接下来,对每一个切割后的数据作为Payload载荷,进行加密,这里要注意,SRTP加密后的数据和原始数据的长度是不一样的,例如下图,加密前后加密后的长度差异:

  • 加密后,对每一段数据套上一个RTP头,以及一个加密尾,如下图,其中SRTP头占12字节,SRTP尾还有个认证标签(AuthTag)占了10个字节。

  • 这样的一个包,最终被发送到网络上。

接收端如何组包呢?

首先,接收端会现在JitterBuffer中进行一些算法,来保证传输的有序性与完整性。然后等整个帧组合完毕后,我们得到了一个完整的帧。

这个帧是如何组成的呢?大部分都是切帧的反向操作,但区别在于:

  • 与切帧区别的是,每一个子包并不知道原先的StartCode是00 00 00 01 还是 00 00 01,所以,都用 00 00 00 01来替代。这就造成了裸帧数据长度与原先产生了差异。
  • 另外,组和完毕后的裸帧,也是携带StartCode,不需要我们再去手动添加。但要清楚的是,网络传输的时候,RTP的载荷是不携带StartCode的,他是根据我们收到后根据包序列自己添加上去的,这点不要混淆。
  • 假如NALU本身超过了MTU,收到的时候不会立刻对每一个NALU子分片加上StartCode,而是等到NALU全部组和完成后,再对整个NALU完整分片加上StartCode。
  • 根据RTP特性,同一个帧在传输的时候,时间戳一致,以Marker结尾,你可以看成是:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

毕加索解锁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值