mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-22 10:40:05 +08:00
MP4 reader supports loading multi files
Some checks failed
Android / build (push) Has been cancelled
CodeQL / Analyze (cpp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Docker / build (push) Has been cancelled
Linux / build (push) Has been cancelled
macOS / build (push) Has been cancelled
Windows / build (push) Has been cancelled
Some checks failed
Android / build (push) Has been cancelled
CodeQL / Analyze (cpp) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Docker / build (push) Has been cancelled
Linux / build (push) Has been cancelled
macOS / build (push) Has been cancelled
Windows / build (push) Has been cancelled
This commit is contained in:
parent
e4025a6811
commit
61a93fab6a
@ -38,15 +38,24 @@ Frame::Ptr Frame::getCacheAbleFrame(const Frame::Ptr &frame){
|
||||
return std::make_shared<FrameCacheAble>(frame);
|
||||
}
|
||||
|
||||
FrameStamp::FrameStamp(Frame::Ptr frame, Stamp &stamp, int modify_stamp)
|
||||
{
|
||||
FrameStamp::FrameStamp(Frame::Ptr frame) {
|
||||
setIndex(frame->getIndex());
|
||||
_frame = std::move(frame);
|
||||
}
|
||||
|
||||
FrameStamp::FrameStamp(Frame::Ptr frame, Stamp &stamp, int modify_stamp)
|
||||
: FrameStamp(std::move(frame)) {
|
||||
// kModifyStampSystem时采用系统时间戳,kModifyStampRelative采用相对时间戳 [AUTO-TRANSLATED:54dd5685]
|
||||
// When using kModifyStampSystem, the system timestamp is used, and when using kModifyStampRelative, the relative timestamp is used.
|
||||
stamp.revise(_frame->dts(), _frame->pts(), _dts, _pts, modify_stamp == ProtocolOption::kModifyStampSystem);
|
||||
}
|
||||
|
||||
void FrameStamp::setStamp(int64_t dts, int64_t pts) {
|
||||
_dts = dts;
|
||||
_pts = pts;
|
||||
}
|
||||
|
||||
|
||||
TrackType getTrackType(CodecId codecId) {
|
||||
switch (codecId) {
|
||||
#define XX(name, type, value, str, mpeg_id, mp4_id) case name : return type;
|
||||
|
@ -524,6 +524,7 @@ private:
|
||||
class FrameStamp : public Frame {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<FrameStamp>;
|
||||
FrameStamp(Frame::Ptr frame);
|
||||
FrameStamp(Frame::Ptr frame, Stamp &stamp, int modify_stamp);
|
||||
~FrameStamp() override {}
|
||||
|
||||
@ -538,6 +539,7 @@ public:
|
||||
char *data() const override { return _frame->data(); }
|
||||
size_t size() const override { return _frame->size(); }
|
||||
CodecId getCodecId() const override { return _frame->getCodecId(); }
|
||||
void setStamp(int64_t dts, int64_t pts);
|
||||
|
||||
private:
|
||||
int64_t _dts;
|
||||
|
@ -9,7 +9,10 @@
|
||||
*/
|
||||
|
||||
#ifdef ENABLE_MP4
|
||||
|
||||
#include <algorithm>
|
||||
#include "MP4Demuxer.h"
|
||||
#include "Util/File.h"
|
||||
#include "Util/logger.h"
|
||||
#include "Extension/Factory.h"
|
||||
|
||||
@ -189,5 +192,90 @@ uint64_t MP4Demuxer::getDurationMS() const {
|
||||
return _duration_ms;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void MultiMP4Demuxer::openMP4(const string &files_string) {
|
||||
std::vector<std::string> files;
|
||||
if (File::is_dir(files_string)) {
|
||||
File::scanDir(files_string, [&](const string &path, bool is_dir) {
|
||||
if (!is_dir) {
|
||||
files.emplace_back(path);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
std::sort(files.begin(), files.end());
|
||||
} else {
|
||||
files = split(files_string, ";");
|
||||
}
|
||||
|
||||
uint64_t duration_ms = 0;
|
||||
for (auto &file : files) {
|
||||
auto demuxer = std::make_shared<MP4Demuxer>();
|
||||
demuxer->openMP4(file);
|
||||
_demuxers.emplace(duration_ms, demuxer);
|
||||
duration_ms += demuxer->getDurationMS();
|
||||
}
|
||||
CHECK(!_demuxers.empty());
|
||||
_it = _demuxers.begin();
|
||||
for (auto &track : _it->second->getTracks(false)) {
|
||||
_tracks.emplace(track->getIndex(), track->clone());
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t MultiMP4Demuxer::getDurationMS() const {
|
||||
return _demuxers.empty() ? 0 : _demuxers.rbegin()->first + _demuxers.rbegin()->second->getDurationMS();
|
||||
}
|
||||
|
||||
void MultiMP4Demuxer::closeMP4() {
|
||||
_demuxers.clear();
|
||||
_it = _demuxers.end();
|
||||
_tracks.clear();
|
||||
}
|
||||
|
||||
int64_t MultiMP4Demuxer::seekTo(int64_t stamp_ms) {
|
||||
if (stamp_ms >= (int64_t)getDurationMS()) {
|
||||
return -1;
|
||||
}
|
||||
_it = std::prev(_demuxers.upper_bound(stamp_ms));
|
||||
return _it->first + _it->second->seekTo(stamp_ms - _it->first);
|
||||
}
|
||||
|
||||
Frame::Ptr MultiMP4Demuxer::readFrame(bool &keyFrame, bool &eof) {
|
||||
for (;;) {
|
||||
auto ret = _it->second->readFrame(keyFrame, eof);
|
||||
if (ret) {
|
||||
auto it = _tracks.find(ret->getIndex());
|
||||
if (it != _tracks.end()) {
|
||||
auto ret2 = std::make_shared<FrameStamp>(ret);
|
||||
ret2->setStamp(_it->first + ret->dts(), _it->first + ret->pts());
|
||||
ret = std::move(ret2);
|
||||
it->second->inputFrame(ret);
|
||||
}
|
||||
}
|
||||
if (eof && _it != _demuxers.end()) {
|
||||
// 切换到下一个文件
|
||||
if (++_it == _demuxers.end()) {
|
||||
// 已经是最后一个文件了
|
||||
eof = true;
|
||||
return nullptr;
|
||||
}
|
||||
// 下一个文件从头开始播放
|
||||
_it->second->seekTo(0);
|
||||
continue;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Track::Ptr> MultiMP4Demuxer::getTracks(bool trackReady) const {
|
||||
std::vector<Track::Ptr> ret;
|
||||
for (auto &pr : _tracks) {
|
||||
if (!trackReady || pr.second->ready()) {
|
||||
ret.emplace_back(pr.second);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}//namespace mediakit
|
||||
#endif// ENABLE_MP4
|
||||
|
@ -11,9 +11,12 @@
|
||||
#ifndef ZLMEDIAKIT_MP4DEMUXER_H
|
||||
#define ZLMEDIAKIT_MP4DEMUXER_H
|
||||
#ifdef ENABLE_MP4
|
||||
|
||||
#include <map>
|
||||
#include "MP4.h"
|
||||
#include "Extension/Track.h"
|
||||
#include "Util/ResourcePool.h"
|
||||
|
||||
namespace mediakit {
|
||||
|
||||
class MP4Demuxer : public TrackSource {
|
||||
@ -103,6 +106,56 @@ private:
|
||||
toolkit::ResourcePool<toolkit::BufferRaw> _buffer_pool;
|
||||
};
|
||||
|
||||
class MultiMP4Demuxer : public TrackSource {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<MultiMP4Demuxer>;
|
||||
|
||||
~MultiMP4Demuxer() override = default;
|
||||
|
||||
/**
|
||||
* 批量打开mp4文件,把多个文件当做一个mp4看待
|
||||
* @param file 多个mp4文件路径,以分号分隔; 或者包含多个mp4文件的文件夹
|
||||
*/
|
||||
void openMP4(const std::string &file);
|
||||
|
||||
/**
|
||||
* @brief 批量关闭 mp4 文件
|
||||
*/
|
||||
void closeMP4();
|
||||
|
||||
/**
|
||||
* 移动总体时间轴至某处
|
||||
* @param stamp_ms 预期的时间轴总体长度位置,单位毫秒
|
||||
* @return 时间轴总体长度位置
|
||||
*/
|
||||
int64_t seekTo(int64_t stamp_ms);
|
||||
|
||||
/**
|
||||
* 读取一帧数据
|
||||
* @param keyFrame 是否为关键帧
|
||||
* @param eof 是否所有文件读取完毕
|
||||
* @return 帧数据,可能为空
|
||||
*/
|
||||
Frame::Ptr readFrame(bool &keyFrame, bool &eof);
|
||||
|
||||
/**
|
||||
* 获取第一个文件所有Track信息
|
||||
* @param trackReady 是否要求track为就绪状态
|
||||
* @return 第一个文件所有Track信息
|
||||
*/
|
||||
std::vector<Track::Ptr> getTracks(bool trackReady) const override;
|
||||
|
||||
/**
|
||||
* 获取文件总长度
|
||||
* @return 文件总长度,单位毫秒
|
||||
*/
|
||||
uint64_t getDurationMS() const;
|
||||
|
||||
private:
|
||||
std::map<int, Track::Ptr> _tracks;
|
||||
std::map<uint64_t, MP4Demuxer::Ptr>::iterator _it;
|
||||
std::map<uint64_t, MP4Demuxer::Ptr> _demuxers;
|
||||
};
|
||||
|
||||
}//namespace mediakit
|
||||
#endif//ENABLE_MP4
|
||||
|
@ -54,7 +54,7 @@ void MP4Reader::setup(const MediaTuple &tuple, const std::string &file_path, con
|
||||
_file_path = File::absolutePath(_file_path, recordPath);
|
||||
}
|
||||
|
||||
_demuxer = std::make_shared<MP4Demuxer>();
|
||||
_demuxer = std::make_shared<MultiMP4Demuxer>();
|
||||
_demuxer->openMP4(_file_path);
|
||||
|
||||
if (tuple.stream.empty()) {
|
||||
@ -164,7 +164,7 @@ void MP4Reader::startReadMP4(uint64_t sample_ms, bool ref_self, bool file_repeat
|
||||
_file_repeat = file_repeat;
|
||||
}
|
||||
|
||||
const MP4Demuxer::Ptr &MP4Reader::getDemuxer() const {
|
||||
const MultiMP4Demuxer::Ptr &MP4Reader::getDemuxer() const {
|
||||
return _demuxer;
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ public:
|
||||
|
||||
* [AUTO-TRANSLATED:4f0dfc29]
|
||||
*/
|
||||
const MP4Demuxer::Ptr& getDemuxer() const;
|
||||
const MultiMP4Demuxer::Ptr& getDemuxer() const;
|
||||
|
||||
private:
|
||||
//MediaSourceEvent override
|
||||
@ -100,7 +100,7 @@ private:
|
||||
std::recursive_mutex _mtx;
|
||||
toolkit::Ticker _seek_ticker;
|
||||
toolkit::Timer::Ptr _timer;
|
||||
MP4Demuxer::Ptr _demuxer;
|
||||
MultiMP4Demuxer::Ptr _demuxer;
|
||||
MultiMediaSourceMuxer::Ptr _muxer;
|
||||
toolkit::EventPoller::Ptr _poller;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user