首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >H.264上的RTP -识别SPS和PPS帧

H.264上的RTP -识别SPS和PPS帧
EN

Stack Overflow用户
提问于 2012-03-08 13:26:44
回答 2查看 32.3K关注 1票数 17

我有一个原始H.264流从一个IP相机打包在RTP帧。我想把原始H.264数据转换成一个文件,这样我就可以用ffmpeg来转换它了。

因此,当我想将数据写入我的原始H.264文件时,我发现它必须如下所示:

代码语言:javascript
复制
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]
....

因此,我从前面的SPS通信中从Session Description Protocol获得Session Description ProtocolRTSP。另外,相机在以视频流本身开始之前,将SPSPPS发送到两个单独的消息中。

因此,我按以下顺序捕获消息:

代码语言:javascript
复制
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个完整的视频帧,SPSPPS再次。(同样在两个RTP框架中,如上面的示例所示)。我知道,特别是PPS可以在流媒体之间进行转换,但这不是问题所在。

我现在的问题是:

1.我是否需要每8帧写一次SPS/PPS?

如果我的SPSPPS没有改变,那么在我的文件一开始就编写它们就足够了,仅此而已吗?

2.如何区分SPS/PPS和普通RTP帧?

在解析传输数据的C++代码中,我需要在具有正常有效负载的RTP帧和承载SPS/PPS的帧之间进行区别。我怎么才能区分他们?好的,SPS/PPS帧通常要小得多,但这不是一个可以依赖的保存调用。因为如果我忽略它们,我需要知道我可以丢弃哪些数据,或者如果我需要写它们,我需要将00 00 01前缀放在它们前面。?或者它们每8帧出现一次是一条固定的规则吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-03-08 13:33:42

  1. 如果SPS和PPS没有改变,你可以省略它们,除了第一个。
  2. 您需要解析每个NAL的nal_unit_type字段,对于SPS,nal_unit_type==7;对于PPS,nal_unit_type==8。

我记得,nal_unit_type是帧的第一个字节的较低的5位。

代码语言:javascript
复制
nal_unit_type = frame[0] & 0x1f;
票数 16
EN

Stack Overflow用户

发布于 2012-09-01 09:27:45

  1. 您应该在流开始时编写SPS和PPS,只有当它们在流的中间发生变化时才能这样做。
  2. SPS和PPS帧被封装在STAP单元(通常是STAP )中,NAL 24型(STAP)或25 (STAP)STAP格式用RFC-3984节5.7.1描述。
  3. 不要依赖标记位,在NAL头中使用开始位和结束位。
  4. 对于分段视频帧,您应该使用第一个片段(F,NRI)的3个NAL单元比特与有效载荷中的第一个字节的5个NAL类型比特(仅针对设置为1的数据包)重新生成NAL单元,请检查RFC-3984条5.8: 碎片NAL单元的NAL单元类型八进制不包括在碎片单元有效载荷中,而是碎片NAL单元的NAL单元类型八进制的信息在碎片单元的FU指示八组的F和NRI字段以及FU头的类型字段中传递。

编辑:关于碎片单元的NAL单元构造的更多解释:

这是FU-A有效负载的前两个字节(就在rtp头之后):

代码语言:javascript
复制
|  FU indicator |   FU header   |
+---------------+---------------+
|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|F|NRI|  Type   |S|E|R|  Type   |
+---------------+---------------+

要构造NAL单元,应从"FU标头“取"Type”,从"FU指示器“取"F”和"NRI“。

这里是一个简单的实现

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9618369

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档