H264完整一帧被分成多片时,如何进行RTMP推流
一帧frame一般是一张图片。是一组明度采样的数组。帧有I帧、B帧、P帧等。I帧是帧内编码,不依赖其它。首个I帧叫IDR帧。IDR帧是立即刷新,不将错误传播下去。
B帧是双向预测编码,是双向差别帧。P帧是向前预测帧。
片slice是一帧内的一块数组。一张图片至少有一片或多片。
一般I帧和P帧比较多分片。
一帧多片推送RTMP(srs_rtmp)服务器时,会绿屏花屏的。
如图
IDR帧被7片。每一片都是以“00 00 01”开始。如果你直接将此数据直接推送给RTMP服务器,客户端拉流播放就会花屏。
如何处理呢?其实很简单,把一帧多片打成一个包发送即可。但是要注意,关键就在这里。把一帧多片复制到数组,发送的时候
需要把头部的“00 00 01”或“00 00 00 01”去掉发送才可以成。注意要调用srs_write_h264_raw_frame这个接口,如果你调用srs_h264_write_raw_frames
这个接口的话,里面还是会把你打包好的帧拆成多片分发。实际上封包发送是调用mux_avc2flv,封装成rtmp的格式整包发送的。这个mux_avc2flv函数
主要作用是封装H264的裸流。
在这个函数里面也就是增加了一个5个字节的协议头。 1bytes, FrameType | CodecID, 1bytes, AVCPacketType, 3bytes, CompositionTime, the cts.
再次强调,我们把一帧多片拼成一个数组时,只需要去掉头部的"00 00 01",后面的“00 00 01”不用去掉。
当然我说的这些,是调用srs_rtmp库推流的。
P帧多个分片也是同样处理。如何判断P帧多片的接收呢?
很简单。“00 00 00 01 41 9A” 中,“00 00 00 01” 是一帧开始,“41”与上0x1f等于1表示其是P帧(0x41&0x1f=1)。“9A”与上“0x80”等于0x80,表示其是P帧分片的开始。
到这里,你应该猜出来了,那就是,直到下个P帧的下个字节“9A”与上“0x80”等于0x80时,那就是一帧多片的结束。此时也是下一帧的开始。
同理,你将一帧多片存入数组,去掉头部的"00 00 00 01"发送及可。