extended timestamp of type3 chunk


调试微信小程序rtmp推流到一款rtmpserver, 流推不上来, 服务端报码流错乱.

抓包查看原因,发现小程序发出的rtmp包的chunk类型都是type0+type3的组合,没有type2的包,每个message的首个chunk封装都是type0的chunk,使用绝对时间戳.并且每次一开始的音视频message时戳并不是从0开始,而是一个比较大的值,好像是微信app运行的时间秒数.

查看抓包内容发现问题出在了type3的chunk上

这是第一个视频message的第一个chunk的前面十几个字节

1
06 FF FF FF 00 19 BB 09 01 00 00 00 01 0E 35 EB 17 01

这是第一个视频mesage的第二个chunk的前面几个字节

1
C6 01 0E 35 EB AA 02 

可以看到这个message的第二个chunk是一个type3类型的chunk包,但是紧接着的四个字节010E35EB和第一个chunk的扩展时戳010E35EB是一样的,也就是说这个type3类型的chunk后面应该是也跟了四字节的扩展时戳. 而这个rtmpserver显然没有认为type3的chunk会含有扩展时戳,所有解析后续字节流报错。

rtmp服务器和客户端的表现


上面这种情况总结来说,就是一个message分为type0 + type3 的chunk,如果type0的chunk包含有扩展时戳,那么后续同属于这个message的type3的chunk也包含四字节的扩展时戳。

对于这种情况,搜索到一篇srs作者的文章,这里面说了"rtmp协议讲了type3的chunk是没有扩展时戳的",并粘贴了rtmp协议的英文原文。

1
2
3
4
5
6
6.1.3. Extended Timestamp
This field is transmitted only when the normal time stamp in the
chunk message header is set to 0x00ffffff. If normal time stamp is
set to any value less than 0x00ffffff, this field MUST NOT be
present. This field MUST NOT be present if the timestamp field is not
present. Type 3 chunks MUST NOT have this field.

这里面的协议原文在互联网还能搜索到片段,但是在最新的RTMP Specification 1.0中已经搜索不到这一段了,这一段可能是老版本的协议内容,最新的应该是协议中已经去掉了。

这篇文章还讲到nginx-rtmp遇到这种type3的chunk是会固定读取四字节的扩展时戳的。

我自己实测srs,nginx-rtmp,lal这几种rtmp server都是能正常解析这种情况的码流。说明在这种情况下这些服务器的实现是会去读取四字节的扩展时戳的。

查看ffmpeg的rtmp拉流代码,在这种情况下同样也会去读取扩展时戳。那么看起来事实上这些常用工具和著名的rtmp server都是认为type3的chunk在这种情况下是包含四字节的扩展时戳的。

协议中一探究竟


来看最新的RTMP Specification 1.0中究竟是怎么说的。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
5.3.1.3. Extended Timestamp
 The Extended Timestamp field is used to encode timestamps or
 timestamp deltas that are greater than 16777215 (0xFFFFFF); that is,
 for timestamps or timestamp deltas that don’t fit in the 24 bit
 fields of Type 0, 1, or 2 chunks. This field encodes the complete
 32-bit timestamp or timestamp delta. The presence of this field is
 indicated by setting the timestamp field of a Type 0 chunk, or the
 timestamp delta field of a Type 1 or 2 chunk, to 16777215 (0xFFFFFF).
 This field is present in Type 3 chunks when the most recent Type 0,
 1, or 2 chunk for the same chunk stream ID indicated the presence of
 an extended timestamp field.

最后一句,This field is present in Type 3 chunks when the most recent Type 0, 1, or 2 chunk for the same chunk stream ID indicated the presence of an extended timestamp field.

意思是当某个type3的chunk前面最近的一个包含相同的stream ID的type0、type1或者type2的chunk有extended timestamp field, 那么extended timestamp field也存在于这个type3的chunk中。

这一段说的很明白了,只要是相同stream ID的前面的chunk有extended timestamp field,那么这个type3的chunk也应该有extended timestamp field。

实际情况中type3的chunk可能是一个message的首个chunk也可能不是首个chunk,对于不是首个chunk的情况来说,其实这个extended timestamp field完全没有任何意义, 因为这个message的时间戳信息由首个chunk和之前的chunk决定。但是标准明确说了,type3的chunk就是可能有扩展时间戳字段的。