在前面提到的转流流程还有一个细节:
这里以Rtmp推流端为例子。
在RtmpSession
中,有一个_push_src
的成员变量,它是RtmpMediaSourceImp
类型,作为一个Rtmp的源。
在RtmpMediaSourceImp
中有MultiMediaSourceMuxer
成员变量_muxer
,它是一个各种协议的muxer类,将视频帧按不同的协议进行拆包。可以看看这篇文章。
在文件RtmpMediaSourceImp.cpp
的setProtocolOption
方法中,创建对象_muxer
时,关闭了rtmp
的muxer。如下代码:
//关闭rtmp的muxer
_option.enable_rtmp = false;
//创建MultiMediaSourceMuxer对象
_muxer = std::make_shared<MultiMediaSourceMuxer>(_tuple, _demuxer->getDuration(), _option);
作为源的RtmpMediaSource
对象会注册到全局MediaSource
中(MediaSource可以看看这篇文章),作为rtmp的源。
**如果有rtmp的拉流端则会直接使用这个源,以RtmpMediaSource
的_ring
成员作为转流结构,而它类型定义如下:
using RingDataType = std::shared_ptr<toolkit::List<RtmpPacket::Ptr> >;
using RingType = toolkit::RingBuffer<RingDataType>;
可以看到这个RingBuffer
中的类型就是RtmpPacket
。可见是没有组帧(视频)的过程是直接转发。RTSP也是如此流程。
当转流需要MultiMediaSourceMuxer
中的suorce作为源时,此时就涉及到了组帧,拆包的过程了。这里的核心就是MultiMediaSourceMuxer
。下面是它的类图
视频帧的转发的被抽象为一个FrameDispathcer
类,它有一个std::map<void,FrameWriteInterface>
类型的成员变量,存放的就是Frame的消费者。
Frame通过inputFrame
方法,将Frame转发至各个FrameWriteInterface
类型的消费者中。MultiMediaSourceMuxer
就是FrameWriteInterface
类型。
在RtmpDemux
,RtspDemux
中,通过信令协商产生了对应的音视频的Track,视频对应的Track为H265Track
和H264Track
,它们都是具体的FrameDispathcer
类型,数据将由它们转发。下面Frame的牛转图。
在以Rtsp为源的情况下,RtspDemuxer::inputRtp
方法传入的是rtp包,经过H264RtpDecoder
后就将rtp包组成了视频帧。视频帧再通过FrameDispatcher
体系,最终到达MultiMediaSourceMuxer
中各个类型的source
,视频帧又被拆分为各协议对应的包。