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()
略…
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。
- 总封装克隆demuxerVideoTrack,相当于创建cloneVideoTrack。
- 注册_track_ready_callback回调,数据到来时,创建子封装videoTrack。
- 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源码分析(二)推流创建。