手机网站制作 尺寸,教你用模板做网站,网站推广服务算中介吗,新手如何找cps推广渠道zlmediakit的优势就是支持多种媒体容器和媒体协议。我从推流和拉流的两个角度#xff0c;梳理出了转流的核心骨架。
推流
协议和容器格式的转换#xff0c;最基本的内核就是音视频数据的扭转。对视频而言就是#xff0c;解封装帧数据#xff0c;组帧#xff0c;封装帧。…zlmediakit的优势就是支持多种媒体容器和媒体协议。我从推流和拉流的两个角度梳理出了转流的核心骨架。
推流
协议和容器格式的转换最基本的内核就是音视频数据的扭转。对视频而言就是解封装帧数据组帧封装帧。对音频而言简单些只有解封装封装。如下是rtsp中的视频转换为rtmp,mp4,webrtc的简单示意图。
源端是rtsp的推流目的端是各种协议的拉流。
最开始的是rtsp信令协商。信令协议协商成功后通过rtp传输媒体数据。从rtp包中解出视频nalu数据。组成完整的nalu数据再根据具体的目的协议或容器进行封装。目标协议也是媒体的协商在媒体协商完成后由拉流端主动发起转流。
下面是以rtsp推流中的整个流程为例子画了一个视频的流转图(音频也类似)。 当一个rtsp推流端推流后媒体流会经过解封装组帧再经过封装成不同协议放到对应的ringbuffer中。流程图中可以很明显的看到整个过程。对推到ZLMediaKit的流都会固定的产生FMP4MediaSource(有宏控制)RtmpMediaSourceRtspMediaSourceTSMediaSourceMP4Recorder(mp4存储按需产生)HlsRecorder(Hls存储按需产生)RingBuffer未经过封装的裸帧数据。
这些对象都会注册到全局的MediaSource容器中就是s_media_source_map下面是它的定义
using StreamMap unordered_mapstring/*strema_id*/, weak_ptrMediaSource ;
using AppStreamMap unordered_mapstring/*app*/, StreamMap;
using VhostAppStreamMap unordered_mapstring/*vhost*/, AppStreamMap;
using SchemaVhostAppStreamMap unordered_mapstring/*schema*/, VhostAppStreamMap;
static SchemaVhostAppStreamMap s_media_source_map;就是多个unorder_map的套娃记录了流的信息和对应的MediaSource对象。当有需要该流时会根据流信息在容器中找对应的MediaSource。
每路推流(不同的stream id)都会这样的流程产生几个对应协议的MediaSource对象。所以在媒体层面不管该流是否有被消费(拉流)媒体层面的rtsp,rtmp,fmp4,ts数据都已准备好。那么在消息(拉流)时只需要媒体信令完成就可以直接发流了。
拉流
上面了解了推流的处理流程那么拉流的流程就比较好理解了如下图
以rtmp协议拉流rtmp的信令协商处理最终会放到RtmpSession中处理。在协商完成后会在s_media_source_map找到MediaSource。再通过MediaSoruce取到RingBuffer对象。通过调用RingBuffer对象的attch方法打通转流。
下面是rtmp拉流与源端对接的代码位于RtmpSession::sendPlayResponse中。
_ring_reader src-getRing()-attach(getPoller());weak_ptrRtmpSession weak_self static_pointer_castRtmpSession(shared_from_this());_ring_reader-setGetInfoCB([weak_self]() {Any ret;ret.set(static_pointer_castSockInfo(weak_self.lock()));return ret;});_ring_reader-setReadCB([weak_self](const RtmpMediaSource::RingDataType pkt) {auto strong_self weak_self.lock();if (!strong_self) {return;}size_t i 0;auto size pkt-size();strong_self-setSendFlushFlag(false);pkt-for_each([](const RtmpPacket::Ptr rtmp){if(i size){strong_self-setSendFlushFlag(true);}strong_self-onSendMedia(rtmp);});});通过RingBuffer的attach方法将RtmpSession对象关联到源buffer中再将数据发送出去。
这就是ZLMediaKit转流的骨架当然整个流程涉及到很多皮毛比如媒体格式的匹配时间戳的转换同步等。掌握了骨架在解读细节就不会困难了。