ZLMedia--h264的流程

将conf\config.ini中[rtsp ]directProxy=1。和AAC的流程基本相同。

还未搞明白直接代理和非直接代理在流程上有什么不同。

一.RtspSession::onRecv--RtspSession.cpp

从网络上得到一个包。对于H264包buf->data()[1]==0x0。

1.用FFMPEG推送的第一个视频包

(1)第一个字节0x24,表示开始。

(2)第二个字节0x00,是视频。

(3)3、4字节0x 00 2a,用10进制表示42,表示RTP包的长度为42.

(4)RTP Payload的第一个字节0x18(0001 1000),即10进制24。这个字节是NAL Header ,

 

Type为24,表示:STAP-A(单一时间组合包模式 A,用于一个 RTP 包荷载多个 NALU)

 一个 RTP 包荷载多个 NALU,结构如下。  一个 RTP 包荷载多个 NALU,结构如下。

 结合抓图:

00 15:两个字节的长度, 表示第一个NALU的长度为21(10进制,含NALU HEADER)。

67:一个字节的NALU HEADER,即0110 0111。0:必须为0, 11 :指示该 NALU 重要性,该值越大说明该 NALU 越重要,需要受到保护。00111:为7,SPS(序列参数集)

向后数21个字节

00 04:两个字节的长度, 表示第二个NALU的长度为4(10进制,含NALU HEADER)。

68:一个字节的NALU HEADER,即01101000。0:必须为0,11表示非常重要;01000:为8,PPS(图像参数集)。

2.用FFMPEG推送的关键帧的开始视频包

 (1)Payload第一个字节7c即0111 1100

11100:28表明为分片模式。用于将一个 NALU 分片到多个 RTP 包中。RTP 头部之后的第一个字节为 FU indicator,第二个字节为 FU header。

(2)

 (3)FU indicator 结构如下所示,同NAUL HEADER 。

 (4)FU header 结构如下所示,字段含义如下

 第二个字节85(10000101),type 101为5:IDR 图像的片(关键帧)。

3.IDR中间的一包数据

 (1)Payload第一个字节7c即0111 1100。11100:28表明为分片模式。用于将一个 NALU 分片到多个 RTP 包中。RTP 头部之后的第一个字节为 FU indicator,第二个字节为 FU header。

(2)第二个字节为05即0000  0101。表白是一个中间的NALU,类型仍旧为5(IDR关键帧)。

4.IDR帧的最后一帧

(1)Marker变为true.

(2)第二个字节变为45,即0100 0101。表示关键的最后一帧。

二. HttpRequestSplitter::input--HttpRequestSplitter.cpp

b  /opt/ZLMediaKit/src/Http/HttpRequestSplitter.cpp:67  if data[1]==0x0

b  /opt/ZLMediaKit/src/Http/HttpRequestSplitter.cpp:65  if header_size==46

三.RtspSplitter::onRecvHeader--RtspSplitter.cpp

b  /opt/ZLMediaKit/src/Rtsp/RtspSplitter.cpp:63

在这个函数中将rtp包和rtsp包分别处理,在这个函数中,可以方便的观察各个rtp包。

四.RtspSession::onRtpPacket--RtspSession.cpp

 这个函数将RTP与RTCP包分开处理。

RTP包调用:handleOneRtp函数。传入参数时将RTSP去掉,前4个字节。

五.RtpMultiReceiver::handleOneRtp--RtpReceiver.h

没有对数据进行改变,将由track处理。

六.RtpTrack::inputRtp--RtpReceiver.cpp

b  /opt/ZLMediaKit/src/Rtsp/RtpReceiver.cpp:99

在这个函数中又重新加上了RTSP的前4个字节。并调用  rtp->ntp_stamp = _ntp_stamp.getNtpStamp(rtp->getStamp(), sample_rate);改变时间戳。

七.RtspSession::onBeforeRtpSorted--RtspSession.cpp

调用updateRtcpContext对RTCP进行处理。RTCP先不详细解释。

###################################################################

1、2、3、4、5、6、7可以重复执行,存储起来供后续调用。

###################################################################

八.RtspSession::onRtpSorted--RtspSession.cpp

将RTP包存储到推流相关绑定的源中。

九.RtspMediaSourceImp::onWrite--RtspMediaSourceImp.h

将RTP包存储到解复用中。

 十.RtspDemuxer::inputRtp--RtspDemuxer.cpp

 将RTP包存储到解码器中。

==================================以后的步骤是和ACC有区别的==========================================

十一、H264RtpDecoder::inputRtp--H264Rtp.cpp

调用解码器。

十二、H264RtpDecoder::decodeRtp--H264Rtp.cpp

调用不同的函数对不同的包进行解码。

 frame[0]这个字节是NAL Header ,第一个字节0x18(0001 1000),即10进制24。

Type为24,表示:STAP-A(单一时间组合包模式 A,用于一个 RTP 包荷载多个 NALU)。

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\

十三、H264RtpDecoder::unpackStapA-- H264Rtp.cpp

 这个函数执行的是一个拆包行为,将SPS(序列参数集)和PPS(图像参数集)分开。 
  1. SPS,前两个字节0x0, 0x15,即十进制21.
  2. PPs,前两个字节0x0, 0x4,即十进制4.
拆好以后将H264RtpDecoder::singleFrame函数处理。

十三-1、H264RtpDecoder::mergeFu-- H264Rtp.cpp

Type为28时,将多个rtp包合为一帧。

b H264Rtp.cpp:111

1.第一帧时:

prt[0]     7c  0111 1100   type 11100 28

nal_suffix = *ptr & (~0x1F) 0110 0000

fu—>prt[1]  85  1000 0101  type 00101 5 表I帧

enum {

        NAL_IDR = 5,

        NAL_SEI = 6,

        NAL_SPS = 7,

        NAL_PPS = 8,

        NAL_AUD = 9,

        NAL_B_P = 1,

};

合为一帧时,前面加4个字节,\x00\x00\x00\x01

后面一个字节为NALU 头,nal_suffix | fu->nal_type,即0110 0000| 0000 0101 à0110 0101 à0x65

2.不为第一帧是,将前面的FU Indicator和FU Header去掉,直接加入后面。

然后执行到十五。

十四、H264RtpDecoder:: singleFrame-- H264Rtp.cpp

  1. 对每帧加上00 00 00 01的帧头。

      2.对pts进行赋值。PTS是真正录制和播放的时间戳.

十五、H264RtpDecoder::outputFrame-- H264Rtp.cpp

对dts进行了赋值,将每帧数据交编码器处理。

  _dts_generator.getDts(frame->_pts, frame->_dts);

十六、FrameDispatcher : : inputFrame—Frame.h

对形成的帧派发给代理。

十七、H264Track::inputFrame--H264.cpp

主要对sps和pps帧进一步处理。对其它帧交由代理处理。

十八、MediaSink::addTrack-- MediaSink.cpp

track->addDelegate,如果不满足条件对帧进行存储,满足条件则由onTrackFrame继续处理。

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

十九、MultiMediaSourceMuxer::onTrackFrame-- MultiMediaSourceMuxer.cpp

这里是一个重要的节点,对发出来的数据双进行封装,将由MultiMediaSourceMuxer::inputFrame进行处理(这里先对RTSP进行说明)。

二十、RtspMuxer::inputFrame-- RtspMuxer.cpp

通过TrackType得到编码器,进一步处理。

二十一、H264RtpEncoder::inputFrame-- H264Rtp.cpp

b  /opt/ZLMediaKit/src/Extension/H264Rtp.cpp:290

取出sps、pps帧,及最后一帧。

二十二、 H264RtpEncoder::inputFrame_l-- H264Rtp.cpp

对每帧进一步处理,保证每一个关键帧前都有SPS与PPS。并调用packRtp进行Rtp打包。

二十三、H264RtpEncoder::packRtp-- H264Rtp.cpp

按type的类型分类处理。type为24,即STAP-A模式;type为28,即FU-A模式。

b  /opt/ZLMediaKit/src/Extension/H264Rtp.cpp:223

getMaxSize为1388。下面按type为24先行说明。

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

二十四、H264RtpEncoder::packRtpStapA-- H264Rtp.cpp

  1. 调用makeRtp生成RTP包。这个包包括4个字节的rtsp over tcp 头,12个字节的rtp头。
  2. Payload前加三个字节,第一个字节为类型,第二、三个字节为长度。

payload[0] = (ptr[0] & (~0x1F)) | 24;

NRI变为11,表示非常重要。

b  /opt/ZLMediaKit/src/Extension/H264Rtp.cpp:279

 

二十四-1、H264RtpEncoder::packRtpFu---- H264Rtp.cpp

 

b  H264Rtp.cpp:234

 

把每一帧分成多个rtp包。每个rtp包的长度为:1386

 

二十五、RtpRing::inputRtp-- RtpCodec.h

Rtp包写入到RingType中。

二十六、RingBuffer::write-- RingBuffer.h

调用_delegate->onWrite(std::move(in), is_key);

二十七、RtspMediaSource::onWrite-- RtspMediaSource.h

b  /opt/ZLMediaKit/src/Rtsp/RtspMediaSource.h:161

对track和缓冲组更新,并通知数据变化。调用将数据插入缓冲区函数。

二十八、PacketCache::inputPacket--MediaSource.h

将RTP包追加到RTP LIST后面。

二十九、PacketCache::onFlush--MediaSource.h

更新RTP LIST。

posted @ 2022-09-30 15:19  泽良_小涛  阅读(588)  评论(0编辑  收藏  举报