ZLMediaKit源码分析(四)重封装

ZLMediaKit源码分析(一)服务启动
ZLMediaKit源码分析(二)推流创建
ZLMediaKit源码分析(三)拉流创建
ZLMediaKit源码分析(四)重封装

重封装流程图

ZLMediaKit重封装流程图

编码结构体创建

src/Rtsp/RtspSession.cpp
        // RtspMediaSourceImp::Ptr RtspSession::_push_src;
		if (!_push_src) {
    
    
            // RtspMediaSourceImp构造函数中 构造RtspMediaSource(vhost, app, id, ringSize)
            // 然后又构造MediaSource(RTSP_SCHEMA, vhost, app, stream_id) 
            //  初始化 _vhost = vhost.empty() ? DEFAULT_VHOST : vhost;  _schema = schema; _app = app; _stream_id = stream_id;
            //  在数据到来之际 会调用 MediaSource::regist() 追加四维map s_media_source_map
            //  auto &ref = s_media_source_map[_schema][_vhost][_app][_stream_id];
            _push_src = std::make_shared<RtspMediaSourceImp>(_media_info._vhost, _media_info._app, _media_info._streamid);
            //获取所有权
            _push_src_ownership = _push_src->getOwnership();
            _push_src->setProtocolOption(option);
            _push_src->setSdp(parser.Content());
        }
        _push_src->setListener(dynamic_pointer_cast<MediaSourceEvent>(shared_from_this()));

RtspMediaSourceImp::RtspMediaSourceImp()

src/Rtsp/RtspMediaSourceImp.cpp
RtspMediaSourceImp::RtspMediaSourceImp(const std::string &vhost, const std::string &app, const std::string &id, int ringSize) 
    : RtspMediaSource(vhost, app, id, ringSize)
{
    
    
	// MultiMediaSourceMuxer::Ptr _muxer
	// RtspDemuxer::Ptr _demuxer
    _demuxer = std::make_shared<RtspDemuxer>();
    // this 即位RtspMediaSourceImp,后面会使用到
    _demuxer->setTrackListener(this);
}

构造RtspMediaSource和MediaSource

ZLMediaKit直接代理模式,使用该结构体。重封装模式,该结构体无用。

src/Rtsp/RtspMediaSource.h
    RtspMediaSource(const std::string &vhost,
                    const std::string &app,
                    const std::string &stream_id,
                    int ring_size = RTP_GOP_SIZE) :
            MediaSource(RTSP_SCHEMA, vhost, app, stream_id), _ring_size(ring_size) {
    
    }

RtspDemuxer::RtspDemuxer ()

src/Rtsp/RtspDemuxer.h
class RtspDemuxer : public Demuxer {
    
    
public:
using Ptr = std::shared_ptr<RtspDemuxer>;
	// 空构造
    RtspDemuxer() = default;
    virtual ~RtspDemuxer() = default;

    /**
     * 加载sdp
     */
    void loadSdp(const std::string &sdp);

    /**
     * 开始解复用
     * @param rtp rtp包
     * @return true 代表是i帧第一个rtp包
     */
    bool inputRtp(const RtpPacket::Ptr &rtp);

    /**
     * 获取节目总时长
     * @return 节目总时长,单位秒
     */
    float getDuration() const;

private:
    void makeAudioTrack(const SdpTrack::Ptr &audio);
    void makeVideoTrack(const SdpTrack::Ptr &video);
    void loadSdp(const SdpParser &parser);

private:
    float _duration = 0;
    AudioTrack::Ptr _audio_track;
    VideoTrack::Ptr _video_track;
    RtpCodec::Ptr _audio_rtp_decoder;
    RtpCodec::Ptr _video_rtp_decoder;
};
src/Common/MediaSink.cpp
void Demuxer::setTrackListener(TrackListener *listener, bool wait_track_ready) {
    
    
    if (wait_track_ready) {
    
    
        auto sink = std::make_shared<MediaSinkDelegate>();
        sink->setTrackListener(listener);
        _sink = std::move(sink);
    }
    _listener = listener;
}

RtspMediaSourceImp::getOwnership()

暂不分析。

RtspMediaSourceImp::setProtocolOption()

这部分主要初始化总封装和子封装。子封装父类会创建缓冲区。
RtspMediaSourceImp继承自RtspMediaSource继承自MediaSource。

src/Rtsp/RtspMediaSourceImp.cpp
void RtspMediaSourceImp::setProtocolOption(const ProtocolOption &option)
{
    
    
    GET_CONFIG(bool, direct_proxy, Rtsp::kDirectProxy);
    //开启直接代理模式时,rtsp直接代理,不重复产生;但是有些rtsp推流端,由于sdp中已有sps pps,rtp中就不再包括sps pps,
    //导致rtc无法播放,所以在rtsp推流rtc播放时,建议关闭直接代理模式
    _option = option;
	_option.enable_rtsp = !direct_proxy;
	// MultiMediaSourceMuxer::Ptr _muxer
	// RtspDemuxer::Ptr _demuxer
    _muxer = std::make_shared<MultiMediaSourceMuxer>(getVhost(), getApp(), getId(), _demuxer->getDuration(), _option);
    _muxer->setMediaListener(getListener());
    _muxer->setTrackListener(std::static_pointer_cast<RtspMediaSourceImp>(shared_from_this()));
    //让_muxer对象拦截一部分事件(比如说录像相关事件)
    MediaSource::setListener(_muxer);

	// 获取解封装的Tracks
	// 此时track为0。应该在RtspMediaSourceImp::setSdp()中
    for (auto &track : _demuxer->getTracks(false)) {
    
    
        _muxer->addTrack(track);
        // vector<Track::Ptr> 继承自 FrameDispatcher
        track->addDelegate(_muxer);
    }
}

MultiMediaSourceMuxer::MultiMediaSourceMuxer()

头文件定义:

src/Common/MultiMediaSourceMuxer.h
class MultiMediaSourceMuxer : public MediaSourceEventInterceptor, public MediaSink, public std::enable_shared_from_this<MultiMediaSourceMuxer>{
    
    
public:
    using Ptr = std::shared_ptr<MultiMediaSourceMuxer>;

    class Listener {
    
    
    public:
        Listener() = default;
        virtual ~Listener() = default;
        virtual void onAllTrackReady() = 0;
    };

    MultiMediaSourceMuxer(const std::string &vhost, const std::string &app, const std::string &stream, float dur_sec = 0.0,const ProtocolOption &option = ProtocolOption());
    ~MultiMediaSourceMuxer() override = default;
	......
protected:
    /MediaSink override/
   /**
    * 某track已经准备好,其ready()状态返回true,
    * 此时代表可以获取其例如sps pps等相关信息了
    * @param track
    */
    bool onTrackReady(const Track::Ptr & track) override;
	......

private:
    .......
#if defined(ENABLE_MP4)
    FMP4MediaSourceMuxer::Ptr _fmp4;
#endif
    RtmpMediaSourceMuxer::Ptr _rtmp;
    RtspMediaSourceMuxer::Ptr _rtsp;
    TSMediaSourceMuxer::Ptr _ts;
    MediaSinkInterface::Ptr _mp4;
    HlsRecorder::Ptr _hls;
    toolkit::EventPoller::Ptr _poller;

    //对象个数统计
    toolkit::ObjectStatistic<MultiMediaSourceMuxer> _statistic;
};

初始化多类型子封装。

src/Common/MultiMediaSourceMuxer.cpp
MultiMediaSourceMuxer::MultiMediaSourceMuxer(const string &vhost, const string &app, const string &stream, float dur_sec, const ProtocolOption &option) {
    
    
    _poller = EventPollerPool::Instance().getPoller();
    _create_in_poller = _poller->isCurrentThread();
    _vhost = vhost;
    _app = app;
    _stream_id = stream;
    _option = option;
    
    // 如果配置文件开启了 rtmp
    if (option.enable_rtmp) {
    
    
        _rtmp = std::make_shared<RtmpMediaSourceMuxer>(vhost, app, stream, option, std::make_shared<TitleMeta>(dur_sec));
    }
    if (option.enable_rtsp) {
    
    
        _rtsp = std::make_shared<RtspMediaSourceMuxer>(vhost, app, stream, option, std::make_shared<TitleSdp>(dur_sec));
    }
    if (option.enable_hls) {
    
    
        _hls = dynamic_pointer_cast<HlsRecorder>(Recorder::createRecorder(Recorder::type_hls, vhost, app, stream, option));
    }
    if (option.enable_mp4) {
    
    
        _mp4 = Recorder::createRecorder(Recorder::type_mp4, vhost, app, stream, option);
    }
    if (option.enable_ts) {
    
    
        _ts = std::make_shared<TSMediaSourceMuxer>(vhost, app, stream, option);
    }
#if defined(ENABLE_MP4)
    if (option.enable_fmp4) {
    
    
        _fmp4 = std::make_shared<FMP4MediaSourceMuxer>(vhost, app, stream, option);
    }
#endif

    // 音频相关设置
    enableAudio(option.enable_audio);
    enableMuteAudio(option.add_mute_audio);
}

RtspMediaSourceMuxer::RtspMediaSourceMuxer()

初始化Rtsp子封装。
主要操作有两点:

src/Rtsp/RtspMediaSourceMuxer.h
class RtspMediaSourceMuxer final : public RtspMuxer, public MediaSourceEventInterceptor,
public std::enable_shared_from_this<RtspMediaSourceMuxer> {
    
    
public:
    using Ptr = std::shared_ptr<RtspMediaSourceMuxer>;

    RtspMediaSourceMuxer(const std::string &vhost,
                         const std::string &strApp,
                         const std::string &strId,
                         const ProtocolOption &option,
            const TitleSdp::Ptr &title = nullptr) : RtspMuxer(title) {
    
    
        _option = option;
        // RtspMediaSource::Ptr _media_src;
        // 包含下行分发,这是重封装的最终输出。
        _media_src = std::make_shared<RtspMediaSource>(vhost,strApp,strId);
        // getRtpRing() 继承自父类RtspMuxer
        // 父类包含两个Ring Buffer,_rtpRing,_rtpInterceptor(rtp环形缓冲区)
        getRtpRing()->setDelegate(_media_src);
    }

    ~RtspMediaSourceMuxer() override {
    
     RtspMuxer::flush(); }

    void setListener(const std::weak_ptr<MediaSourceEvent> &listener){
    
    
        setDelegate(listener);
        _media_src->setListener(shared_from_this());
    }
	......
	// 子封装的输入函数
    bool inputFrame(const Frame::Ptr &frame) override {
    
    
        if (_clear_cache && _option.rtsp_demand) {
    
    
            _clear_cache = false;
            _media_src->clearCache();
        }
        if (_enabled || !_option.rtsp_demand) {
    
    
            return RtspMuxer::inputFrame(frame);
        }
        return false;
    }
	......
private:
    bool _enabled = true;
    bool _clear_cache = false;
    ProtocolOption _option;
    RtspMediaSource::Ptr _media_src;
};

父类初始化RtspMuxer::RtspMuxer()

src/Rtsp/RtspMuxer.h
class RtspMuxer : public MediaSinkInterface {
    
    
public:
    using Ptr = std::shared_ptr<RtspMuxer>;
    ......
    RtpRing::RingType::Ptr getRtpRing() const;
    bool addTrack(const Track::Ptr & track) override;
	......

private:
	void onRtp(RtpPacket::Ptr in, bool is_key);

private:
    bool _live = true;
    uint32_t _rtp_stamp[TrackMax]{
    
    0};
    uint64_t _ntp_stamp[TrackMax]{
    
    0};
    uint64_t _ntp_stamp_start;
    std::string _sdp;
    Stamp _stamp[TrackMax];
    RtpCodec::Ptr _encoder[TrackMax];
    RtpRing::RingType::Ptr _rtpRing;
    RtpRing::RingType::Ptr _rtpInterceptor;
};

初始化两个重要的缓冲区。总封装输出会调用_rtpInterceptor,_rtpInterceptor的代理为_rtpRing,_rtpRing的代理为_media_src,传递输出数据。

src/Rtsp/RtspMuxer.cpp
RtspMuxer::RtspMuxer(const TitleSdp::Ptr &title) {
    
    
    if (!title) {
    
    
        _sdp = std::make_shared<TitleSdp>()->getSdp();
    } else {
    
    
        _live = title->getDuration() == 0;
        _sdp = title->getSdp();
	}
	// RtpRing::RingType::Ptr _rtpRing;
	// using RingType = toolkit::RingBuffer<RtpPacket::Ptr>;
	// 这个直接就是ringbuffer
	_rtpRing = std::make_shared<RtpRing::RingType>();
	// RtpRing::RingType::Ptr _rtpInterceptor;
	// using RingType = toolkit::RingBuffer<RtpPacket::Ptr>;
    _rtpInterceptor = std::make_shared<RtpRing::RingType>();
    _rtpInterceptor->setDelegate(std::make_shared<RingDelegateHelper>([this](RtpPacket::Ptr in, bool is_key) {
    
    
        onRtp(std::move(in), is_key);
    }));
    _ntp_stamp_start = getCurrentMillisecond(true);
}

RtmpMediaSourceMuxer::RtmpMediaSourceMuxer()

略…

扫描二维码关注公众号,回复: 15434200 查看本文章

MultiMediaSourceMuxer::setMediaListener()

src/Common/MultiMediaSourceMuxer.cpp
void MultiMediaSourceMuxer::setMediaListener(const std::weak_ptr<MediaSourceEvent> &listener) {
    
    
    setDelegate(listener);

    auto self = shared_from_this();
    //拦截事件
    if (_rtmp) {
    
    
        _rtmp->setListener(self);
    }
    if (_rtsp) {
    
    
        _rtsp->setListener(self);
    }
    if (_ts) {
    
    
        _ts->setListener(self);
    }
#if defined(ENABLE_MP4)
    if (_fmp4) {
    
    
        _fmp4->setListener(self);
    }
#endif
    auto hls = _hls;
    if (hls) {
    
    
        hls->setListener(self);
    }
}

MultiMediaSourceMuxer::setTrackListener()

略…

Demuxer::getTracks() 未执行

略…

MultiMediaSourceMuxer::addTrack() 未执行

略…

FrameDispatcher::addDelegate() 未执行

略…

RtspMediaSourceImp::setSdp()创建track

父类函数是虚函数。virtual void RtspMediaSource::setSdp(const std::string &sdp);

src/Rtsp/RtspMediaSourceImp.cpp
void RtspMediaSourceImp::setSdp(const std::string &strSdp)
{
    
    
    if (!getSdp().empty()) {
    
    
        return;
	}
	// RtspDemuxer::Ptr _demuxer
	_demuxer->loadSdp(strSdp);
	// 调用父类的函数 虚函数
    RtspMediaSource::setSdp(strSdp);
}

RtspDemuxer::loadSdp()

创建音视频demuxerAVTrack,解码器代理为demuxerAVTrack。demuxerAVTrack代理为总分装。

src/Rtsp/RtspDemuxer.cpp
void RtspDemuxer::loadSdp(const SdpParser &attr) {
    
    
    auto tracks = attr.getAvailableTrack();
    for (auto &track : tracks) {
    
    
        switch (track->_type) {
    
    
            case TrackVideo: {
    
    
                 // 这里会调用 Demuxer::addTrack()
                makeVideoTrack(track);
            }
                break;
            case TrackAudio: {
    
    
                makeAudioTrack(track);
            }
                break;
            default:
                break;
        }
    }
    //rtsp能通过sdp立即知道有多少个track
    addTrackCompleted();

    auto titleTrack = attr.getTrack(TrackTitle);
    if (titleTrack) {
    
    
        _duration = titleTrack->_duration;
    }
}

获取所有可用AVTrack。

src/Rtsp/Rtsp.cpp
vector<SdpTrack::Ptr> SdpParser::getAvailableTrack() const {
    
    
    vector<SdpTrack::Ptr> ret;
    bool audio_added = false;
    bool video_added = false;
    for (auto &track : _track_vec) {
    
    
        if (track->_type == TrackAudio) {
    
    
            if (!audio_added) {
    
    
                ret.emplace_back(track);
                audio_added = true;
            }
            continue;
        }
        // 这个地方产生 VideoTrack
        if (track->_type == TrackVideo) {
    
    
            if (!video_added) {
    
    
                ret.emplace_back(track);
                video_added = true;
            }
            continue;
        }
    }
    return ret;
}

音频暂不分析。

src/Rtsp/RtspDemuxer.h
class RtspDemuxer : public Demuxer {
    
    
public:
    using Ptr = std::shared_ptr<RtspDemuxer>;
    RtspDemuxer() = default;
    virtual ~RtspDemuxer() = default;
    void loadSdp(const std::string &sdp);
    bool inputRtp(const RtpPacket::Ptr &rtp);
    float getDuration() const;

private:
    void makeAudioTrack(const SdpTrack::Ptr &audio);
    void makeVideoTrack(const SdpTrack::Ptr &video);
    void loadSdp(const SdpParser &parser);

private:
    float _duration = 0;
    AudioTrack::Ptr _audio_track;
    VideoTrack::Ptr _video_track;
    RtpCodec::Ptr _audio_rtp_decoder;
    RtpCodec::Ptr _video_rtp_decoder;
};

创建demuxerVideoTrack,创建解码器_video_rtp_decoder,设置解码器代理为demuxerVideoTrack。

src/Rtsp/RtspDemuxer.cpp
void RtspDemuxer::makeVideoTrack(const SdpTrack::Ptr &video) {
    
    
    if (_video_rtp_decoder) {
    
    
        return;
    }
	//生成Track对象 即demuxerVideoTrack
	// VideoTrack::Ptr _video_track;
	// H264Track继承自VideoTrack继承自Track继承自CodecInfo和FrameDispatcher继承自FrameWriterInterface。
	_video_track = dynamic_pointer_cast<VideoTrack>(Factory::getTrackBySdp(video));
    if (!_video_track) {
    
    
        return;
    }
    setBitRate(video, _video_track);
	//生成RtpCodec对象以便解码rtp
	// RtpCodec::Ptr _video_rtp_decoder;
	//(H264RtpEncoder继承自)H264RtpDecoder继承自RtpCodec。
    _video_rtp_decoder = Factory::getRtpDecoderByTrack(_video_track);
    if (!_video_rtp_decoder) {
    
    
        //找不到相应的rtp解码器,该track无效
        _video_track.reset();
        return;
    }
	//设置rtp解码器代理,生成的frame写入该Track
	// VideoTrack::Ptr _video_track;
	// H264Track继承自VideoTrack继承自Track继承自CodecInfo和FrameDispatcher继承自FrameWriterInterface。
	// RtpCodec::Ptr _video_rtp_decoder;
	//(H264RtpEncoder继承自)H264RtpDecoder继承自RtpCodec继承自FrameDispatcher继承自FrameWriterInterface。
	// FrameWriterInterface* addDelegate(FrameWriterInterface::Ptr delegate)
    _video_rtp_decoder->addDelegate(_video_track);
    // 解封装添加AVTrack
    addTrack(_video_track);
}

获取解码videoTrack

H264Track继承自VideoTrack继承自Track继承自CodecInfo和FrameDispatcher继承自FrameWriterInterface。

src/Extension/Factory.cpp
Track::Ptr Factory::getTrackBySdp(const SdpTrack::Ptr &track) {
    
    
    auto codec = getCodecId(track->_codec);
    if (codec == CodecInvalid) {
    
    
        //根据传统的payload type 获取编码类型以及采样率等信息
        codec = RtpPayload::getCodecId(track->_pt);
    }
    switch (codec) {
    
    
        case CodecG711A:
        case CodecG711U: return std::make_shared<G711Track>(codec, track->_samplerate, track->_channel, 16);
        case CodecL16:  return std::make_shared<L16Track>(track->_samplerate, track->_channel);
        case CodecOpus : return std::make_shared<OpusTrack>();
        case CodecAAC : {
    
     ...... }
        case CodecH264 : {
    
    
            //a=fmtp:96 packetization-mode=1;profile-level-id=42C01F;sprop-parameter-sets=Z0LAH9oBQBboQAAAAwBAAAAPI8YMqA==,aM48gA==
            auto map = Parser::parseArgs(track->_fmtp, ";", "=");
            auto sps_pps = map["sprop-parameter-sets"];
            string base64_SPS = FindField(sps_pps.data(), NULL, ",");
            string base64_PPS = FindField(sps_pps.data(), ",", NULL);
            auto sps = decodeBase64(base64_SPS);
            auto pps = decodeBase64(base64_PPS);
            if (sps.empty() || pps.empty()) {
    
    
                //如果sdp里面没有sps/pps,那么可能在后续的rtp里面恢复出sps/pps
                return std::make_shared<H264Track>();
            }
            return std::make_shared<H264Track>(sps, pps, 0, 0);
        }
        case CodecH265: {
    
     ...... }
        case CodecJPEG : {
    
    
            return std::make_shared<JPEGTrack>();
        }
        default: {
    
    
            //其他codec不支持
            WarnL << "暂不支持该rtsp编码类型:" << track->getName();
            return nullptr;
        }
    }
}

获取解码器

(H264RtpEncoder继承自)H264RtpDecoder继承自RtpCodec。

src/Extension/Factory.cpp
RtpCodec::Ptr Factory::getRtpDecoderByTrack(const Track::Ptr &track) {
    
    
    switch (track->getCodecId()){
    
    
        case CodecH264 : return std::make_shared<H264RtpDecoder>();
        case CodecH265 : return std::make_shared<H265RtpDecoder>();
        case CodecAAC : return std::make_shared<AACRtpDecoder>(track->clone());
        case CodecL16 :
        case CodecOpus :
        case CodecG711A :
        case CodecG711U : return std::make_shared<CommonRtpDecoder>(track->getCodecId());
        case CodecJPEG: return std::make_shared<JPEGRtpDecoder>();
        default : 
			WarnL << "暂不支持该CodecId:" << track->getCodecName(); return nullptr;
    }
}

FrameDispatcher::addDelegate() 解码器代理 demuxerVideoTrack

RtpCodec继承自FrameDispatcher继承自FrameWriterInterface。
VideoTrack继承自Track继承自FrameDispatcher继承自FrameWriterInterface。

src/Extension/Frame.h
class FrameDispatcher : public FrameWriterInterface {
    
    
public:
    using Ptr = std::shared_ptr<FrameDispatcher>;
    FrameDispatcher() = default;
    ~FrameDispatcher() override = default;

    /**
     * 添加代理
     */
	// 执行
	// _video_rtp_decoder->addDelegate(_video_track);
    FrameWriterInterface* addDelegate(FrameWriterInterface::Ptr delegate) {
    
    
        std::lock_guard<std::recursive_mutex> lck(_mtx);
        return _delegates.emplace(delegate.get(), std::move(delegate)).first->second.get();
	}

	// 未执行
    FrameWriterInterface* addDelegate(std::function<bool(const Frame::Ptr &frame)> cb);
	......

private:
	......
    std::map<void *, FrameWriterInterface::Ptr> _delegates;
};

Demuxer::addTrack() 解封装添加demuxerVideoTrack

参考1:

src/Rtsp/RtspMediaSourceImp.cpp
class RtspDemuxer;
class RtspMediaSourceImp final : public RtspMediaSource, private TrackListener, public MultiMediaSourceMuxer::Listener  {
    
    
public:
    using Ptr = std::shared_ptr<RtspMediaSourceImp>;
    ......
private:
    bool _all_track_ready = false;
    ProtocolOption _option;
    RtspDemuxer::Ptr _demuxer;
    MultiMediaSourceMuxer::Ptr _muxer;
};

参考2:

src/Rtsp/RtspMediaSourceImp.cpp
RtspMediaSourceImp::RtspMediaSourceImp(const std::string &vhost, const std::string &app, const std::string &id, int ringSize) 
    : RtspMediaSource(vhost, app, id, ringSize)
{
    
    
	// MultiMediaSourceMuxer::Ptr _muxer
	// RtspDemuxer::Ptr _demuxer
	_demuxer = std::make_shared<RtspDemuxer>();
	// 该函数设置_listener
	// this实际为RtspMediaSourceImp
    _demuxer->setTrackListener(this);
}

_listener->addTrack(track),其实就是RtspMediaSourceImp::addTrack()。

src/Common/MediaSink.cpp
bool Demuxer::addTrack(const Track::Ptr &track) {
    
    
	if (!_sink) {
    
    
        // run
        // track实际为: VideoTrack::Ptr _video_track;
        _origin_track.emplace_back(track);
        // TrackListener *_listener = nullptr;
        // _demuxer->setTrackListener(this); 
		// this实际为RtspMediaSourceImp,参考解封装初始化。
        return _listener ? _listener->addTrack(track) : false;
    }

    // not run
    if (_sink->addTrack(track)) {
    
    
        track->addDelegate([this](const Frame::Ptr &frame) {
    
    
            return _sink->inputFrame(frame);
        });
        return true;
    }
    return false;
}

RtspMediaSourceImp::addTrack() 上行中专demuxerVideoTrack

总封装添加cloneVideoTrack,并将demuxerVideoTrack的代理设置为总封装。总封装接到demuxerVideoTrack的数据之后,通过cloneVideoTrack进行数据分发。

src/Rtsp/RtspMediaSourceImp.h
class RtspMediaSourceImp final : public RtspMediaSource, private TrackListener, public MultiMediaSourceMuxer::Listener  {
    
    
public:
    using Ptr = std::shared_ptr<RtspMediaSourceImp>;
    ......
    /**
     * _demuxer触发的添加Track事件
     */
	// 上行Rtsp推流添加videoTrack
	// track实际为: VideoTrack::Ptr _video_track;即demuxerVideoTrack
	bool addTrack(const Track::Ptr &track) override {
    
    
         // MultiMediaSourceMuxer::Ptr _muxer;
         // 总封装
        if (_muxer) {
    
    
         	// MultiMediaSourceMuxer继承自MediaSink.
         	// 实际调用MediaSink::addTrack()
            if (_muxer->addTrack(track)) {
    
    
                 // track实际为: VideoTrack::Ptr _video_track;
                 // MultiMediaSourceMuxer::Ptr _muxer;
                 // MultiMediaSourceMuxer继承自MediaSink继承自MediaSinkInterface继承自FrameWriterInterface;
                track->addDelegate(_muxer);
                return true;
            }
        }
        return false;
    }
    ......
private:
    bool _all_track_ready = false;
    ProtocolOption _option;
    RtspDemuxer::Ptr _demuxer;
    MultiMediaSourceMuxer::Ptr _muxer;
};

MediaSink::addTrack() 为总封装添加cloneVideoTrack和回调

MultiMediaSourceMuxer继承自MediaSink。

  1. 总封装克隆demuxerVideoTrack,相当于创建cloneVideoTrack。
  2. 注册_track_ready_callback回调,数据到来时,创建子封装videoTrack。
  3. cloneVideoTrack注册分发代理,分发数据给子封装。
    创建子封装Track和总封装分发数据给子封装,都在数据输入部分,下面会分析。
src/Common/MediaSingk.cpp
bool MediaSink::addTrack(const Track::Ptr &track_in) {
    
    
    if (_only_audio && track_in->getTrackType() != TrackAudio) {
    
    
        InfoL << "Only audio enabled, track ignored: " << track_in->getCodecName();
        return false;
    }
    if (!_enable_audio) {
    
    
        // 关闭音频时,加快单视频流注册速度
        if (track_in->getTrackType() == TrackAudio) {
    
    
            // 音频被全局忽略
            InfoL << "Audio disabled, audio track ignored";
            return false;
        }
    }
    if (_all_track_ready) {
    
    
        WarnL << "All track is ready, add track too late: " << track_in->getCodecName();
        return false;
    }
	//克隆Track,只拷贝其数据,不拷贝其数据转发关系
	// 1. 总封装克隆demuxerVideoTrack,相当于创建了一个cloneVideoTrack。
	// track_in实际为: VideoTrack::Ptr RtspDemuxer::_video_track;
	auto track = track_in->clone();
    auto track_type = track->getTrackType();
    // 管理cloneTrack。创建子封装Track和分发数据都需要。
	_track_map[track_type] = std::make_pair(track, false);
	// 2. 注册_track_ready_callback回调,数据到来时,创建子封装videoTrack。
	_track_ready_callback[track_type] = [this, track]() {
    
    
        // 创建子封装videoTrack
        onTrackReady(track);
    };
    _ticker.resetTime();

	// 3. cloneVideoTrack注册分发代理,分发数据给子封装
	// FrameWriterInterface* addDelegate(std::function<bool(const Frame::Ptr &frame)> cb);
	// RtpCodec继承自FrameDispatcher继承自FrameWriterInterface。
	// VideoTrack继承自Track继承自FrameDispatcher继承自FrameWriterInterface。
    track->addDelegate([this](const Frame::Ptr &frame) {
    
    
        if (_all_track_ready) {
    
    
            return onTrackFrame(frame);
        }
        auto &frame_unread = _frame_unread[frame->getTrackType()];

        GET_CONFIG(uint32_t, kMaxUnreadyFrame, General::kUnreadyFrameCache);
        if (frame_unread.size() > kMaxUnreadyFrame) {
    
    
            //未就绪的的track,不能缓存太多的帧,否则可能内存溢出
            frame_unread.clear();
            WarnL << "Cached frame of unready track(" << frame->getCodecName() << ") is too much, now cleared";
        }
        //还有Track未就绪,先缓存之
        frame_unread.emplace_back(Frame::getCacheAbleFrame(frame));
        return true;
    });
    return true;
}

FrameDispatcher::addDelegate() demuxerVideoTrack添加代理总封装

RtpCodec继承自FrameDispatcher继承自FrameWriterInterface。
VideoTrack继承自Track继承自FrameDispatcher继承自FrameWriterInterface。
MultiMediaSourceMuxer继承自MediaSink继承自MediaSinkInterface继承自FrameWriterInterface;

src/Extension/Frame.h
class FrameDispatcher : public FrameWriterInterface {
    
    
public:
    using Ptr = std::shared_ptr<FrameDispatcher>;
    FrameDispatcher() = default;
    ~FrameDispatcher() override = default;

    /**
     * 添加代理
     */
	// 已执行
	// _video_rtp_decoder->addDelegate(_video_track);
	// 执行
	// track->addDelegate(_muxer);
    FrameWriterInterface* addDelegate(FrameWriterInterface::Ptr delegate) {
    
    
        std::lock_guard<std::recursive_mutex> lck(_mtx);
        return _delegates.emplace(delegate.get(), std::move(delegate)).first->second.get();
	}

	// 已执行
    FrameWriterInterface* addDelegate(std::function<bool(const Frame::Ptr &frame)> cb);
	......
private:
    ......
    std::map<void *, FrameWriterInterface::Ptr> _delegates;
};

RtspMediaSource::setSdp()

虚函数。virtual void RtspMediaSource::setSdp(const std::string &sdp);

src/Rtsp/RtspMediaSourceImp.cpp
void RtspMediaSource::setSdp(const std::string &sdp) {
    
    
SdpParser sdp_parser(sdp);
	// SdpTrack::Ptr _tracks[TrackMax];
    _tracks[TrackVideo] = sdp_parser.getTrack(TrackVideo);
    _tracks[TrackAudio] = sdp_parser.getTrack(TrackAudio);
    _have_video = (bool)_tracks[TrackVideo];
	_sdp = sdp_parser.toString();

	// not run
    if (_ring) {
    
    
        regist();
    }
}

RtspMediaSourceImp::setListener()

src/Rtsp/RtspMediaSourceImp.h
class RtspDemuxer;
class RtspMediaSourceImp final : public RtspMediaSource, private TrackListener, public MultiMediaSourceMuxer::Listener  {
    
    
public:
    using Ptr = std::shared_ptr<RtspMediaSourceImp>;
    。。。。。
    /**
     * 设置事件监听器
     * @param listener 监听器
     */
	void setListener(const std::weak_ptr<MediaSourceEvent> &listener) override{
    
    
        // MultiMediaSourceMuxer::Ptr _muxer;
        if (_muxer) {
    
    
            // run
			// 在函数RtspMediaSourceImp::setProtocolOption()中初始化
        	// MultiMediaSourceMuxer::Ptr _muxer
        	// _muxer = std::make_shared<MultiMediaSourceMuxer>();
        	//_muxer对象不能处理的事件再给listener处理
            _muxer->setMediaListener(listener);
        } else {
    
    
            //未创建_muxer对象,事件全部给listener处理
            MediaSource::setListener(listener);
        }
	}
private:
    bool _all_track_ready = false;
    ProtocolOption _option;
    RtspDemuxer::Ptr _demuxer;
    MultiMediaSourceMuxer::Ptr _muxer;
}

MultiMediaSourceMuxer::setMediaListener()

void MultiMediaSourceMuxer::setMediaListener(const std::weak_ptr<MediaSourceEvent> &listener) {
    
    
    setDelegate(listener);

    auto self = shared_from_this();
    //拦截事件
    if (_rtmp) {
    
    
        _rtmp->setListener(self);
    }
    if (_rtsp) {
    
    
        _rtsp->setListener(self);
    }
    if (_ts) {
    
    
        _ts->setListener(self);
    }
#if defined(ENABLE_MP4)
    if (_fmp4) {
    
    
        _fmp4->setListener(self);
    }
#endif
    auto hls = _hls;
    if (hls) {
    
    
        hls->setListener(self);
    }
}

数据输入与解码

RtspSession::onRtpSorted() 数据输入。

src/Rtsp/RtspSession.h
using BufferRtp = toolkit::BufferOffset<toolkit::Buffer::Ptr>;
class RtspSession : public toolkit::Session, public RtspSplitter, public RtpReceiver, public MediaSourceEvent {
    
    
public:
    ......
    RtpReceiver override
    void onRtpSorted(RtpPacket::Ptr rtp, int track_idx) override;
    void onBeforeRtpSorted(const RtpPacket::Ptr &rtp, int track_index) override;
    ......

    //rtsp推流相关绑定的源
    RtspMediaSourceImp::Ptr _push_src;
    ......
};
src/Rtsp/RtspSession.cpp
void RtspSession::onRtpSorted(RtpPacket::Ptr rtp, int track_idx) {
    
    
    if (_push_src) {
    
    
        // run 
        // 接收推流数据
        //RtspMediaSourceImp::Ptr _push_src;
        //RtspMediaSourceImp::onWrite [RtspMediaSourceImp.cpp]
        _push_src->onWrite(std::move(rtp), false);
    } else {
    
    
        WarnL << "Not a rtsp push!";
    }
}

上行输出函数。和RtspMediaSource::onWrite()再同一个文件。

src/Rtsp/RtspMediaSourceImp.cpp
void RtspMediaSourceImp::onWrite(RtpPacket::Ptr rtp, bool key_pos)
{
    
    
if (_all_track_ready && !_muxer->isEnabled()) {
    
    
        //获取到所有Track后,并且未开启转协议,那么不需要解复用rtp
        //在关闭rtp解复用后,无法知道是否为关键帧,这样会导致无法秒开,或者开播花屏
        key_pos = rtp->type == TrackVideo;
    } else {
    
    
        //需要解复用rtp
        // RtspDemuxer::inputRtp()
        key_pos = _demuxer->inputRtp(rtp);
    }
    GET_CONFIG(bool, directProxy, Rtsp::kDirectProxy);
	if (directProxy) {
    
    
        //直接代理模式才直接使用原始rtp
        RtspMediaSource::onWrite(std::move(rtp), key_pos);
    }
}

解封装调用解码输入。

src/Rtsp/RtspDemuxer.cpp
bool RtspDemuxer::inputRtp(const RtpPacket::Ptr &rtp) {
    
    
    switch (rtp->type) {
    
    
        case TrackVideo: {
    
    
             // RtpCodec::Ptr _video_rtp_decoder;
             //(H264RtpEncoder继承自)H264RtpDecoder继承自RtpCodec。
            if (_video_rtp_decoder) {
    
    
                return _video_rtp_decoder->inputRtp(rtp, true);
            }
            return false;
        }
        case TrackAudio: {
    
    
            if (_audio_rtp_decoder) {
    
    
                _audio_rtp_decoder->inputRtp(rtp, false);
                return false;
            }
            return false;
        }
        default: return false;
    }
}

解码部分省略…
H264RtpDecoder::outputFrame() 解码输出。

src/Extension/H264Rtp.cpp
void H264RtpDecoder::outputFrame(const RtpPacket::Ptr &rtp, const H264Frame::Ptr &frame) {
    
    
    if (frame->dropAble()) {
    
    
        //不参与dts生成
        frame->_dts = frame->_pts;
    } else {
    
    
        //rtsp没有dts,那么根据pts排序算法生成dts
        _dts_generator.getDts(frame->_pts, frame->_dts);
    }

    if (frame->keyFrame() && _gop_dropped) {
    
    
        _gop_dropped = false;
        InfoL << "new gop received, rtp:\r\n" << rtp->dumpString();
    }
	if (!_gop_dropped) {
    
    
        // 实际调用FrameDispatcher::inputFrame()
        // H264RtpDecoder 继承自RtpCodec继承自RtpRing 和FrameDispatcher继承自FrameWriterInterface。
        RtpCodec::inputFrame(frame);
    }
    _frame = obtainFrame();
}

FrameDispatcher::inputFrame() 调用demuxerVideoTrack输入H264Track::inputFrame()。

class FrameDispatcher : public FrameWriterInterface {
    
    
public:
    using Ptr = std::shared_ptr<FrameDispatcher>;
    FrameDispatcher() = default;
    ~FrameDispatcher() override = default;

    /**
     * 添加代理
     */
	// 执行
	// _video_rtp_decoder->addDelegate(_video_track);
	// addDelegate()调用在RtspMediaSourceImp::setSdp()->RtspDemuxer::loadSdp()->RtspDemuxer::makeVideoTrack()->FrameDispatcher::addDelegate().
    FrameWriterInterface* addDelegate(FrameWriterInterface::Ptr delegate) {
    
    
        std::lock_guard<std::recursive_mutex> lck(_mtx);
        return _delegates.emplace(delegate.get(), std::move(delegate)).first->second.get();
    }

    // 未执行
    FrameWriterInterface* addDelegate(std::function<bool(const Frame::Ptr &frame)> cb);

    /**
     * 写入帧并派发
     */
	// 执行代理输入
	// 此时FrameDispatcher代表解码器H264RtpDecoder,其代理为demuxerVideoTrack
	// delegates由addDelegate(FrameWriterInterface::Ptr delegate)添加
    bool inputFrame(const Frame::Ptr &frame) override {
    
    
        std::lock_guard<std::recursive_mutex> lck(_mtx);
        doStatistics(frame);
        bool ret = false;
        for (auto &pr : _delegates) {
    
    
         	// 实际执行H264Track::inputFrame()
         	// 参考RtspDemuxer::makeVideoTrack()
            if (pr.second->inputFrame(frame)) {
    
    
                ret = true;
            }
        }
        return ret;
}
	......
private:
	......
    std::map<void *, FrameWriterInterface::Ptr> _delegates;
};

demuxerVideoTrack数据输入

H264RtpDecoder 继承自RtpCodec继承自RtpRing 和FrameDispatcher继承自FrameWriterInterface。
H264Track::inputFrame() 解码videoTrack输入。

src/Externsion/H264.cpp
bool H264Track::inputFrame(const Frame::Ptr &frame) {
    
    
    using H264FrameInternal = FrameInternal<H264FrameNoCacheAble>;
    int type = H264_TYPE(frame->data()[frame->prefixSize()]);
   
    if ((type == H264Frame::NAL_B_P || type == H264Frame::NAL_IDR) && ready()) {
    
    
        return inputFrame_l(frame);
    }

    //非I/B/P帧情况下,split一下,防止多个帧粘合在一起
    bool ret = false;
    splitH264(frame->data(), frame->size(), frame->prefixSize(), [&](const char *ptr, size_t len, size_t prefix) {
    
    
        H264FrameInternal::Ptr sub_frame = std::make_shared<H264FrameInternal>(frame, (char *)ptr, len, prefix);
        if (inputFrame_l(sub_frame)) {
    
    
            ret = true;
        }
    });
    return ret;
}
src/Externsion/H264.cpp
bool H264Track::inputFrame_l(const Frame::Ptr &frame) {
    
    
    int type = H264_TYPE(frame->data()[frame->prefixSize()]);
    bool ret = true;
    switch (type) {
    
    
        case H264Frame::NAL_SPS: {
    
    
            _sps = string(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize());
            _latest_is_config_frame = true;
            ret = VideoTrack::inputFrame(frame);
            break;
        }
        case H264Frame::NAL_PPS: {
    
    
            _pps = string(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize());
            _latest_is_config_frame = true;
            ret = VideoTrack::inputFrame(frame);
            break;
        }
        default:
            // 避免识别不出关键帧
            if (_latest_is_config_frame && !frame->dropAble()) {
    
    
                if (!frame->keyFrame()) {
    
    
                    const_cast<Frame::Ptr &>(frame) = std::make_shared<FrameCacheAble>(frame, true);
                }
            }
            // 判断是否是I帧, 并且如果是,那判断前面是否插入过config帧, 如果插入过就不插入了
            if (frame->keyFrame() && !_latest_is_config_frame) {
    
    
                insertConfigFrame(frame);
            }
            if(!frame->dropAble()){
    
    
                _latest_is_config_frame = false;
            }
             // H264Track继承自VideoTrack
             // track->addDelegate(_muxer);
             // 实际执行FrameDispatcher::inputFrame()
            ret = VideoTrack::inputFrame(frame);
            break;
    }

    if (_width == 0 && ready()) {
    
    
        onReady();
    }
    return ret;
}

总封装输入

FrameDispatcher::inputFrame() demuxerVideoTrack代理总封装输入。
MultiMediaSourceMuxer继承自MediaSink继承自MediaSinkInterface继承自FrameWriterInterface。
参考,设置demuxerVideoTrack代理为总分装:

src/Rtsp/RtspMediaSourceImp.h
class RtspMediaSourceImp final : public RtspMediaSource, private TrackListener, public MultiMediaSourceMuxer::Listener  {
    
    
public:
    using Ptr = std::shared_ptr<RtspMediaSourceImp>;
    ......
    /**
     * _demuxer触发的添加Track事件
     */
	// Rtsp推流结构体
	// track实际为: VideoTrack::Ptr _video_track;
	bool addTrack(const Track::Ptr &track) override {
    
    
        // Rtsp推流结构体封装(MultiMediaSourceMuxer::Ptr _muxer)
        if (_muxer) {
    
    
            if (_muxer->addTrack(track)) {
    
    
                // track实际为: VideoTrack::Ptr _video_track;
                // MultiMediaSourceMuxer::Ptr _muxer;
                // MultiMediaSourceMuxer继承自MediaSink继承自MediaSinkInterface继承自FrameWriterInterface;
                track->addDelegate(_muxer);
                return true;
            }
        }
        return false;
    }
    ......
private:
    bool _all_track_ready = false;
    ProtocolOption _option;
    RtspDemuxer::Ptr _demuxer;
    MultiMediaSourceMuxer::Ptr _muxer;
};

这个时候使用Track代理。
(H264Track继承自)VideoTrack继承自Track继承自CodecInfo和FrameDispatcher继承自FrameWriterInterface。

src/Extension/Frame.h
class FrameDispatcher : public FrameWriterInterface {
    
    
public:
    using Ptr = std::shared_ptr<FrameDispatcher>;
    FrameDispatcher() = default;
    ~FrameDispatcher() override = default;

    /**
     * 添加代理
     */
	// 已执行
	// addDelegate()调用在RtspMediaSourceImp::setSdp()->RtspDemuxer::loadSdp()->RtspDemuxer::makeVideoTrack()->FrameDispatcher::addDelegate().
	// 执行
	// addDelegate()调用在RtspMediaSourceImp::setSdp()->RtspMediaSourceImp::addTrack()->(track->addDelegate(_muxer)
    FrameWriterInterface* addDelegate(FrameWriterInterface::Ptr delegate) {
    
    
        std::lock_guard<std::recursive_mutex> lck(_mtx);
        return _delegates.emplace(delegate.get(), std::move(delegate)).first->second.get();
    }

    // 未执行
    FrameWriterInterface* addDelegate(std::function<bool(const Frame::Ptr &frame)> cb);

    /**
     * 写入帧并派发
     */
	// 此时执行MediaSink::inputFrame(frame);
	// MultiMediaSourceMuxer继承自MediaSink
    bool inputFrame(const Frame::Ptr &frame) override {
    
    
        std::lock_guard<std::recursive_mutex> lck(_mtx);
        doStatistics(frame);
        bool ret = false;
        for (auto &pr : _delegates) {
    
    
         	// 此时不执行H264Track::inputFrame()
         	// 此时执行MediaSink::inputFrame()
			// MultiMediaSourceMuxer继承自MediaSink继承自MediaSinkInterface继承自FrameWriterInterface。
            if (pr.second->inputFrame(frame)) {
    
    
                ret = true;
            }
        }
        return ret;
	}
	......
private:
    ......
    std::map<void *, FrameWriterInterface::Ptr> _delegates;
};

MediaSink::inputFrame() multiMuxer输入.

编码和数据输出

MultiMediaSourceMuxer继承自MediaSink继承自MediaSinkInterface继承自FrameWriterInterface。

src/Common/MediaSink.cpp
bool MediaSink::inputFrame(const Frame::Ptr &frame) {
    
    
    auto it = _track_map.find(frame->getTrackType());
    if (it == _track_map.end()) {
    
    
        return false;
    }
	//got frame
	// it->second==std::make_pair(track, false);
	it->second.second = true;
	// track实际为: VideoTrack::Ptr _video_track;
	//track->inputFrame()
	// 2. 实际执行FrameDispatcher::inputFrame()
    auto ret = it->second.first->inputFrame(frame);
    if (_mute_audio_maker && frame->getTrackType() == TrackVideo) {
    
    
        //视频驱动产生静音音频
        _mute_audio_maker->inputFrame(frame);
	}

	// 1. 创建Track,首次执行
    checkTrackIfReady();
    return ret;
}

参考:
MultiMediaSourceMuxer继承自MediaSink。

src/Common/MediaSingk.cpp
bool MediaSink::addTrack(const Track::Ptr &track_in) {
    
    
    if (_only_audio && track_in->getTrackType() != TrackAudio) {
    
    
        InfoL << "Only audio enabled, track ignored: " << track_in->getCodecName();
        return false;
    }
    if (!_enable_audio) {
    
    
        // 关闭音频时,加快单视频流注册速度
        if (track_in->getTrackType() == TrackAudio) {
    
    
            // 音频被全局忽略
            InfoL << "Audio disabled, audio track ignored";
            return false;
        }
    }
    if (_all_track_ready) {
    
    
        WarnL << "All track is ready, add track too late: " << track_in->getCodecName();
        return false;
    }
	//克隆Track,只拷贝其数据,不拷贝其数据转发关系
	// 1. 总封装克隆demuxerVideoTrack,相当于创建了一个cloneVideoTrack。
	// track_in实际为: VideoTrack::Ptr RtspDemuxer::_video_track;
	auto track = track_in->clone();
    auto track_type = track->getTrackType();
	_track_map[track_type] = std::make_pair(track, false);
	// 2. 注册_track_ready_callback回调,数据到来时,创建子封装videoTrack。
	_track_ready_callback[track_type] = [this, track]() {
    
    
        // 创建子封装videoTrack
        onTrackReady(track);
    };
    _ticker.resetTime();

	// 3. cloneVideoTrack注册分发代理,分发数据给子封装
	// FrameWriterInterface* addDelegate(std::function<bool(const Frame::Ptr &frame)> cb);
	// RtpCodec继承自FrameDispatcher继承自FrameWriterInterface。
	// VideoTrack继承自Track继承自FrameDispatcher继承自FrameWriterInterface。
    track->addDelegate([this](const Frame::Ptr &frame) {
    
    
        if (_all_track_ready) {
    
    
            return onTrackFrame(frame);
        }
        auto &frame_unread = _frame_unread[frame->getTrackType()];

        GET_CONFIG(uint32_t, kMaxUnreadyFrame, General::kUnreadyFrameCache);
        if (frame_unread.size() > kMaxUnreadyFrame) {
    
    
            //未就绪的的track,不能缓存太多的帧,否则可能内存溢出
            frame_unread.clear();
            WarnL << "Cached frame of unready track(" << frame->getCodecName() << ") is too much, now cleared";
        }
        //还有Track未就绪,先缓存之
        frame_unread.emplace_back(Frame::getCacheAbleFrame(frame));
        return true;
    });
    return true;
}

MediaSink::checkTrackIfReady()创建子封装

触发MultiMediaSourceMuxer::onTrackReady()创建track。

src/Common/MediaSink.cpp
void MediaSink::checkTrackIfReady(){
    
    
	// bool _all_track_ready = false;
    // std::unordered_map<int, std::function<void()> > _track_ready_callback;
	if (!_all_track_ready && !_track_ready_callback.empty()) {
    
    
    	// _track_map[track_type] = std::make_pair(track, false);
        // pr.second.second =true 在MediaSink::inputFrame()
        for (auto &pr : _track_map) {
    
    
            if (pr.second.second && pr.second.first->ready()) {
    
    
                //Track由未就绪状态转换成就绪状态,我们就触发onTrackReady回调
                // pr.first=track_type
                // find执行回调,触发onTrackReady()
                auto it = _track_ready_callback.find(pr.first);
                if (it != _track_ready_callback.end()) {
    
    
                    it->second();
                    _track_ready_callback.erase(it);
                }
            }
        }
    }

    if(!_all_track_ready){
    
    
        GET_CONFIG(uint32_t, kMaxWaitReadyMS, General::kWaitTrackReadyMS);
        if(_ticker.elapsedTime() > kMaxWaitReadyMS){
    
    
            //如果超过规定时间,那么不再等待并忽略未准备好的Track
            emitAllTrackReady();
            return;
        }

        if(!_track_ready_callback.empty()){
    
    
            //在超时时间内,如果存在未准备好的Track,那么继续等待
            return;
        }

        if(_track_map.size() == _max_track_size){
    
    
            //如果已经添加了音视频Track,并且不存在未准备好的Track,那么说明所有Track都准备好了
            emitAllTrackReady();
            return;
        }

        GET_CONFIG(uint32_t, kMaxAddTrackMS, General::kWaitAddTrackMS);
        if(_track_map.size() == 1 && _ticker.elapsedTime() > kMaxAddTrackMS){
    
    
            //如果只有一个Track,那么在该Track添加后,我们最多还等待若干时间(可能后面还会添加Track)
            emitAllTrackReady();
            return;
        }
    }
}

子封装添加Track和编码器

MultiMediaSourceMuxer继承自MediaSink。
参数track只用于获取trackid,区分音视频。

src/Common/MultiMediaSourceMuxer.cpp
bool MultiMediaSourceMuxer::onTrackReady(const Track::Ptr &track) {
    
    

	bool ret = false;
	// RtmpMediaSourceMuxer::Ptr _rtmp;
    if (_rtmp) {
    
    
        ret = _rtmp->addTrack(track) ? true : ret;
	}

	// RtspMediaSourceMuxer::Ptr _rtsp;
    if (_rtsp) {
    
    
        ret = _rtsp->addTrack(track) ? true : ret;
    }
    if (_ts) {
    
    
        ret = _ts->addTrack(track) ? true : ret;
    }
#if defined(ENABLE_MP4)
    if (_fmp4) {
    
    
        ret = _fmp4->addTrack(track) ? true : ret;
    }
#endif

    //拷贝智能指针,目的是为了防止跨线程调用设置录像相关api导致的线程竞争问题
    auto hls = _hls;
    if (hls) {
    
    
        ret = hls->addTrack(track) ? true : ret;
    }
    auto mp4 = _mp4;
    if (mp4) {
    
    
        ret = mp4->addTrack(track) ? true : ret;
    }
    return ret;
}

子封装添加编码器,并为编码器设置输出环形缓冲区。

src/Rtsp/RtspMuxer.cpp
bool RtspMuxer::addTrack(const Track::Ptr &track) {
    
    
    //根据track生成sdp
    Sdp::Ptr sdp = track->getSdp();
    if (!sdp) {
    
    
        return false;
	}

	// RtpCodec::Ptr _encoder[TrackMax];
	// H264RtpEncoder继承自H264RtpDecoder继承自RtpCodec。
	auto &encoder = _encoder[track->getTrackType()];
	// 返回RtpCodec::Ptr
    encoder = Factory::getRtpEncoderBySdp(sdp);
    if (!encoder) {
    
    
        return false;
	}
	// RtpCodec继承自RtpRing。
    //设置rtp输出环形缓存
    encoder->setRtpRing(_rtpInterceptor);

    //添加其sdp
    _sdp.append(sdp->getSdp());
    trySyncTrack();
    return true;
}

参考:

src/Rtsp/RtspMuxer.cpp
RtspMuxer::RtspMuxer(const TitleSdp::Ptr &title) {
    
    
	......
	// RtpRing::RingType::Ptr _rtpRing;
	// using RingType = toolkit::RingBuffer<RtpPacket::Ptr>;
	_rtpRing = std::make_shared<RtpRing::RingType>();
	// RtpRing::RingType::Ptr _rtpInterceptor;
	// using RingType = toolkit::RingBuffer<RtpPacket::Ptr>;
    _rtpInterceptor = std::make_shared<RtpRing::RingType>();
    _rtpInterceptor->setDelegate(std::make_shared<RingDelegateHelper>([this](RtpPacket::Ptr in, bool is_key) {
    
    
        onRtp(std::move(in), is_key);
    }));
    ......
}
src/Extension/Factory.cpp
RtpCodec::Ptr Factory::getRtpEncoderBySdp(const Sdp::Ptr &sdp) {
    
    
    // ssrc不冲突即可,可以为任意的32位整形
    static atomic<uint32_t> s_ssrc(0);
    uint32_t ssrc = s_ssrc++;
    if (!ssrc) {
    
    
        // ssrc不能为0
        ssrc = s_ssrc++;
    }
    if (sdp->getTrackType() == TrackVideo) {
    
    
        //视频的ssrc是偶数,方便调试
        ssrc = 2 * ssrc;
    } else {
    
    
        //音频ssrc是奇数
        ssrc = 2 * ssrc + 1;
    }
    return getRtpEncoderByCodecId(sdp->getCodecId(), sdp->getSampleRate(), sdp->getPayloadType(), ssrc);
}

H264RtpEncoder继承自H264RtpDecoder继承自RtpCodec。

src/Extension/Factory.cpp
RtpCodec::Ptr Factory::getRtpEncoderByCodecId(CodecId codec_id, uint32_t sample_rate, uint8_t pt, uint32_t ssrc) {
    
    
    GET_CONFIG(uint32_t, audio_mtu, Rtp::kAudioMtuSize);
    GET_CONFIG(uint32_t, video_mtu, Rtp::kVideoMtuSize);
    auto type = getTrackType(codec_id);
    auto mtu = type == TrackVideo ? video_mtu : audio_mtu;
    auto interleaved = type * 2;
    switch (codec_id) {
    
    
        case CodecH264: return std::make_shared<H264RtpEncoder>(ssrc, mtu, sample_rate, pt, interleaved);
        case CodecH265: return std::make_shared<H265RtpEncoder>(ssrc, mtu, sample_rate, pt, interleaved);
        case CodecAAC: return std::make_shared<AACRtpEncoder>(ssrc, mtu, sample_rate, pt, interleaved);
        case CodecL16:
        case CodecOpus: return std::make_shared<CommonRtpEncoder>(codec_id, ssrc, mtu, sample_rate, pt, interleaved);
        case CodecG711A:
        case CodecG711U: {
    
    
            if (pt == Rtsp::PT_PCMA || pt == Rtsp::PT_PCMU) {
    
    
                return std::make_shared<G711RtpEncoder>(codec_id, ssrc, mtu, sample_rate, pt, interleaved, 1);
            }
            return std::make_shared<CommonRtpEncoder>(codec_id, ssrc, mtu, sample_rate, pt, interleaved);
        }
        case CodecJPEG: return std::make_shared<JPEGRtpEncoder>(ssrc, mtu, sample_rate, pt, interleaved);
        default: WarnL << "暂不支持该CodecId:" << codec_id; return nullptr;
    }
}

cloneVideoTrack输入数据

MultiMediaSourceMuxer继承自MediaSink继承自MediaSinkInterface继承自FrameWriterInterface。
(H264Track继承自)VideoTrack继承自Track继承自CodecInfo和FrameDispatcher继承自FrameWriterInterface。

src/Extension/Frame.h
class FrameDispatcher : public FrameWriterInterface {
    
    
public:
    using Ptr = std::shared_ptr<FrameDispatcher>;
    FrameDispatcher() = default;
    ~FrameDispatcher() override = default;

    /**
     * 添加代理
     */
	// 不执行
	// addDelegate()调用在RtspMediaSourceImp::setSdp()->RtspDemuxer::loadSdp()->RtspDemuxer::makeVideoTrack()->FrameDispatcher::addDelegate().
	// 不执行
	// addDelegate()调用在RtspMediaSourceImp::setSdp()->RtspMediaSourceImp::addTrack()->(track->addDelegate(_muxer)
    FrameWriterInterface* addDelegate(FrameWriterInterface::Ptr delegate) {
    
    
        std::lock_guard<std::recursive_mutex> lck(_mtx);
        return _delegates.emplace(delegate.get(), std::move(delegate)).first->second.get();
    }

	// 执行
	// addDelegate()调用在RtspMediaSourceImp::setSdp()->RtspMediaSourceImp::addTrack()->MediaSink::addTrack()->(track->addDelegate([this](const Frame::Ptr &frame) {…}))
    FrameWriterInterface* addDelegate(std::function<bool(const Frame::Ptr &frame)> cb);
	.....
private:
    ......
    std::map<void *, FrameWriterInterface::Ptr> _delegates;
};
src/Extension/Frame.cpp
class FrameWriterInterfaceHelper : public FrameWriterInterface {
    
    
public:
    using Ptr = std::shared_ptr<FrameWriterInterfaceHelper>;
    using onWriteFrame = std::function<bool(const Frame::Ptr &frame)>;

    /**
     * inputFrame后触发onWriteFrame回调
     */
    FrameWriterInterfaceHelper(onWriteFrame cb) {
    
     _callback = std::move(cb); }

    virtual ~FrameWriterInterfaceHelper() = default;

    /**
     * 写入帧数据
     */
    // 最终调用MultiMediaSourceMuxer::onTrackFrame()
    bool inputFrame(const Frame::Ptr &frame) override {
    
     return _callback(frame); }

private:
    onWriteFrame _callback;
};

FrameWriterInterface* FrameDispatcher::addDelegate(std::function<bool(const Frame::Ptr &frame)> cb) {
    
    
    return addDelegate(std::make_shared<FrameWriterInterfaceHelper>(std::move(cb)));
}

MultiMediaSourceMuxer::onTrackFrame()分发数据

src/Common/MultiMediaSourceMuxer.cpp
bool MultiMediaSourceMuxer::onTrackFrame(const Frame::Ptr &frame_in) {
    
    
    auto frame = frame_in;
   	if (_option.modify_stamp) {
    
    
        //开启了时间戳覆盖
        frame = std::make_shared<FrameStamp>(frame, _stamp[frame->getTrackType()],true);
    }

    bool ret = false;
    if (_rtmp) {
    
    
        ret = _rtmp->inputFrame(frame) ? true : ret;
	}
	// RtspMediaSourceMuxer::Ptr _rtsp;
	// RtspMediaSourceMuxer继承自RtspMuxer。
	// 实际调用RtspMuxer::inputFrame()
    if (_rtsp) {
    
    
        ret = _rtsp->inputFrame(frame) ? true : ret;
    }
    if (_ts) {
    
    
        ret = _ts->inputFrame(frame) ? true : ret;
    }

    //拷贝智能指针,目的是为了防止跨线程调用设置录像相关api导致的线程竞争问题
    //此处使用智能指针拷贝来确保线程安全,比互斥锁性能更优
    auto hls = _hls;
    if (hls) {
    
    
        ret = hls->inputFrame(frame) ? true : ret;
    }
    auto mp4 = _mp4;
    if (mp4) {
    
    
        ret = mp4->inputFrame(frame) ? true : ret;
    }

#if defined(ENABLE_MP4)
    if (_fmp4) {
    
    
        ret = _fmp4->inputFrame(frame) ? true : ret;
    }
#endif

#if defined(ENABLE_RTPPROXY)
    for (auto &pr : _rtp_sender) {
    
    
        ret = pr.second->inputFrame(frame) ? true : ret;
    }
#endif //ENABLE_RTPPROXY
    return ret;
}

子封装数据输入。

src/Rtsp/RtspMediaSourceMuxer.h
class RtspMediaSourceMuxer final : public RtspMuxer, public MediaSourceEventInterceptor,
                                   public std::enable_shared_from_this<RtspMediaSourceMuxer> {
    
    
public:
    using Ptr = std::shared_ptr<RtspMediaSourceMuxer>;

    RtspMediaSourceMuxer(const std::string &vhost,
                         const std::string &strApp,
                         const std::string &strId,
                         const ProtocolOption &option,
                         const TitleSdp::Ptr &title = nullptr) : RtspMuxer(title) {
    
    
        _option = option;
        _media_src = std::make_shared<RtspMediaSource>(vhost,strApp,strId);
        getRtpRing()->setDelegate(_media_src);
    }
	......

    bool inputFrame(const Frame::Ptr &frame) override {
    
    
        if (_clear_cache && _option.rtsp_demand) {
    
    
            _clear_cache = false;
            _media_src->clearCache();
        }
        if (_enabled || !_option.rtsp_demand) {
    
    
            return RtspMuxer::inputFrame(frame);
        }
        return false;
    }
    ......
private:
    bool _enabled = true;
    bool _clear_cache = false;
    ProtocolOption _option;
    RtspMediaSource::Ptr _media_src;
};

子封装传递数据给编码器。

src/Rtsp/RtspMuxer.cpp
bool RtspMuxer::inputFrame(const Frame::Ptr &frame) {
    
    
auto &encoder = _encoder[frame->getTrackType()];
	// RtpCodec::Ptr RtspMuxer::_encoder[TrackMax];
    // encoder在RtspMediaSourceMuxer::addTrack()中创建。
	// 实际执行H264RtpEncoder::inputFrame().
    return encoder ? encoder->inputFrame(frame) : false;
}

编码器数据输入

src/Extension/H264Rtp.cpp
bool H264RtpEncoder::inputFrame(const Frame::Ptr &frame) {
    
    
    auto ptr = frame->data() + frame->prefixSize();
    switch (H264_TYPE(ptr[0])) {
    
    
        case H264Frame::NAL_SPS: {
    
    
            _sps = Frame::getCacheAbleFrame(frame);
            return true;
        }
        case H264Frame::NAL_PPS: {
    
    
            _pps = Frame::getCacheAbleFrame(frame);
            return true;
        }
        default: break;
    }

    GET_CONFIG(int,lowLatency,Rtp::kLowLatency);
    if (lowLatency) {
    
     // 低延迟模式
        if (_last_frame) {
    
    
            flush();
        }
        inputFrame_l(frame, true);
    } else {
    
    
        if (_last_frame) {
    
    
            //如果时间戳发生了变化,那么markbit才置true
            inputFrame_l(_last_frame, _last_frame->pts() != frame->pts());
        }
        _last_frame = Frame::getCacheAbleFrame(frame);
    }
    return true;
}

省略编码过程…

编码完数据写入环形缓冲区RtspMuxer::_rtpInterceptor。

src/Rtsp/RtpCodec.h
class RtpRing {
    
    
public:
    using Ptr = std::shared_ptr<RtpRing>;
    using RingType = toolkit::RingBuffer<RtpPacket::Ptr>;

    RtpRing() = default;
    virtual ~RtpRing() = default;

    virtual RingType::Ptr getRtpRing() const {
    
    
        return _ring;
    }

    virtual void setRtpRing(const RingType::Ptr &ring) {
    
    
        _ring = ring;
    }

	// RtpCodec继承自RtpRing。
	// return _video_rtp_decoder->inputRtp(rtp, true);
    virtual bool inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) {
    
    
        if (_ring) {
    
    
            // _ring实际为RtspMuxer::_rtpInterceptor = std::make_shared<RtpRing::RingType>();
         	// 实际调用RtpRing::RingBuffer::write()
            _ring->write(rtp, key_pos);
        }
        return key_pos;
    }

protected:
    RingType::Ptr _ring;
};

参考1:RtspMuxer获取_rtpInterceptor,并设置代理。

src/Rtsp/RtspMuxer.cpp
RtspMuxer::RtspMuxer(const TitleSdp::Ptr &title) {
    
    
	......
	// RtpRing::RingType::Ptr _rtpRing;
	// using RingType = toolkit::RingBuffer<RtpPacket::Ptr>;
	_rtpRing = std::make_shared<RtpRing::RingType>();
	// RtpRing::RingType::Ptr _rtpInterceptor;
	// using RingType = toolkit::RingBuffer<RtpPacket::Ptr>;
    _rtpInterceptor = std::make_shared<RtpRing::RingType>();
    _rtpInterceptor->setDelegate(std::make_shared<RingDelegateHelper>([this](RtpPacket::Ptr in, bool is_key) {
    
    
        onRtp(std::move(in), is_key);
    }));
    ......
}

参考2:RtspMuxer获取H264RtpEncoder,设置RtpRing:

src/Rtsp/RtspMuxer.cpp
bool RtspMuxer::addTrack(const Track::Ptr &track) {
    
    
    //根据track生成sdp
    Sdp::Ptr sdp = track->getSdp();
    if (!sdp) {
    
    
        return false;
	}

	// RtpCodec::Ptr _encoder[TrackMax];
	// H264RtpEncoder继承自H264RtpDecoder继承自RtpCodec
	auto &encoder = _encoder[track->getTrackType()];
	// 返回RtpCodec::Ptr
	// H264RtpEncoder继承自H264RtpDecoder继承自RtpCodec
    encoder = Factory::getRtpEncoderBySdp(sdp);
    if (!encoder) {
    
    
        return false;
	}
	// RtpCodec继承自RtpRing。
    //设置rtp输出环形缓存
    encoder->setRtpRing(_rtpInterceptor);

    //添加其sdp
    _sdp.append(sdp->getSdp());
    trySyncTrack();
    return true;
}

RtpRing::RingBuffer::write()代理数据

3rdpart/ZLToolKit/src/Util/RingBuffer.h
template <typename T>
class RingBuffer : public std::enable_shared_from_this<RingBuffer<T>> {
    
    
public:
    using Ptr = std::shared_ptr<RingBuffer>;
    using RingReader = _RingReader<T>;
    using RingStorage = _RingStorage<T>;
    using RingReaderDispatcher = _RingReaderDispatcher<T>;
    using onReaderChanged = std::function<void(int size)>;
    using onGetInfoCB = std::function<void(std::list<ReaderInfo> &info_list)>;
	......
	void write(T in, bool is_key = true) {
    
    
        // _delegate 实际为RingDelegateHelper
        // RingDelegateHelper继承自RingDelegate
        if (_delegate) {
    
    
            // 实际执行RingDelegateHelper::onWrite()
            _delegate->onWrite(std::move(in), is_key);
            return;
        }

        ......
    }

    void setDelegate(const typename RingDelegate<T>::Ptr &delegate) {
    
    
         _delegate = delegate; 
	}
    ......
private:
    std::mutex _mtx_map;
    std::atomic_int _total_count {
    
     0 };
    typename RingStorage::Ptr _storage;
    typename RingDelegate<T>::Ptr _delegate;
    onReaderChanged _on_reader_changed;
    std::unordered_map<EventPoller::Ptr, typename RingReaderDispatcher::Ptr, HashOfPtr> _dispatcher_map;
};

环形缓冲区写入数据给_rtpRing。

RingDelegateHelper::onWrite()
RingDelegateHelper继承自RingDelegate。

src/Rtsp/RtspMuxer.h
class RingDelegateHelper : public toolkit::RingDelegate<RtpPacket::Ptr> {
    
    
public:
    using onRtp = std::function<void(RtpPacket::Ptr in, bool is_key)> ;

    ~RingDelegateHelper() override = default;

    RingDelegateHelper(onRtp on_rtp) {
    
    
        _on_rtp = std::move(on_rtp);
    }

    void onWrite(RtpPacket::Ptr in, bool is_key) override {
    
    
        _on_rtp(std::move(in), is_key);
    }

private:
    onRtp _on_rtp;
};

参考:

src/Rtsp/RtspMuxer.cpp
RtspMuxer::RtspMuxer(const TitleSdp::Ptr &title) {
    
    
	......
	// RtpRing::RingType::Ptr _rtpRing;
	// using RingType = toolkit::RingBuffer<RtpPacket::Ptr>;
	_rtpRing = std::make_shared<RtpRing::RingType>();
	// RtpRing::RingType::Ptr _rtpInterceptor;
	// using RingType = toolkit::RingBuffer<RtpPacket::Ptr>;
    _rtpInterceptor = std::make_shared<RtpRing::RingType>();
    _rtpInterceptor->setDelegate(std::make_shared<RingDelegateHelper>([this](RtpPacket::Ptr in, bool is_key) {
    
    
        onRtp(std::move(in), is_key);
    }));
    _ntp_stamp_start = getCurrentMillisecond(true);
}

RtspMuxer::onRtp() 输出数据给_media_src

src/Rtsp/RtspMuxer.hcpp
void RtspMuxer::onRtp(RtpPacket::Ptr in, bool is_key) {
    
    
    if (_live) {
    
    
        if (_rtp_stamp[in->type] != in->getHeader()->stamp) {
    
    
            //rtp时间戳变化才计算ntp,节省cpu资源
            int64_t stamp_ms = in->getStamp() * uint64_t(1000) / in->sample_rate;
            int64_t stamp_ms_inc;
            //求rtp时间戳增量
            _stamp[in->type].revise(stamp_ms, stamp_ms, stamp_ms_inc, stamp_ms_inc);
            _rtp_stamp[in->type] = in->getHeader()->stamp;
            _ntp_stamp[in->type] = stamp_ms_inc + _ntp_stamp_start;
        }

        //rtp拦截入口,此处统一赋值ntp
        in->ntp_stamp = _ntp_stamp[in->type];
    } else {
    
    
        //点播情况下设置ntp时间戳为rtp时间戳加基准ntp时间戳
        in->ntp_stamp = _ntp_stamp_start + (in->getStamp() * uint64_t(1000) / in->sample_rate);
	}
	// RtpRing::RingType::Ptr _rtpRing;
    _rtpRing->write(std::move(in), is_key);
}

_rtpRing->write()。最后写入数据给子封装的成员RtspMediaSource::Ptr RtspMediaSourceMuxer::_media_src;
_media_src继承自PacketCache,实现数据分发输出,参考ZLMediaKit源码分析(二)推流创建

猜你喜欢

转载自blog.csdn.net/cliffordl/article/details/131208976
今日推荐