Tob*_*oby 13 c++ rtp rtsp h.264
我有一个来自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]
....
Run Code Online (Sandbox Code Playgroud)
所以我得到的SPS和PPS从Session Description Protocol我的前面的RTSP通信.此外,相机在开始使用视频流之前发送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
Run Code Online (Sandbox Code Playgroud)
然后有一些带有负载的帧,在某些时候有一个带有的RTP帧Marker Bit = 1.这意味着(如果我做对了)我有一个完整的视频帧.在此之后,我再次编写前缀序列(00 00 01)和NAL有效载荷,然后继续执行相同的过程.
现在我的相机向我的每8个完整的视频帧后SPS和PPS试.(再次在两个RTP帧中,如上例所示).我知道特别是PPS流媒体之间可以改变,但这不是问题.
我现在的问题是:
1.我是否需要每隔8个视频帧写一次SPS/PPS?
如果我SPS和我的PPS不改变它应该足以让它们在我的文件的最开始写,仅此而已?
2.如何区分SPS/PPS和普通RTP帧?
在我解析传输数据的C++代码中,我需要在具有正常有效负载的RTP帧与带有该传输数据的RTP帧之间进行区分SPS/PPS.我该如何区分它们?好吧,SPS/PPS帧通常会更小,但这不是一个依赖的保存呼叫.因为如果我忽略它们,我需要知道我可以丢弃哪些数据,或者如果我需要编写它们,我需要将00 00 01前缀放在它们前面.?或者它是每隔8个视频帧出现的固定规则吗?
cip*_*hor 13
我记得,nal_unit_type是帧的第1个字节的低5位.
nal_unit_type = frame[0] & 0x1f;
Run Code Online (Sandbox Code Playgroud)
ara*_*rdi 12
您应该在流的开头编写SPS和PPS,并且只有在流中间更改时才编写SPS和PPS.
SPS和PPS帧打包在STAP NAL单元(通常为STAP-A)中,NAL类型24(STAP-A)或25(STAP-B)STAP格式在RFC-3984第5.7.1节中描述
不要依赖标记位,使用NAL头中的起始位和结束位.
对于分段视频帧,您应该使用第一个片段(F,NRI)的3个NAL单元位和有效负载中的第一个字节的5个NAL类型位重新生成NAL单元(仅适用于起始位设置为1的数据包)检查RFC-3984第5.8节:
分段NAL单元的NAL单元类型八位字节不包括在分段单元有效载荷中,而是分段NAL单元的NAL单元类型八位字节的信息在FU指示符八位字节的F和NRI字段中传送.分段单元和FU头的类型字段.
编辑:关于碎片单元的NAL单元构造的更多解释:
这是FU-A有效载荷的前两个字节(在rtp标题之后):
| 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 |
+---------------+---------------+
Run Code Online (Sandbox Code Playgroud)
要构建NAL单元,你应该从"FU Header"中取"Type",从"FU指示器"取"F"和"NRI"
这是一个简单的实现
| 归档时间: |
|
| 查看次数: |
27612 次 |
| 最近记录: |