我正在对Node Media Server进行扩展,以将传入流作为MP4保存到磁盘。对于这种向MP4的转换,我主要依靠Apple QuickTime Movie Specification,The ISO/IEC 14496-14 Specification(我在Rust-MP4 GitHub存储库中免费发现)和The HLS.js Source Code
我目前正在测试一个视频。一旦成功,我将开始尝试其他视频。对于我的用例,我只需要支持H.264视频和AAC音频。
当前,当建立RTMP连接时,我收到的前3个数据包是一致的:
AMF metadata
数据包(RTMP cid = 6),其中包含诸如视频宽度,视频高度,比特率,音频采样率等信息。audio
数据包(RMTP cid = 4),其中包含7个字节的数据。我认为这是AAC配置数据包video
数据包(RTMP cid = 5),其中包含46个字节的数据。我认为这是AVC配置数据包编写MP4 moov
原子时,有两个地方需要利用AMF元数据(可能位于这两个配置数据包中)以外的其他信息:
esds
原子中,The HLS.js source附加了“ config”数据。我假设我只是将音频配置数据包中的整个7字节有效负载附加到此处avcC
原子中,The HLS.js source附加“ sps”和“ pps”数据。这是我问题的根源关于这46个字节的解析,我在Node Media Server和HLS.js中发现了似乎解析相同数据的代码。这两段代码之间的区别在于,Node Media Server在数据包的开头期望额外的13个字节的数据。我收到的数据包似乎包含这13个字节,因此我仅遵循它们的先后顺序来提取width
,height
,profile
,compat
和level
信息。特别是46个字节是:
[0x17, 0x00, 0x00, 0x00, 0x00, 0x01, 0x42, 0xc0, 0x1f, 0xff, 0xe1, 0x00, 0x19, 0x67, 0x42, 0xc0, 0x1f, 0xa6, 0x11, 0x02, 0x80, 0xbf, 0xe5, 0x84, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0xc2, 0x3c, 0x60, 0xc8, 0x46, 0x01, 0x00, 0x05, 0x68, 0xc8, 0x42, 0x32, 0xc8]
将此分解为我可以 容易 解析的字节(在使用指数哥伦布编码之前):
[
0x17, // "frame type", specifies H.264 or HVEC
0x00, 0x00, 0x00, 0x00, 0x01, // ignored. Reserved?
0x42, // profile
0xc0, // compat
0x1f, // level
0xff, // "info.nalu" (per Node Media Server source)
0xe1, // "info.nb_sps" (per Node Media Server source)
0x00, 0x19, // "nal size"
// Above here are the bits exclusively seen by Node Media Server (specific to RTMP?)
// Below here are the bits passed to HLS.js as "unit.data" (common to all AVC1 streams?):
0x67, // "nal type"
0x42, // profile (again?)
0xc0, // compat (again?)
0x1f, // level (again?)
// Below here, data is not necessarily byte-aligned as Exponential Golomb encoding is used
// ...
]
现在我遇到的问题是在创建moov
原子(特别是avcC
原子期间),我需要同时了解sps
和{{ 1}}个字节。 From the HLS.js source似乎pps
可能只是这个视频配置数据包减去前13个字节。但是,如何找到sps
? pps
实际上是此数据包的最后几个字节,我应该将其拆分到某个地方吗?会以其他小包的形式发送吗?如果需要两个视频数据包,我是否可以通过某种方式对其进行区分,以便知道哪个是pps
,哪个是sps
?
如果我能弄清楚这最后一点,那么我应该完全写完pps
数据包(此后,我只需要找出moov
数据包的正确格式即可,应该有工作代码)
更新:为了进行记录,我只是检查了正在传递的第四个数据包,以查看其中是否包含mdat
数据。重新连接到流约20次后,第四个数据包始终是pps
数据包(RTMP cid = 5),但是数据包的大小在16000字节到21000字节之间。我怀疑这是合法的视频数据。
第二次更新::刚解析完SPS时,我刚刚检查了视频配置数据包中的偏移量,并且我位于字节23(video
)上。因此,很可能PPS 实际上是在此字节数组的末尾,但是我不确定分隔符/标头有多少个字节(NAL类型,NAL长度等)以及多少个字节是实际的PPS。