From 283188bedb4024c8edc2e0c31ce7499baba2ccb1 Mon Sep 17 00:00:00 2001 From: ziyue <1213642868@qq.com> Date: Wed, 15 Dec 2021 20:50:35 +0800 Subject: [PATCH] =?UTF-8?q?MP4Demuxer:=20=E6=8F=90=E9=AB=98MP4=E8=A7=A3?= =?UTF-8?q?=E5=A4=8D=E7=94=A8=E5=99=A8=E6=8E=A5=E5=8F=A3=E7=81=B5=E6=B4=BB?= =?UTF-8?q?=E5=BA=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Record/MP4Reader.cpp | 72 ++++++++++++++++++++++++++++------------ src/Record/MP4Reader.h | 16 +++++---- 2 files changed, 61 insertions(+), 27 deletions(-) diff --git a/src/Record/MP4Reader.cpp b/src/Record/MP4Reader.cpp index a0766b56..b5d43aee 100644 --- a/src/Record/MP4Reader.cpp +++ b/src/Record/MP4Reader.cpp @@ -15,23 +15,27 @@ using namespace toolkit; namespace mediakit { -MP4Reader::MP4Reader(const string &strVhost,const string &strApp, const string &strId,const string &filePath ) { +MP4Reader::MP4Reader(const string &vhost, const string &app, const string &stream_id, const string &file_path) { _poller = WorkThreadPool::Instance().getPoller(); - _file_path = filePath; - if(_file_path.empty()){ - GET_CONFIG(string,recordPath,Record::kFilePath); - GET_CONFIG(bool,enableVhost,General::kEnableVhost); - if(enableVhost){ - _file_path = strVhost + "/" + strApp + "/" + strId; - }else{ - _file_path = strApp + "/" + strId; + _file_path = file_path; + if (_file_path.empty()) { + GET_CONFIG(string, recordPath, Record::kFilePath); + GET_CONFIG(bool, enableVhost, General::kEnableVhost); + if (enableVhost) { + _file_path = vhost + "/" + app + "/" + stream_id; + } else { + _file_path = app + "/" + stream_id; } - _file_path = File::absolutePath(_file_path,recordPath); + _file_path = File::absolutePath(_file_path, recordPath); } _demuxer = std::make_shared(); _demuxer->openMP4(_file_path); - _muxer = std::make_shared(strVhost, strApp, strId, _demuxer->getDurationMS() / 1000.0f, true, true, false, false); + + if (stream_id.empty()) { + return; + } + _muxer = std::make_shared(vhost, app, stream_id, _demuxer->getDurationMS() / 1000.0f, true, true, false, false); auto tracks = _demuxer->getTracks(false); if(tracks.empty()){ throw std::runtime_error(StrPrinter << "该mp4文件没有有效的track:" << _file_path); @@ -60,14 +64,16 @@ bool MP4Reader::readSample() { if (!frame) { continue; } - _muxer->inputFrame(frame); + if (_muxer) { + _muxer->inputFrame(frame); + } if (frame->dts() > getCurrentStamp()) { break; } } GET_CONFIG(bool, fileRepeat, Record::kFileRepeat); - if (eof && fileRepeat) { + if (eof && (fileRepeat || _file_repeat)) { //需要从头开始看 seekTo(0); return true; @@ -76,10 +82,14 @@ bool MP4Reader::readSample() { return !eof; } -void MP4Reader::startReadMP4() { +void MP4Reader::stopReadMP4() { + _timer = nullptr; +} + +void MP4Reader::startReadMP4(const EventPoller::Ptr &poller, uint64_t sample_ms, bool ref_self, bool file_repeat) { GET_CONFIG(uint32_t, sampleMS, Record::kSampleMS); auto strongSelf = shared_from_this(); - _muxer->setMediaListener(strongSelf); + if (_muxer) { _muxer->setMediaListener(strongSelf); } //先获取关键帧 seekTo(0); @@ -88,10 +98,28 @@ void MP4Reader::startReadMP4() { readSample(); //启动定时器 - _timer = std::make_shared(sampleMS / 1000.0f, [strongSelf]() { - lock_guard lck(strongSelf->_mtx); - return strongSelf->readSample(); - }, _poller); + if (ref_self) { + _timer = std::make_shared((sample_ms ? sample_ms : sampleMS) / 1000.0f, [strongSelf]() { + lock_guard lck(strongSelf->_mtx); + return strongSelf->readSample(); + }, poller ? poller : _poller); + } else { + weak_ptr weak_self = strongSelf; + _timer = std::make_shared((sample_ms ? sample_ms : sampleMS) / 1000.0f, [weak_self]() { + auto strongSelf = weak_self.lock(); + if (!strongSelf) { + return false; + } + lock_guard lck(strongSelf->_mtx); + return strongSelf->readSample(); + }, poller ? poller : _poller); + } + + _file_repeat = file_repeat; +} + +const MP4Demuxer::Ptr &MP4Reader::getDemuxer() const { + return _demuxer; } uint32_t MP4Reader::getCurrentStamp() { @@ -102,7 +130,7 @@ void MP4Reader::setCurrentStamp(uint32_t new_stamp){ auto old_stamp = getCurrentStamp(); _seek_to = new_stamp; _seek_ticker.resetTime(); - if (old_stamp != new_stamp) { + if (old_stamp != new_stamp && _muxer) { //时间轴未拖动时不操作 _muxer->setTimeStamp(new_stamp); } @@ -170,7 +198,9 @@ bool MP4Reader::seekTo(uint32_t ui32Stamp) { } if(keyFrame || frame->keyFrame() || frame->configFrame()){ //定位到key帧 - _muxer->inputFrame(frame); + if (_muxer) { + _muxer->inputFrame(frame); + } //设置当前时间戳 setCurrentStamp(frame->dts()); return true; diff --git a/src/Record/MP4Reader.h b/src/Record/MP4Reader.h index 909fcd70..4978e78a 100644 --- a/src/Record/MP4Reader.h +++ b/src/Record/MP4Reader.h @@ -23,18 +23,21 @@ public: /** * 流化一个mp4文件,使之转换成RtspMediaSource和RtmpMediaSource - * @param strVhost 虚拟主机 - * @param strApp 应用名 - * @param strId 流id - * @param filePath 文件路径,如果为空则根据配置文件和上面参数自动生成,否则使用指定的文件 + * @param vhost 虚拟主机 + * @param app 应用名 + * @param stream_id 流id + * @param file_path 文件路径,如果为空则根据配置文件和上面参数自动生成,否则使用指定的文件 */ - MP4Reader(const string &strVhost,const string &strApp, const string &strId,const string &filePath = ""); + MP4Reader(const string &vhost, const string &app, const string &stream_id, const string &file_path = ""); /** * 开始流化MP4文件,需要指出的是,MP4Reader对象一经过调用startReadMP4方法,它的强引用会自持有, * 意思是在文件流化结束之前或中断之前,MP4Reader对象是不会被销毁的(不管有没有被外部对象持有) */ - void startReadMP4(); + void startReadMP4(const EventPoller::Ptr &poller = nullptr, uint64_t sample_ms = 0, bool ref_self = true, bool file_repeat = false); + void stopReadMP4(); + + const MP4Demuxer::Ptr& getDemuxer() const; private: //MediaSourceEvent override @@ -53,6 +56,7 @@ private: bool seekTo(uint32_t ui32Stamp); private: + bool _file_repeat = false; bool _have_video = false; bool _paused = false; float _speed = 1.0;