mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-22 10:40:05 +08:00
MP4Demuxer: 提高MP4解复用器接口灵活度
This commit is contained in:
parent
5bffc98541
commit
283188bedb
@ -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<MP4Demuxer>();
|
||||
_demuxer->openMP4(_file_path);
|
||||
_muxer = std::make_shared<MultiMediaSourceMuxer>(strVhost, strApp, strId, _demuxer->getDurationMS() / 1000.0f, true, true, false, false);
|
||||
|
||||
if (stream_id.empty()) {
|
||||
return;
|
||||
}
|
||||
_muxer = std::make_shared<MultiMediaSourceMuxer>(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;
|
||||
}
|
||||
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<Timer>(sampleMS / 1000.0f, [strongSelf]() {
|
||||
if (ref_self) {
|
||||
_timer = std::make_shared<Timer>((sample_ms ? sample_ms : sampleMS) / 1000.0f, [strongSelf]() {
|
||||
lock_guard<recursive_mutex> lck(strongSelf->_mtx);
|
||||
return strongSelf->readSample();
|
||||
}, _poller);
|
||||
}, poller ? poller : _poller);
|
||||
} else {
|
||||
weak_ptr<MP4Reader> weak_self = strongSelf;
|
||||
_timer = std::make_shared<Timer>((sample_ms ? sample_ms : sampleMS) / 1000.0f, [weak_self]() {
|
||||
auto strongSelf = weak_self.lock();
|
||||
if (!strongSelf) {
|
||||
return false;
|
||||
}
|
||||
lock_guard<recursive_mutex> 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帧
|
||||
if (_muxer) {
|
||||
_muxer->inputFrame(frame);
|
||||
}
|
||||
//设置当前时间戳
|
||||
setCurrentStamp(frame->dts());
|
||||
return true;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user