diff --git a/src/Common/MediaSink.cpp b/src/Common/MediaSink.cpp index 4d74e2c9..c757b57c 100644 --- a/src/Common/MediaSink.cpp +++ b/src/Common/MediaSink.cpp @@ -111,21 +111,16 @@ void MediaSink::inputFrame(const Frame::Ptr &frame) { } } -bool MediaSink::isAllTrackReady() const { - return _allTrackReady; -} - -Track::Ptr MediaSink::getTrack(TrackType type,bool trackReady) const { +vector MediaSink::getTracks(bool trackReady) const{ + vector ret; lock_guard lck(_mtx); for (auto &pr : _track_map){ - if(pr.second->getTrackType() == type){ - if(!trackReady){ - return pr.second; - } - return pr.second->ready() ? pr.second : nullptr; + if(trackReady && !pr.second->ready()){ + continue; } + ret.emplace_back(pr.second); } - return nullptr; + return std::move(ret); } diff --git a/src/Common/MediaSink.h b/src/Common/MediaSink.h index 8798590d..d117aae5 100644 --- a/src/Common/MediaSink.h +++ b/src/Common/MediaSink.h @@ -38,11 +38,29 @@ using namespace toolkit; namespace mediakit{ +class MediaSinkInterface : public FrameWriterInterface { +public: + MediaSinkInterface(){}; + virtual ~MediaSinkInterface(){}; + + /** + * 添加track,内部会调用Track的clone方法 + * 只会克隆sps pps这些信息 ,而不会克隆Delegate相关关系 + * @param track + */ + virtual void addTrack(const Track::Ptr & track) = 0; + + /** + * 重置track + */ + virtual void resetTracks() = 0; +}; + /** * 该类的作用是等待Track ready()返回true也就是就绪后再通知派生类进行下一步的操作 * 目的是输入Frame前由Track截取处理下,以便获取有效的信息(譬如sps pps aa_cfg) */ -class MediaSink : public FrameWriterInterface , public std::enable_shared_from_this{ +class MediaSink : public MediaSinkInterface , public TrackSource , public std::enable_shared_from_this{ public: typedef std::shared_ptr Ptr; MediaSink(){} @@ -59,26 +77,18 @@ public: * 只会克隆sps pps这些信息 ,而不会克隆Delegate相关关系 * @param track */ - virtual void addTrack(const Track::Ptr & track); + void addTrack(const Track::Ptr & track) override; /** * 重置track */ - virtual void resetTracks(); + void resetTracks() override; /** - * 全部Track是否都准备好了 - * @return - */ - bool isAllTrackReady() const; - - /** - * 获取特定类型的Track - * @param type track类型 + * 获取所有Track * @param trackReady 是否获取已经准备好的Track - * @return */ - Track::Ptr getTrack(TrackType type,bool trackReady = true) const; + vector getTracks(bool trackReady = true) const override ; protected: /** * 某track已经准备好,其ready()状态返回true, diff --git a/src/Common/MediaSource.h b/src/Common/MediaSource.h index 5cfe597d..1e31b57b 100644 --- a/src/Common/MediaSource.h +++ b/src/Common/MediaSource.h @@ -92,7 +92,7 @@ public: string _param_strs; }; -class MediaSource: public enable_shared_from_this { +class MediaSource: public TrackSource, public enable_shared_from_this { public: typedef std::shared_ptr Ptr; typedef unordered_map > StreamMap; @@ -191,14 +191,6 @@ public: } virtual int readerCount() = 0; - - /** - * 获取track - * @return - */ - virtual vector getTracks(bool trackReady) const{ - return vector(0); - } protected: void regist() ; bool unregist() ; diff --git a/src/Common/MultiMediaSourceMuxer.h b/src/Common/MultiMediaSourceMuxer.h index b466ffec..4bf40c85 100644 --- a/src/Common/MultiMediaSourceMuxer.h +++ b/src/Common/MultiMediaSourceMuxer.h @@ -31,7 +31,7 @@ #include "Rtmp/RtmpMediaSourceMuxer.h" #include "MediaFile/MediaRecorder.h" -class MultiMediaSourceMuxer : public FrameWriterInterface{ +class MultiMediaSourceMuxer : public MediaSink{ public: typedef std::shared_ptr Ptr; @@ -54,25 +54,10 @@ public: } virtual ~MultiMediaSourceMuxer(){} - - /** - * 添加音视频媒体 - * @param track 媒体描述 - */ - void addTrack(const Track::Ptr & track) { - if(_rtmp){ - _rtmp->addTrack(track); - } - if(_rtsp){ - _rtsp->addTrack(track); - } - _record->addTrack(track); - } - /** * 重置音视频媒体 */ - void resetTracks() { + void resetTracks() override{ if(_rtmp){ _rtmp->resetTracks(); } @@ -82,20 +67,6 @@ public: _record->resetTracks(); } - /** - * 写入帧数据然后打包rtmp - * @param frame 帧数据 - */ - void inputFrame(const Frame::Ptr &frame) override { - if(_rtmp) { - _rtmp->inputFrame(frame); - } - if(_rtsp) { - _rtsp->inputFrame(frame); - } - _record->inputFrame(frame); - } - /** * 设置事件监听器 * @param listener @@ -122,6 +93,47 @@ public: _rtsp->setTimeStamp(stamp); } } + +protected: + /** + * 添加音视频媒体 + * @param track 媒体描述 + */ + void onTrackReady(const Track::Ptr & track) override { + if(_rtmp){ + _rtmp->addTrack(track); + } + if(_rtsp){ + _rtsp->addTrack(track); + } + _record->addTrack(track); + } + + /** + * 写入帧数据然后打包rtmp + * @param frame 帧数据 + */ + void onTrackFrame(const Frame::Ptr &frame) override { + if(_rtmp) { + _rtmp->inputFrame(frame); + } + if(_rtsp) { + _rtsp->inputFrame(frame); + } + _record->inputFrame(frame); + } + + /** + * 所有Track都准备就绪,触发媒体注册事件 + */ + void onAllTrackReady() override{ + if(_rtmp) { + _rtmp->onAllTrackReady(); + } + if(_rtsp) { + _rtsp->onAllTrackReady(); + } + } private: RtmpMediaSourceMuxer::Ptr _rtmp; RtspMediaSourceMuxer::Ptr _rtsp; diff --git a/src/Extension/Frame.h b/src/Extension/Frame.h index 79b5d02a..5e4234f7 100644 --- a/src/Extension/Frame.h +++ b/src/Extension/Frame.h @@ -50,7 +50,7 @@ typedef enum { TrackVideo = 0, TrackAudio, TrackTitle, - TrackMax = 0x7FFF + TrackMax = 3 } TrackType; /** diff --git a/src/Extension/Track.h b/src/Extension/Track.h index 5209c74e..b4771027 100644 --- a/src/Extension/Track.h +++ b/src/Extension/Track.h @@ -131,6 +131,37 @@ public: }; +class TrackSource{ +public: + TrackSource(){} + virtual ~TrackSource(){} + + /** + * 获取全部的Track + * @param trackReady 是否获取全部已经准备好的Track + * @return + */ + virtual vector getTracks(bool trackReady = true) const { + return vector(); + } + + /** + * 获取特定Track + * @param type track类型 + * @param trackReady 是否获取全部已经准备好的Track + * @return + */ + Track::Ptr getTrack(TrackType type , bool trackReady = true) const { + auto tracks = getTracks(trackReady); + for(auto &track : tracks){ + if(track->getTrackType() == type){ + return track; + } + } + return nullptr; + } +}; + }//namespace mediakit #endif //ZLMEDIAKIT_TRACK_H diff --git a/src/MediaFile/MP4Muxer.cpp b/src/MediaFile/MP4Muxer.cpp index c1b5bad3..70d6e38c 100644 --- a/src/MediaFile/MP4Muxer.cpp +++ b/src/MediaFile/MP4Muxer.cpp @@ -67,8 +67,12 @@ void MP4MuxerBase::init(int flags) { } /////////////////////////////////// +void MP4Muxer::resetTracks() { + _codec_to_trackid.clear(); + _started = false; +} -void MP4Muxer::onTrackFrame(const Frame::Ptr &frame) { +void MP4Muxer::inputFrame(const Frame::Ptr &frame) { if(frame->configFrame()){ //忽略配置帧 return; @@ -117,7 +121,7 @@ void MP4Muxer::onTrackFrame(const Frame::Ptr &frame) { with_nalu_size); } -void MP4Muxer::onTrackReady(const Track::Ptr &track) { +void MP4Muxer::addTrack(const Track::Ptr &track) { switch (track->getCodecId()) { case CodecAAC: { auto aac_track = dynamic_pointer_cast(track); @@ -210,7 +214,12 @@ void MP4Muxer::onTrackReady(const Track::Ptr &track) { } } -MP4MuxerFile::MP4MuxerFile(const char *file) { +MP4MuxerFile::MP4MuxerFile(const char *file){ + _file_name = file; + openFile(file); +} + +void MP4MuxerFile::openFile(const char *file) { //创建文件 auto fp = File::createfile_file(file,"wb+"); if(!fp){ @@ -237,7 +246,6 @@ MP4MuxerFile::MP4MuxerFile(const char *file) { }); GET_CONFIG(bool, mp4FastStart, Record::kFastStart); - init(mp4FastStart ? MOV_FLAG_FASTSTART : 0); } @@ -264,6 +272,12 @@ uint64_t MP4MuxerFile::onTell() { return ftell64(_file.get()); } + +void MP4MuxerFile::resetTracks(){ + MP4Muxer::resetTracks(); + openFile(_file_name.data()); +} + }//namespace mediakit #endif//#ifdef ENABLE_MP4RECORD diff --git a/src/MediaFile/MP4Muxer.h b/src/MediaFile/MP4Muxer.h index de15d4cc..1532d87e 100644 --- a/src/MediaFile/MP4Muxer.h +++ b/src/MediaFile/MP4Muxer.h @@ -57,23 +57,24 @@ protected: std::shared_ptr _mov_writter; }; -class MP4Muxer : public MediaSink , public MP4MuxerBase{ +class MP4Muxer : public MediaSinkInterface , public MP4MuxerBase{ public: MP4Muxer() = default; ~MP4Muxer() override = default; -protected: - /** - * 某track已经准备好,其ready()状态返回true, - * 此时代表可以获取其例如sps pps等相关信息了 - * @param track - */ - void onTrackReady(const Track::Ptr & track) override; /** - * 某Track输出frame,在onAllTrackReady触发后才会调用此方法 - * @param frame + * 添加已经ready状态的track */ - void onTrackFrame(const Frame::Ptr &frame) override; + void addTrack(const Track::Ptr & track) override; + /** + * 输入帧 + */ + void inputFrame(const Frame::Ptr &frame) override; + + /** + * 重置所有track + */ + void resetTracks() override ; private: struct track_info{ int track_id = -1; @@ -89,13 +90,16 @@ public: typedef std::shared_ptr Ptr; MP4MuxerFile(const char *file); ~MP4MuxerFile(); + void resetTracks() override ; protected: int onRead(void* data, uint64_t bytes) override; int onWrite(const void* data, uint64_t bytes) override; int onSeek( uint64_t offset) override; uint64_t onTell() override ; + void openFile(const char *file); private: std::shared_ptr _file; + string _file_name; }; }//namespace mediakit diff --git a/src/MediaFile/MP4Recorder.cpp b/src/MediaFile/MP4Recorder.cpp index 0f36561c..092258b4 100644 --- a/src/MediaFile/MP4Recorder.cpp +++ b/src/MediaFile/MP4Recorder.cpp @@ -128,7 +128,7 @@ void MP4Recorder::closeFile() { } } -void MP4Recorder::onTrackFrame(const Frame::Ptr &frame) { +void MP4Recorder::inputFrame(const Frame::Ptr &frame) { GET_CONFIG(uint32_t,recordSec,Record::kFileSecond); if(!_muxer || ((_createFileTicker.elapsedTime() > recordSec * 1000) && (!_haveVideo || (_haveVideo && frame->keyFrame()))) ){ @@ -145,7 +145,7 @@ void MP4Recorder::onTrackFrame(const Frame::Ptr &frame) { } } -void MP4Recorder::onTrackReady(const Track::Ptr & track){ +void MP4Recorder::addTrack(const Track::Ptr & track){ //保存所有的track,为创建MP4MuxerFile做准备 _tracks.emplace_back(track); if(track->getTrackType() == TrackVideo){ @@ -158,7 +158,6 @@ void MP4Recorder::resetTracks() { _tracks.clear(); _haveVideo = false; _createFileTicker.resetTime(); - MediaSink::resetTracks(); } } /* namespace mediakit */ diff --git a/src/MediaFile/MP4Recorder.h b/src/MediaFile/MP4Recorder.h index 0c619461..2d9e84e9 100644 --- a/src/MediaFile/MP4Recorder.h +++ b/src/MediaFile/MP4Recorder.h @@ -55,7 +55,7 @@ public: string strStreamId;//流ID string strVhost;//vhost }; -class MP4Recorder : public MediaSink{ +class MP4Recorder : public MediaSinkInterface{ public: typedef std::shared_ptr Ptr; MP4Recorder(const string &strPath, @@ -68,19 +68,16 @@ public: * 重置所有Track */ void resetTracks() override; -private: + /** - * 某Track输出frame,在onAllTrackReady触发后才会调用此方法 - * @param frame + * 输入frame */ - void onTrackFrame(const Frame::Ptr &frame) override ; + void inputFrame(const Frame::Ptr &frame) override; /** - * 某track已经准备好,其ready()状态返回true, - * 此时代表可以获取其例如sps pps等相关信息了 - * @param track + * 添加ready状态的track */ - void onTrackReady(const Track::Ptr & track) override; + void addTrack(const Track::Ptr & track) override; private: void createFile(); void closeFile(); diff --git a/src/MediaFile/MediaRecorder.h b/src/MediaFile/MediaRecorder.h index c36f8613..fbfba1e7 100644 --- a/src/MediaFile/MediaRecorder.h +++ b/src/MediaFile/MediaRecorder.h @@ -37,7 +37,7 @@ using namespace toolkit; namespace mediakit { -class MediaRecorder : public MediaSink{ +class MediaRecorder : public MediaSinkInterface{ public: typedef std::shared_ptr Ptr; MediaRecorder(const string &strVhost, diff --git a/src/MediaFile/TsMuxer.h b/src/MediaFile/TsMuxer.h index a876c8c3..3bd4509c 100644 --- a/src/MediaFile/TsMuxer.h +++ b/src/MediaFile/TsMuxer.h @@ -38,7 +38,7 @@ using namespace toolkit; namespace mediakit { -class TsMuxer : public MediaSink { +class TsMuxer : public MediaSinkInterface { public: TsMuxer(); virtual ~TsMuxer(); diff --git a/src/Player/PlayerBase.h b/src/Player/PlayerBase.h index 84fd6795..54aa0f3c 100644 --- a/src/Player/PlayerBase.h +++ b/src/Player/PlayerBase.h @@ -41,7 +41,7 @@ using namespace toolkit; namespace mediakit { -class DemuxerBase { +class DemuxerBase : public TrackSource{ public: typedef std::shared_ptr Ptr; @@ -57,29 +57,6 @@ public: * @return */ virtual bool isInited(int analysisMs) { return true; } - - /** - * 获取全部的Track - * @param trackReady 是否获取全部已经准备好的Track - * @return - */ - virtual vector getTracks(bool trackReady = true) const { return vector();} - - /** - * 获取特定Track - * @param type track类型 - * @param trackReady 是否获取全部已经准备好的Track - * @return - */ - virtual Track::Ptr getTrack(TrackType type , bool trackReady = true) const { - auto tracks = getTracks(trackReady); - for(auto &track : tracks){ - if(track->getTrackType() == type){ - return track; - } - } - return nullptr; - } }; @@ -274,14 +251,14 @@ public: bool isInited(int analysisMs) override; /** - * 获取所有可用Track,请在isInited()返回true时调用 - * @return + * 获取所有Track + * @return 所有Track */ vector getTracks(bool trackReady = true) const override; /** * 获取节目总时长 - * @return + * @return 节目总时长,单位秒 */ float getDuration() const override; protected: diff --git a/src/Rtmp/RtmpMediaSourceMuxer.h b/src/Rtmp/RtmpMediaSourceMuxer.h index e3d9561d..2f8e81cc 100644 --- a/src/Rtmp/RtmpMediaSourceMuxer.h +++ b/src/Rtmp/RtmpMediaSourceMuxer.h @@ -48,11 +48,12 @@ public: void setListener(const std::weak_ptr &listener){ _mediaSouce->setListener(listener); } + int readerCount() const{ return _mediaSouce->readerCount(); } -private: - void onAllTrackReady() override { + + void onAllTrackReady(){ _mediaSouce->onGetMetaData(getMetadata()); } private: diff --git a/src/Rtmp/RtmpMuxer.cpp b/src/Rtmp/RtmpMuxer.cpp index 6ed7e324..e252d410 100644 --- a/src/Rtmp/RtmpMuxer.cpp +++ b/src/Rtmp/RtmpMuxer.cpp @@ -38,13 +38,7 @@ RtmpMuxer::RtmpMuxer(const TitleMeta::Ptr &title) { _rtmpRing = std::make_shared(); } -void RtmpMuxer::onTrackReady(const Track::Ptr &track) { - //生成rtmp编码器 - //克隆该Track,防止循环引用 - auto encoder = Factory::getRtmpCodecByTrack(track->clone()); - if (!encoder) { - return; - } +void RtmpMuxer::addTrack(const Track::Ptr &track) { //根据track生产metadata Metadata::Ptr metadata; switch (track->getTrackType()){ @@ -57,26 +51,34 @@ void RtmpMuxer::onTrackReady(const Track::Ptr &track) { } break; default: - return;; + return; } + + auto &encoder = _encoder[track->getTrackType()]; + //生成rtmp编码器,克隆该Track,防止循环引用 + encoder = Factory::getRtmpCodecByTrack(track->clone()); + if (!encoder) { + return; + } + + //设置rtmp输出环形缓存 + encoder->setRtmpRing(_rtmpRing); + //添加其metadata metadata->getMetadata().object_for_each([&](const std::string &key, const AMFValue &value){ _metadata.set(key,value); }); - //设置Track的代理,这样输入frame至Track时,最终数据将输出到RtmpEncoder中 - track->addDelegate(encoder); - //Rtmp编码器共用同一个环形缓存 - encoder->setRtmpRing(_rtmpRing); } +void RtmpMuxer::inputFrame(const Frame::Ptr &frame) { + auto &encoder = _encoder[frame->getTrackType()]; + if(encoder){ + encoder->inputFrame(frame); + } +} const AMFValue &RtmpMuxer::getMetadata() const { - if(!isAllTrackReady()){ - //尚未就绪 - static AMFValue s_amf; - return s_amf; - } return _metadata; } @@ -84,4 +86,12 @@ RtmpRingInterface::RingType::Ptr RtmpMuxer::getRtmpRing() const { return _rtmpRing; } +void RtmpMuxer::resetTracks() { + _metadata.clear(); + for(auto &encoder : _encoder){ + encoder = nullptr; + } +} + + }/* namespace mediakit */ \ No newline at end of file diff --git a/src/Rtmp/RtmpMuxer.h b/src/Rtmp/RtmpMuxer.h index 87552eb5..3c4743b9 100644 --- a/src/Rtmp/RtmpMuxer.h +++ b/src/Rtmp/RtmpMuxer.h @@ -34,7 +34,7 @@ namespace mediakit{ -class RtmpMuxer : public MediaSink{ +class RtmpMuxer : public MediaSinkInterface{ public: typedef std::shared_ptr Ptr; @@ -55,16 +55,26 @@ public: * @return */ RtmpRingInterface::RingType::Ptr getRtmpRing() const; -protected: + /** - * 某track已经准备好,其ready()状态返回true, - * 此时代表可以获取其例如sps pps等相关信息了 - * @param track - */ - void onTrackReady(const Track::Ptr & track) override ; + * 添加ready状态的track + */ + void addTrack(const Track::Ptr & track) override; + + /** + * 写入帧数据 + * @param frame 帧 + */ + void inputFrame(const Frame::Ptr &frame) override; + + /** + * 重置所有track + */ + void resetTracks() override ; private: RtmpRingInterface::RingType::Ptr _rtmpRing; AMFValue _metadata; + RtmpCodec::Ptr _encoder[TrackMax]; }; diff --git a/src/Rtsp/RtspMediaSourceMuxer.h b/src/Rtsp/RtspMediaSourceMuxer.h index f4637942..9c496bd6 100644 --- a/src/Rtsp/RtspMediaSourceMuxer.h +++ b/src/Rtsp/RtspMediaSourceMuxer.h @@ -48,14 +48,16 @@ public: void setListener(const std::weak_ptr &listener){ _mediaSouce->setListener(listener); } + int readerCount() const{ return _mediaSouce->readerCount(); } + void setTimeStamp(uint32_t stamp){ _mediaSouce->setTimeStamp(stamp); } -private: - void onAllTrackReady() override { + + void onAllTrackReady(){ _mediaSouce->onGetSDP(getSdp()); } private: diff --git a/src/Rtsp/RtspMuxer.cpp b/src/Rtsp/RtspMuxer.cpp index 9f4da62a..1e482add 100644 --- a/src/Rtsp/RtspMuxer.cpp +++ b/src/Rtsp/RtspMuxer.cpp @@ -38,29 +38,34 @@ RtspMuxer::RtspMuxer(const TitleSdp::Ptr &title){ _rtpRing = std::make_shared(); } -void RtspMuxer::onTrackReady(const Track::Ptr &track) { +void RtspMuxer::addTrack(const Track::Ptr &track) { //根据track生成sdp Sdp::Ptr sdp = track->getSdp(); if (!sdp) { return; } - auto encoder = Factory::getRtpEncoderBySdp(sdp); + + auto &encoder = _encoder[track->getTrackType()]; + encoder = Factory::getRtpEncoderBySdp(sdp); if (!encoder) { return; } + + //设置rtp输出环形缓存 + encoder->setRtpRing(_rtpRing); + //添加其sdp _sdp.append(sdp->getSdp()); - //设置Track的代理,这样输入frame至Track时,最终数据将输出到RtpEncoder中 - track->addDelegate(encoder); - //rtp编码器共用同一个环形缓存 - encoder->setRtpRing(_rtpRing); +} + +void RtspMuxer::inputFrame(const Frame::Ptr &frame) { + auto &encoder = _encoder[frame->getTrackType()]; + if(encoder){ + encoder->inputFrame(frame); + } } string RtspMuxer::getSdp() { - if(!isAllTrackReady()){ - //尚未就绪 - return ""; - } return _sdp; } @@ -68,5 +73,12 @@ RtpRingInterface::RingType::Ptr RtspMuxer::getRtpRing() const { return _rtpRing; } +void RtspMuxer::resetTracks() { + _sdp.clear(); + for(auto &encoder : _encoder){ + encoder = nullptr; + } +} + } /* namespace mediakit */ \ No newline at end of file diff --git a/src/Rtsp/RtspMuxer.h b/src/Rtsp/RtspMuxer.h index 3d99537b..2d9a8736 100644 --- a/src/Rtsp/RtspMuxer.h +++ b/src/Rtsp/RtspMuxer.h @@ -35,7 +35,7 @@ namespace mediakit{ /** * rtsp生成器 */ -class RtspMuxer : public MediaSink{ +class RtspMuxer : public MediaSinkInterface{ public: typedef std::shared_ptr Ptr; @@ -57,16 +57,26 @@ public: * @return */ RtpRingInterface::RingType::Ptr getRtpRing() const; -protected: + /** - * 某track已经准备好,其ready()状态返回true, - * 此时代表可以获取其例如sps pps等相关信息了 - * @param track - */ - void onTrackReady(const Track::Ptr & track) override ; + * 添加ready状态的track + */ + void addTrack(const Track::Ptr & track) override; + + /** + * 写入帧数据 + * @param frame 帧 + */ + void inputFrame(const Frame::Ptr &frame) override; + + /** + * 重置所有track + */ + void resetTracks() override ; private: - RtpRingInterface::RingType::Ptr _rtpRing; string _sdp; + RtpCodec::Ptr _encoder[TrackMax]; + RtpRingInterface::RingType::Ptr _rtpRing; };