Commit d6e60e09 by Weiwei.Zhou

添加断流重连是否接着前一次继续写;修复断流重连成功后hls时间戳错误问题

parent 7d76a3eb
...@@ -32,6 +32,9 @@ streamNoneReaderDelayMS=5000 ...@@ -32,6 +32,9 @@ streamNoneReaderDelayMS=5000
ultraLowDelay=1 ultraLowDelay=1
#拉流代理是否添加静音音频(直接拉流模式本协议无效) #拉流代理是否添加静音音频(直接拉流模式本协议无效)
addMuteAudio=1 addMuteAudio=1
#拉流代理时如果断流再重连成功是否删除前一次的媒体流数据,如果删除将重新开始,
#如果不删除将会接着上一次的数据继续写(录制hls/mp4时会继续在前一个文件后面写)
resetWhenRePlay=1
[hls] [hls]
#hls写文件的buf大小,调整参数可以提高文件io性能 #hls写文件的buf大小,调整参数可以提高文件io性能
......
...@@ -32,7 +32,7 @@ namespace mediakit{ ...@@ -32,7 +32,7 @@ namespace mediakit{
void MediaSink::addTrack(const Track::Ptr &track_in) { void MediaSink::addTrack(const Track::Ptr &track_in) {
lock_guard<recursive_mutex> lck(_mtx); lock_guard<recursive_mutex> lck(_mtx);
//克隆Track,只拷贝其数据,不拷贝其数据转发关系 //克隆Track,只拷贝其数据,不拷贝其数据转发关系
auto track = track_in->clone(); auto track = track_in->clone();
weak_ptr<MediaSink> weakSelf = shared_from_this(); weak_ptr<MediaSink> weakSelf = shared_from_this();
...@@ -60,6 +60,14 @@ void MediaSink::addTrack(const Track::Ptr &track_in) { ...@@ -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) { void MediaSink::inputFrame(const Frame::Ptr &frame) {
lock_guard<recursive_mutex> lck(_mtx); lock_guard<recursive_mutex> lck(_mtx);
auto codec_id = frame->getCodecId(); auto codec_id = frame->getCodecId();
......
...@@ -52,7 +52,7 @@ public: ...@@ -52,7 +52,7 @@ public:
* 输入frame * 输入frame
* @param frame * @param frame
*/ */
void inputFrame(const Frame::Ptr &frame) override ; void inputFrame(const Frame::Ptr &frame) override;
/** /**
* 添加track,内部会调用Track的clone方法 * 添加track,内部会调用Track的clone方法
...@@ -61,13 +61,16 @@ public: ...@@ -61,13 +61,16 @@ public:
*/ */
virtual void addTrack(const Track::Ptr & track); virtual void addTrack(const Track::Ptr & track);
/**
* 重置track
*/
virtual void resetTracks();
/** /**
* 全部Track是否都准备好了 * 全部Track是否都准备好了
* @return * @return
*/ */
bool isAllTrackReady() const ; bool isAllTrackReady() const;
/** /**
* 获取特定类型的Track * 获取特定类型的Track
...@@ -75,7 +78,7 @@ public: ...@@ -75,7 +78,7 @@ public:
* @param trackReady 是否获取已经准备好的Track * @param trackReady 是否获取已经准备好的Track
* @return * @return
*/ */
Track::Ptr getTrack(TrackType type,bool trackReady = true) const ; Track::Ptr getTrack(TrackType type,bool trackReady = true) const;
protected: protected:
/** /**
* 某track已经准备好,其ready()状态返回true, * 某track已经准备好,其ready()状态返回true,
......
...@@ -70,6 +70,19 @@ public: ...@@ -70,6 +70,19 @@ public:
} }
/** /**
* 重置音视频媒体
*/
void resetTracks() {
if(_rtmp){
_rtmp->resetTracks();
}
if(_rtsp){
_rtsp->resetTracks();
}
_record->resetTracks();
}
/**
* 写入帧数据然后打包rtmp * 写入帧数据然后打包rtmp
* @param frame 帧数据 * @param frame 帧数据
*/ */
......
...@@ -78,6 +78,7 @@ const string kMaxStreamWaitTimeMS = GENERAL_FIELD"maxStreamWaitMS"; ...@@ -78,6 +78,7 @@ const string kMaxStreamWaitTimeMS = GENERAL_FIELD"maxStreamWaitMS";
const string kEnableVhost = GENERAL_FIELD"enableVhost"; const string kEnableVhost = GENERAL_FIELD"enableVhost";
const string kUltraLowDelay = GENERAL_FIELD"ultraLowDelay"; const string kUltraLowDelay = GENERAL_FIELD"ultraLowDelay";
const string kAddMuteAudio = GENERAL_FIELD"addMuteAudio"; const string kAddMuteAudio = GENERAL_FIELD"addMuteAudio";
const string kResetWhenRePlay = GENERAL_FIELD"resetWhenRePlay";
onceToken token([](){ onceToken token([](){
mINI::Instance()[kFlowThreshold] = 1024; mINI::Instance()[kFlowThreshold] = 1024;
...@@ -86,6 +87,7 @@ onceToken token([](){ ...@@ -86,6 +87,7 @@ onceToken token([](){
mINI::Instance()[kEnableVhost] = 1; mINI::Instance()[kEnableVhost] = 1;
mINI::Instance()[kUltraLowDelay] = 1; mINI::Instance()[kUltraLowDelay] = 1;
mINI::Instance()[kAddMuteAudio] = 1; mINI::Instance()[kAddMuteAudio] = 1;
mINI::Instance()[kResetWhenRePlay] = 1;
},nullptr); },nullptr);
}//namespace General }//namespace General
......
...@@ -179,6 +179,9 @@ extern const string kEnableVhost; ...@@ -179,6 +179,9 @@ extern const string kEnableVhost;
extern const string kUltraLowDelay; extern const string kUltraLowDelay;
//拉流代理时是否添加静音音频 //拉流代理时是否添加静音音频
extern const string kAddMuteAudio; extern const string kAddMuteAudio;
//拉流代理时如果断流再重连成功是否删除前一次的媒体流数据,如果删除将重新开始,
//如果不删除将会接着上一次的数据继续写(录制hls/mp4时会继续在前一个文件后面写)
extern const string kResetWhenRePlay;
}//namespace General }//namespace General
......
...@@ -81,8 +81,18 @@ void HlsMaker::makeIndexFile(bool eof) { ...@@ -81,8 +81,18 @@ void HlsMaker::makeIndexFile(bool eof) {
void HlsMaker::inputData(void *data, uint32_t len, uint32_t timestamp) { void HlsMaker::inputData(void *data, uint32_t len, uint32_t timestamp) {
//分片数据中断结束
if (data && len) {
addNewFile(timestamp); addNewFile(timestamp);
onWriteFile((char *) data, len); 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() { void HlsMaker::delOldFile() {
...@@ -102,6 +112,12 @@ void HlsMaker::delOldFile() { ...@@ -102,6 +112,12 @@ void HlsMaker::delOldFile() {
} }
void HlsMaker::addNewFile(uint32_t) { void HlsMaker::addNewFile(uint32_t) {
//上次分片数据中断结束,重置时间避免中途的等待
if (_noData) {
_ticker.resetTime();
_last_file_name = onOpenFile(_file_index++);
_noData = false;
}
_stampInc = _ticker.elapsedTime(); _stampInc = _ticker.elapsedTime();
if (_file_index == 0 || _stampInc >= _seg_duration * 1000) { if (_file_index == 0 || _stampInc >= _seg_duration * 1000) {
_ticker.resetTime(); _ticker.resetTime();
......
...@@ -92,6 +92,7 @@ protected: ...@@ -92,6 +92,7 @@ protected:
protected: protected:
uint32_t _seg_number = 0; uint32_t _seg_number = 0;
private: private:
bool _noData = false;
int _stampInc = 0; int _stampInc = 0;
float _seg_duration = 0; float _seg_duration = 0;
uint64_t _file_index = 0; uint64_t _file_index = 0;
......
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
namespace mediakit { namespace mediakit {
class HlsRecorder : public HlsMakerImp , public TsMuxer { class HlsRecorder : public HlsMakerImp, public TsMuxer {
public: public:
template<typename ...ArgsType> template<typename ...ArgsType>
HlsRecorder(ArgsType &&...args):HlsMakerImp(std::forward<ArgsType>(args)...){} HlsRecorder(ArgsType &&...args):HlsMakerImp(std::forward<ArgsType>(args)...){}
......
...@@ -113,4 +113,18 @@ void MediaRecorder::addTrack(const Track::Ptr &track) { ...@@ -113,4 +113,18 @@ void MediaRecorder::addTrack(const Track::Ptr &track) {
#endif //defined(ENABLE_MP4RECORD) #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 */ } /* namespace mediakit */
...@@ -51,7 +51,7 @@ public: ...@@ -51,7 +51,7 @@ public:
* 输入frame * 输入frame
* @param frame * @param frame
*/ */
void inputFrame(const Frame::Ptr &frame) override ; void inputFrame(const Frame::Ptr &frame) override;
/** /**
* 添加track,内部会调用Track的clone方法 * 添加track,内部会调用Track的clone方法
...@@ -59,6 +59,11 @@ public: ...@@ -59,6 +59,11 @@ public:
* @param track * @param track
*/ */
void addTrack(const Track::Ptr & track) override; void addTrack(const Track::Ptr & track) override;
/**
* 重置track
*/
void resetTracks() override;
private: private:
#if defined(ENABLE_HLS) #if defined(ENABLE_HLS)
std::shared_ptr<HlsRecorder> _hlsRecorder; std::shared_ptr<HlsRecorder> _hlsRecorder;
......
...@@ -101,6 +101,8 @@ void TsMuxer::inputFrame(const Frame::Ptr &frame) { ...@@ -101,6 +101,8 @@ void TsMuxer::inputFrame(const Frame::Ptr &frame) {
} }
void TsMuxer::resetTracks() { void TsMuxer::resetTracks() {
//通知片段中断
onTs(nullptr, 0, 0, 0);
uninit(); uninit();
init(); init();
} }
......
...@@ -43,10 +43,10 @@ public: ...@@ -43,10 +43,10 @@ public:
TsMuxer(); TsMuxer();
virtual ~TsMuxer(); virtual ~TsMuxer();
void addTrack(const Track::Ptr &track) override; void addTrack(const Track::Ptr &track) override;
void resetTracks() override;
void inputFrame(const Frame::Ptr &frame) override; void inputFrame(const Frame::Ptr &frame) override;
protected: protected:
virtual void onTs(const void *packet, int bytes,uint32_t timestamp,int flags) = 0; virtual void onTs(const void *packet, int bytes,uint32_t timestamp,int flags) = 0;
void resetTracks();
private: private:
void init(); void init();
void uninit(); void uninit();
......
...@@ -122,7 +122,13 @@ void PlayerProxy::play(const string &strUrlTmp) { ...@@ -122,7 +122,13 @@ void PlayerProxy::play(const string &strUrlTmp) {
for (auto & track : tracks){ for (auto & track : tracks){
track->delDelegate(strongSelf->_mediaMuxer.get()); track->delDelegate(strongSelf->_mediaMuxer.get());
} }
GET_CONFIG(bool,resetWhenRePlay,General::kResetWhenRePlay);
if (resetWhenRePlay) {
strongSelf->_mediaMuxer.reset(); strongSelf->_mediaMuxer.reset();
} else {
strongSelf->_mediaMuxer->resetTracks();
}
} }
//播放异常中断,延时重试播放 //播放异常中断,延时重试播放
if(*piFailedCnt < strongSelf->_iRetryCount || strongSelf->_iRetryCount < 0) { if(*piFailedCnt < strongSelf->_iRetryCount || strongSelf->_iRetryCount < 0) {
...@@ -138,7 +144,7 @@ void PlayerProxy::play(const string &strUrlTmp) { ...@@ -138,7 +144,7 @@ void PlayerProxy::play(const string &strUrlTmp) {
if(directProxy && _bEnableRtsp){ if(directProxy && _bEnableRtsp){
mediaSource = std::make_shared<RtspMediaSource>(_strVhost,_strApp,_strSrc); mediaSource = std::make_shared<RtspMediaSource>(_strVhost,_strApp,_strSrc);
} }
}else if(dynamic_pointer_cast<RtmpPlayer>(_parser)){ } else if(dynamic_pointer_cast<RtmpPlayer>(_parser)){
//rtmp拉流 //rtmp拉流
if(_bEnableRtmp){ if(_bEnableRtmp){
mediaSource = std::make_shared<RtmpMediaSource>(_strVhost,_strApp,_strSrc); mediaSource = std::make_shared<RtmpMediaSource>(_strVhost,_strApp,_strSrc);
...@@ -154,7 +160,7 @@ PlayerProxy::~PlayerProxy() { ...@@ -154,7 +160,7 @@ PlayerProxy::~PlayerProxy() {
_timer.reset(); _timer.reset();
} }
void PlayerProxy::rePlay(const string &strUrl,int iFailedCnt){ 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<PlayerProxy> weakSelf = shared_from_this(); weak_ptr<PlayerProxy> weakSelf = shared_from_this();
_timer = std::make_shared<Timer>(iDelay / 1000.0f,[weakSelf,strUrl,iFailedCnt]() { _timer = std::make_shared<Timer>(iDelay / 1000.0f,[weakSelf,strUrl,iFailedCnt]() {
//播放失败次数越多,则延时越长 //播放失败次数越多,则延时越长
...@@ -224,16 +230,23 @@ private: ...@@ -224,16 +230,23 @@ private:
}; };
void PlayerProxy::onPlaySuccess() { void PlayerProxy::onPlaySuccess() {
GET_CONFIG(bool,resetWhenRePlay,General::kResetWhenRePlay);
if (dynamic_pointer_cast<RtspMediaSource>(_pMediaSrc)) { if (dynamic_pointer_cast<RtspMediaSource>(_pMediaSrc)) {
//rtsp拉流代理 //rtsp拉流代理
if (resetWhenRePlay || !_mediaMuxer) {
_mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost, _strApp, _strSrc, getDuration(), false, _bEnableRtmp, _bEnableHls, _bEnableMp4)); _mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost, _strApp, _strSrc, getDuration(), false, _bEnableRtmp, _bEnableHls, _bEnableMp4));
}
} else if (dynamic_pointer_cast<RtmpMediaSource>(_pMediaSrc)) { } else if (dynamic_pointer_cast<RtmpMediaSource>(_pMediaSrc)) {
//rtmp拉流代理 //rtmp拉流代理
if (resetWhenRePlay || !_mediaMuxer) {
_mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost, _strApp, _strSrc, getDuration(), _bEnableRtsp, false, _bEnableHls, _bEnableMp4)); _mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost, _strApp, _strSrc, getDuration(), _bEnableRtsp, false, _bEnableHls, _bEnableMp4));
}
} else { } else {
//其他拉流代理 //其他拉流代理
if (resetWhenRePlay || !_mediaMuxer) {
_mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost, _strApp, _strSrc, getDuration(), _bEnableRtsp, _bEnableRtmp, _bEnableHls, _bEnableMp4)); _mediaMuxer.reset(new MultiMediaSourceMuxer(_strVhost, _strApp, _strSrc, getDuration(), _bEnableRtsp, _bEnableRtmp, _bEnableHls, _bEnableMp4));
} }
}
_mediaMuxer->setListener(shared_from_this()); _mediaMuxer->setListener(shared_from_this());
auto videoTrack = getTrack(TrackVideo,false); auto videoTrack = getTrack(TrackVideo,false);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论