From d6e60e09192abaceb85c30b2954d5eaad53877ad Mon Sep 17 00:00:00 2001 From: "Weiwei.Zhou" Date: Fri, 11 Oct 2019 16:51:10 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=AD=E6=B5=81=E9=87=8D?= =?UTF-8?q?=E8=BF=9E=E6=98=AF=E5=90=A6=E6=8E=A5=E7=9D=80=E5=89=8D=E4=B8=80?= =?UTF-8?q?=E6=AC=A1=E7=BB=A7=E7=BB=AD=E5=86=99;=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=96=AD=E6=B5=81=E9=87=8D=E8=BF=9E=E6=88=90=E5=8A=9F=E5=90=8E?= =?UTF-8?q?hls=E6=97=B6=E9=97=B4=E6=88=B3=E9=94=99=E8=AF=AF=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conf/config.ini | 3 +++ src/Common/MediaSink.cpp | 10 +++++++++- src/Common/MediaSink.h | 13 ++++++++----- src/Common/MultiMediaSourceMuxer.h | 13 +++++++++++++ src/Common/config.cpp | 2 ++ src/Common/config.h | 3 +++ src/MediaFile/HlsMaker.cpp | 20 ++++++++++++++++++-- src/MediaFile/HlsMaker.h | 1 + src/MediaFile/HlsRecorder.h | 2 +- src/MediaFile/MediaRecorder.cpp | 14 ++++++++++++++ src/MediaFile/MediaRecorder.h | 21 +++++++++++++-------- src/MediaFile/TsMuxer.cpp | 2 ++ src/MediaFile/TsMuxer.h | 4 ++-- src/Player/PlayerProxy.cpp | 27 ++++++++++++++++++++------- 14 files changed, 109 insertions(+), 26 deletions(-) diff --git a/conf/config.ini b/conf/config.ini index 6c3c6e4a..15d8c7ff 100644 --- a/conf/config.ini +++ b/conf/config.ini @@ -32,6 +32,9 @@ streamNoneReaderDelayMS=5000 ultraLowDelay=1 #拉流代理是否添加静音音频(直接拉流模式本协议无效) addMuteAudio=1 +#拉流代理时如果断流再重连成功是否删除前一次的媒体流数据,如果删除将重新开始, +#如果不删除将会接着上一次的数据继续写(录制hls/mp4时会继续在前一个文件后面写) +resetWhenRePlay=1 [hls] #hls写文件的buf大小,调整参数可以提高文件io性能 diff --git a/src/Common/MediaSink.cpp b/src/Common/MediaSink.cpp index b2263e54..960ea7e9 100644 --- a/src/Common/MediaSink.cpp +++ b/src/Common/MediaSink.cpp @@ -32,7 +32,7 @@ namespace mediakit{ void MediaSink::addTrack(const Track::Ptr &track_in) { lock_guard lck(_mtx); -//克隆Track,只拷贝其数据,不拷贝其数据转发关系 + //克隆Track,只拷贝其数据,不拷贝其数据转发关系 auto track = track_in->clone(); weak_ptr weakSelf = shared_from_this(); @@ -60,6 +60,14 @@ void MediaSink::addTrack(const Track::Ptr &track_in) { } } +void MediaSink::resetTracks() { + _anyTrackUnReady = true; + _allTrackReady = false; + _track_map.clear(); + _trackReadyCallback.clear(); + _ticker.resetTime(); +} + void MediaSink::inputFrame(const Frame::Ptr &frame) { lock_guard lck(_mtx); auto codec_id = frame->getCodecId(); diff --git a/src/Common/MediaSink.h b/src/Common/MediaSink.h index a45b9638..8798590d 100644 --- a/src/Common/MediaSink.h +++ b/src/Common/MediaSink.h @@ -52,7 +52,7 @@ public: * 输入frame * @param frame */ - void inputFrame(const Frame::Ptr &frame) override ; + void inputFrame(const Frame::Ptr &frame) override; /** * 添加track,内部会调用Track的clone方法 @@ -61,21 +61,24 @@ public: */ virtual void addTrack(const Track::Ptr & track); + /** + * 重置track + */ + virtual void resetTracks(); /** * 全部Track是否都准备好了 * @return */ - bool isAllTrackReady() const ; - + bool isAllTrackReady() const; /** * 获取特定类型的Track * @param type track类型 - * @param trackReady 是否获取已经准备好的Track + * @param trackReady 是否获取已经准备好的Track * @return */ - Track::Ptr getTrack(TrackType type,bool trackReady = true) const ; + Track::Ptr getTrack(TrackType type,bool trackReady = true) const; protected: /** * 某track已经准备好,其ready()状态返回true, diff --git a/src/Common/MultiMediaSourceMuxer.h b/src/Common/MultiMediaSourceMuxer.h index 895ba506..b466ffec 100644 --- a/src/Common/MultiMediaSourceMuxer.h +++ b/src/Common/MultiMediaSourceMuxer.h @@ -69,6 +69,19 @@ public: _record->addTrack(track); } + /** + * 重置音视频媒体 + */ + void resetTracks() { + if(_rtmp){ + _rtmp->resetTracks(); + } + if(_rtsp){ + _rtsp->resetTracks(); + } + _record->resetTracks(); + } + /** * 写入帧数据然后打包rtmp * @param frame 帧数据 diff --git a/src/Common/config.cpp b/src/Common/config.cpp index 02827594..a2a6ed28 100644 --- a/src/Common/config.cpp +++ b/src/Common/config.cpp @@ -78,6 +78,7 @@ const string kMaxStreamWaitTimeMS = GENERAL_FIELD"maxStreamWaitMS"; const string kEnableVhost = GENERAL_FIELD"enableVhost"; const string kUltraLowDelay = GENERAL_FIELD"ultraLowDelay"; const string kAddMuteAudio = GENERAL_FIELD"addMuteAudio"; +const string kResetWhenRePlay = GENERAL_FIELD"resetWhenRePlay"; onceToken token([](){ mINI::Instance()[kFlowThreshold] = 1024; @@ -86,6 +87,7 @@ onceToken token([](){ mINI::Instance()[kEnableVhost] = 1; mINI::Instance()[kUltraLowDelay] = 1; mINI::Instance()[kAddMuteAudio] = 1; + mINI::Instance()[kResetWhenRePlay] = 1; },nullptr); }//namespace General diff --git a/src/Common/config.h b/src/Common/config.h index 0cf7e34b..a4557ea1 100644 --- a/src/Common/config.h +++ b/src/Common/config.h @@ -179,6 +179,9 @@ extern const string kEnableVhost; extern const string kUltraLowDelay; //拉流代理时是否添加静音音频 extern const string kAddMuteAudio; +//拉流代理时如果断流再重连成功是否删除前一次的媒体流数据,如果删除将重新开始, +//如果不删除将会接着上一次的数据继续写(录制hls/mp4时会继续在前一个文件后面写) +extern const string kResetWhenRePlay; }//namespace General diff --git a/src/MediaFile/HlsMaker.cpp b/src/MediaFile/HlsMaker.cpp index c067be0b..1a80fba0 100644 --- a/src/MediaFile/HlsMaker.cpp +++ b/src/MediaFile/HlsMaker.cpp @@ -81,8 +81,18 @@ void HlsMaker::makeIndexFile(bool eof) { void HlsMaker::inputData(void *data, uint32_t len, uint32_t timestamp) { - addNewFile(timestamp); - onWriteFile((char *) data, len); + //分片数据中断结束 + if (data && len) { + addNewFile(timestamp); + onWriteFile((char *) data, len); + } + else { + _noData = true; + _stampInc = _ticker.elapsedTime(); + _seg_dur_list.push_back(std::make_tuple(_stampInc, _last_file_name)); + delOldFile(); + makeIndexFile(); + } } void HlsMaker::delOldFile() { @@ -102,6 +112,12 @@ void HlsMaker::delOldFile() { } void HlsMaker::addNewFile(uint32_t) { + //上次分片数据中断结束,重置时间避免中途的等待 + if (_noData) { + _ticker.resetTime(); + _last_file_name = onOpenFile(_file_index++); + _noData = false; + } _stampInc = _ticker.elapsedTime(); if (_file_index == 0 || _stampInc >= _seg_duration * 1000) { _ticker.resetTime(); diff --git a/src/MediaFile/HlsMaker.h b/src/MediaFile/HlsMaker.h index 3e288b73..46731759 100644 --- a/src/MediaFile/HlsMaker.h +++ b/src/MediaFile/HlsMaker.h @@ -92,6 +92,7 @@ protected: protected: uint32_t _seg_number = 0; private: + bool _noData = false; int _stampInc = 0; float _seg_duration = 0; uint64_t _file_index = 0; diff --git a/src/MediaFile/HlsRecorder.h b/src/MediaFile/HlsRecorder.h index 7b876ae0..ca20c5f0 100644 --- a/src/MediaFile/HlsRecorder.h +++ b/src/MediaFile/HlsRecorder.h @@ -32,7 +32,7 @@ namespace mediakit { -class HlsRecorder : public HlsMakerImp , public TsMuxer { +class HlsRecorder : public HlsMakerImp, public TsMuxer { public: template HlsRecorder(ArgsType &&...args):HlsMakerImp(std::forward(args)...){} diff --git a/src/MediaFile/MediaRecorder.cpp b/src/MediaFile/MediaRecorder.cpp index 24309dfa..3f348778 100644 --- a/src/MediaFile/MediaRecorder.cpp +++ b/src/MediaFile/MediaRecorder.cpp @@ -113,4 +113,18 @@ void MediaRecorder::addTrack(const Track::Ptr &track) { #endif //defined(ENABLE_MP4RECORD) } +void MediaRecorder::resetTracks() { +#if defined(ENABLE_HLS) + if (_hlsRecorder) { + _hlsRecorder->resetTracks(); + } +#endif //defined(ENABLE_HLS) + +#if defined(ENABLE_MP4RECORD) + if (_mp4Recorder) { + _mp4Recorder->resetTracks(); + } +#endif //defined(ENABLE_MP4RECORD) +} + } /* namespace mediakit */ diff --git a/src/MediaFile/MediaRecorder.h b/src/MediaFile/MediaRecorder.h index 70ff0093..9619e338 100644 --- a/src/MediaFile/MediaRecorder.h +++ b/src/MediaFile/MediaRecorder.h @@ -48,17 +48,22 @@ public: virtual ~MediaRecorder(); /** - * 输入frame - * @param frame - */ - void inputFrame(const Frame::Ptr &frame) override ; + * 输入frame + * @param frame + */ + void inputFrame(const Frame::Ptr &frame) override; /** - * 添加track,内部会调用Track的clone方法 - * 只会克隆sps pps这些信息 ,而不会克隆Delegate相关关系 - * @param track - */ + * 添加track,内部会调用Track的clone方法 + * 只会克隆sps pps这些信息 ,而不会克隆Delegate相关关系 + * @param track + */ void addTrack(const Track::Ptr & track) override; + + /** + * 重置track + */ + void resetTracks() override; private: #if defined(ENABLE_HLS) std::shared_ptr _hlsRecorder; diff --git a/src/MediaFile/TsMuxer.cpp b/src/MediaFile/TsMuxer.cpp index f0d1092a..fe63624b 100644 --- a/src/MediaFile/TsMuxer.cpp +++ b/src/MediaFile/TsMuxer.cpp @@ -101,6 +101,8 @@ void TsMuxer::inputFrame(const Frame::Ptr &frame) { } void TsMuxer::resetTracks() { + //通知片段中断 + onTs(nullptr, 0, 0, 0); uninit(); init(); } diff --git a/src/MediaFile/TsMuxer.h b/src/MediaFile/TsMuxer.h index b4ea0fab..a876c8c3 100644 --- a/src/MediaFile/TsMuxer.h +++ b/src/MediaFile/TsMuxer.h @@ -43,10 +43,10 @@ public: TsMuxer(); virtual ~TsMuxer(); void addTrack(const Track::Ptr &track) override; - void inputFrame(const Frame::Ptr &frame) override; + void resetTracks() override; + void inputFrame(const Frame::Ptr &frame) override; protected: virtual void onTs(const void *packet, int bytes,uint32_t timestamp,int flags) = 0; - void resetTracks(); private: void init(); void uninit(); diff --git a/src/Player/PlayerProxy.cpp b/src/Player/PlayerProxy.cpp index fce309b9..075394c9 100644 --- a/src/Player/PlayerProxy.cpp +++ b/src/Player/PlayerProxy.cpp @@ -122,7 +122,13 @@ void PlayerProxy::play(const string &strUrlTmp) { for (auto & track : tracks){ track->delDelegate(strongSelf->_mediaMuxer.get()); } - strongSelf->_mediaMuxer.reset(); + + GET_CONFIG(bool,resetWhenRePlay,General::kResetWhenRePlay); + if (resetWhenRePlay) { + strongSelf->_mediaMuxer.reset(); + } else { + strongSelf->_mediaMuxer->resetTracks(); + } } //播放异常中断,延时重试播放 if(*piFailedCnt < strongSelf->_iRetryCount || strongSelf->_iRetryCount < 0) { @@ -138,7 +144,7 @@ void PlayerProxy::play(const string &strUrlTmp) { if(directProxy && _bEnableRtsp){ mediaSource = std::make_shared(_strVhost,_strApp,_strSrc); } - }else if(dynamic_pointer_cast(_parser)){ + } else if(dynamic_pointer_cast(_parser)){ //rtmp拉流 if(_bEnableRtmp){ mediaSource = std::make_shared(_strVhost,_strApp,_strSrc); @@ -154,7 +160,7 @@ PlayerProxy::~PlayerProxy() { _timer.reset(); } void PlayerProxy::rePlay(const string &strUrl,int iFailedCnt){ - auto iDelay = MAX(2 * 1000, MIN(iFailedCnt * 3000,60*1000)); + auto iDelay = MAX(2 * 1000, MIN(iFailedCnt * 3000, 60*1000)); weak_ptr weakSelf = shared_from_this(); _timer = std::make_shared(iDelay / 1000.0f,[weakSelf,strUrl,iFailedCnt]() { //播放失败次数越多,则延时越长 @@ -213,7 +219,7 @@ public: if(_iAudioIndex != iAudioIndex){ _iAudioIndex = iAudioIndex; auto aacFrame = std::make_shared((char *)MUTE_ADTS_DATA, - MUTE_ADTS_DATA_LEN, + MUTE_ADTS_DATA_LEN, _iAudioIndex * MUTE_ADTS_DATA_MS); FrameRingInterfaceDelegate::inputFrame(aacFrame); } @@ -224,15 +230,22 @@ private: }; void PlayerProxy::onPlaySuccess() { + GET_CONFIG(bool,resetWhenRePlay,General::kResetWhenRePlay); if (dynamic_pointer_cast(_pMediaSrc)) { //rtsp拉流代理 - _mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost, _strApp, _strSrc, getDuration(), false, _bEnableRtmp, _bEnableHls, _bEnableMp4)); + if (resetWhenRePlay || !_mediaMuxer) { + _mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost, _strApp, _strSrc, getDuration(), false, _bEnableRtmp, _bEnableHls, _bEnableMp4)); + } } else if (dynamic_pointer_cast(_pMediaSrc)) { //rtmp拉流代理 - _mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost, _strApp, _strSrc, getDuration(), _bEnableRtsp, false, _bEnableHls, _bEnableMp4)); + if (resetWhenRePlay || !_mediaMuxer) { + _mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost, _strApp, _strSrc, getDuration(), _bEnableRtsp, false, _bEnableHls, _bEnableMp4)); + } } else { //其他拉流代理 - _mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost, _strApp, _strSrc, getDuration(), _bEnableRtsp, _bEnableRtmp, _bEnableHls, _bEnableMp4)); + if (resetWhenRePlay || !_mediaMuxer) { + _mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost, _strApp, _strSrc, getDuration(), _bEnableRtsp, _bEnableRtmp, _bEnableHls, _bEnableMp4)); + } } _mediaMuxer->setListener(shared_from_this());