【发布时间】:2012-03-25 23:28:10
【问题描述】:
我有一个来自 IP 摄像机的原始 H.264 流,打包在 RTP 帧中。我想将原始 H.264 数据放入文件中,以便可以使用 ffmpeg 进行转换。
因此,当我想将数据写入原始 H.264 文件时,我发现它必须如下所示:
00 00 01 [SPS]
00 00 01 [PPS]
00 00 01 [NALByte]
[PAYLOAD RTP Frame 1] // Payload always without the first 2 Bytes -> NAL
[PAYLOAD RTP Frame 2]
[... until PAYLOAD Frame with Mark Bit received] // From here its a new Video Frame
00 00 01 [NAL BYTE]
[PAYLOAD RTP Frame 1]
....
所以我从之前的RTSP 通信中得到了Session Description Protocol 中的SPS 和PPS。此外,在开始视频流本身之前,相机会在两条单独的消息中发送SPS 和PPS。
所以我按以下顺序捕获消息:
1. Preceding RTSP Communication here ( including SDP with SPS and PPS )
2. RTP Frame with Payload: 67 42 80 28 DA 01 40 16 C4 // This is the SPS
3. RTP Frame with Payload: 68 CE 3C 80 // This is the PPS
4. RTP Frame with Payload: ... // Video Data
然后出现了一些带有有效负载的帧,在某些时候出现了带有Marker Bit = 1 的 RTP 帧。这意味着(如果我没记错的话)我有一个完整的视频帧。在此之后,我再次从有效负载中编写前缀序列(00 00 01)和NAL,并继续执行相同的过程。
现在,我的相机在每 8 个完整的视频帧之后再次向我发送 SPS 和 PPS。 (同样在两个 RTP 帧中,如上例所示)。我知道,尤其是 PPS 可以在流式传输之间发生变化,但这不是问题。
我现在的问题是:
1.我需要每 8 个视频帧编写一次 SPS/PPS 吗?
如果我的SPS 和我的PPS 不更改,将它们写在我的文件的开头就足够了,仅此而已?
2。如何区分 SPS/PPS 和普通 RTP 帧?
在解析传输数据的 C++ 代码中,我需要区分具有正常有效负载的 RTP 帧和带有 SPS/PPS 的帧。我怎样才能区分它们?好的,SPS/PPS 帧通常要小得多,但这不是可以依赖的保存调用。因为如果我忽略它们,我需要知道我可以丢弃哪些数据,或者如果我需要编写它们,我需要将00 00 01 前缀放在它们前面。 ?还是每 8 个视频帧出现一次的固定规则?
【问题讨论】:
-
感谢您提出这个问题。我和你有同样的问题。我通读了 live555 源代码,不知道他们为什么要这样保存每个数据包/帧。读完这篇文章后,我明白了。作为基于live555实现的建议,marker位只用于其他编解码器,H264有自己的start_bit和end_bit来表示帧的开始/结束,H264不使用marker位。