Compare commits

..

3 Commits

Author SHA1 Message Date
alex
0f408ccdaf
Merge 90bd28249e into 61a93fab6a 2024-10-15 15:07:21 +08:00
xia-chu
61a93fab6a 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
2024-10-13 02:09:39 +08:00
xia-chu
e4025a6811 Improve timestamp corrector 2024-10-13 00:23:34 +08:00
8 changed files with 184 additions and 8 deletions

View File

@ -27,6 +27,12 @@ DeltaStamp::DeltaStamp() {
_max_delta = 300; _max_delta = 300;
} }
void DeltaStamp::reset() {
_last_stamp = 0;
_relative_stamp = 0;
_last_delta = 1;
}
int64_t DeltaStamp::relativeStamp(int64_t stamp, bool enable_rollback) { int64_t DeltaStamp::relativeStamp(int64_t stamp, bool enable_rollback) {
_relative_stamp += deltaStamp(stamp, enable_rollback); _relative_stamp += deltaStamp(stamp, enable_rollback);
return _relative_stamp; return _relative_stamp;
@ -55,8 +61,9 @@ int64_t DeltaStamp::deltaStamp(int64_t stamp, bool enable_rollback) {
// In the live broadcast case, the timestamp increment must not be greater than MAX_DELTA_STAMP, otherwise the relative timestamp is forced to add 1 // In the live broadcast case, the timestamp increment must not be greater than MAX_DELTA_STAMP, otherwise the relative timestamp is forced to add 1
if (ret > _max_delta) { if (ret > _max_delta) {
needSync(); needSync();
return 1; return _last_delta;
} }
_last_delta = ret;
return ret; return ret;
} }
@ -67,7 +74,7 @@ int64_t DeltaStamp::deltaStamp(int64_t stamp, bool enable_rollback) {
// 不允许回退或者回退太多了, 强制时间戳加1 [AUTO-TRANSLATED:152f5ffa] // 不允许回退或者回退太多了, 强制时间戳加1 [AUTO-TRANSLATED:152f5ffa]
// Not allowed to retreat or retreat too much, force the timestamp to add 1 // Not allowed to retreat or retreat too much, force the timestamp to add 1
needSync(); needSync();
return 1; return _last_delta;
} }
return ret; return ret;
} }
@ -93,6 +100,14 @@ void Stamp::enableRollback(bool flag) {
_enable_rollback = flag; _enable_rollback = flag;
} }
void Stamp::reset() {
DeltaStamp::reset();
_relative_stamp = 0;
_last_dts_in = 0;
_last_dts_out = 0;
_last_pts_out = 0;
}
// 限制dts回退 [AUTO-TRANSLATED:6bc53b31] // 限制dts回退 [AUTO-TRANSLATED:6bc53b31]
// Limit dts retreat // Limit dts retreat
void Stamp::revise(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out, bool modifyStamp) { void Stamp::revise(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out, bool modifyStamp) {

View File

@ -42,11 +42,15 @@ public:
// Set the maximum allowed rollback or jump amplitude // Set the maximum allowed rollback or jump amplitude
void setMaxDelta(size_t max_delta); void setMaxDelta(size_t max_delta);
// 重置
void reset();
protected: protected:
virtual void needSync() {} virtual void needSync() {}
protected: protected:
int _max_delta; int _max_delta;
int _last_delta = 1;
int64_t _last_stamp = 0; int64_t _last_stamp = 0;
int64_t _relative_stamp = 0; int64_t _relative_stamp = 0;
}; };
@ -123,6 +127,11 @@ public:
*/ */
void enableRollback(bool flag); void enableRollback(bool flag);
/**
*
*/
void reset();
private: private:
// 主要实现音视频时间戳同步功能 [AUTO-TRANSLATED:45863fce] // 主要实现音视频时间戳同步功能 [AUTO-TRANSLATED:45863fce]
// Mainly implements audio and video timestamp synchronization function // Mainly implements audio and video timestamp synchronization function

View File

@ -38,15 +38,24 @@ Frame::Ptr Frame::getCacheAbleFrame(const Frame::Ptr &frame){
return std::make_shared<FrameCacheAble>(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()); setIndex(frame->getIndex());
_frame = std::move(frame); _frame = std::move(frame);
}
FrameStamp::FrameStamp(Frame::Ptr frame, Stamp &stamp, int modify_stamp)
: FrameStamp(std::move(frame)) {
// kModifyStampSystem时采用系统时间戳kModifyStampRelative采用相对时间戳 [AUTO-TRANSLATED:54dd5685] // kModifyStampSystem时采用系统时间戳kModifyStampRelative采用相对时间戳 [AUTO-TRANSLATED:54dd5685]
// When using kModifyStampSystem, the system timestamp is used, and when using kModifyStampRelative, the relative timestamp is used. // 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); 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) { TrackType getTrackType(CodecId codecId) {
switch (codecId) { switch (codecId) {
#define XX(name, type, value, str, mpeg_id, mp4_id) case name : return type; #define XX(name, type, value, str, mpeg_id, mp4_id) case name : return type;

View File

@ -524,6 +524,7 @@ private:
class FrameStamp : public Frame { class FrameStamp : public Frame {
public: public:
using Ptr = std::shared_ptr<FrameStamp>; using Ptr = std::shared_ptr<FrameStamp>;
FrameStamp(Frame::Ptr frame);
FrameStamp(Frame::Ptr frame, Stamp &stamp, int modify_stamp); FrameStamp(Frame::Ptr frame, Stamp &stamp, int modify_stamp);
~FrameStamp() override {} ~FrameStamp() override {}
@ -538,6 +539,7 @@ public:
char *data() const override { return _frame->data(); } char *data() const override { return _frame->data(); }
size_t size() const override { return _frame->size(); } size_t size() const override { return _frame->size(); }
CodecId getCodecId() const override { return _frame->getCodecId(); } CodecId getCodecId() const override { return _frame->getCodecId(); }
void setStamp(int64_t dts, int64_t pts);
private: private:
int64_t _dts; int64_t _dts;

View File

@ -9,7 +9,10 @@
*/ */
#ifdef ENABLE_MP4 #ifdef ENABLE_MP4
#include <algorithm>
#include "MP4Demuxer.h" #include "MP4Demuxer.h"
#include "Util/File.h"
#include "Util/logger.h" #include "Util/logger.h"
#include "Extension/Factory.h" #include "Extension/Factory.h"
@ -189,5 +192,90 @@ uint64_t MP4Demuxer::getDurationMS() const {
return _duration_ms; 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 }//namespace mediakit
#endif// ENABLE_MP4 #endif// ENABLE_MP4

View File

@ -11,9 +11,12 @@
#ifndef ZLMEDIAKIT_MP4DEMUXER_H #ifndef ZLMEDIAKIT_MP4DEMUXER_H
#define ZLMEDIAKIT_MP4DEMUXER_H #define ZLMEDIAKIT_MP4DEMUXER_H
#ifdef ENABLE_MP4 #ifdef ENABLE_MP4
#include <map>
#include "MP4.h" #include "MP4.h"
#include "Extension/Track.h" #include "Extension/Track.h"
#include "Util/ResourcePool.h" #include "Util/ResourcePool.h"
namespace mediakit { namespace mediakit {
class MP4Demuxer : public TrackSource { class MP4Demuxer : public TrackSource {
@ -103,6 +106,56 @@ private:
toolkit::ResourcePool<toolkit::BufferRaw> _buffer_pool; 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 }//namespace mediakit
#endif//ENABLE_MP4 #endif//ENABLE_MP4

View File

@ -54,7 +54,7 @@ void MP4Reader::setup(const MediaTuple &tuple, const std::string &file_path, con
_file_path = File::absolutePath(_file_path, recordPath); _file_path = File::absolutePath(_file_path, recordPath);
} }
_demuxer = std::make_shared<MP4Demuxer>(); _demuxer = std::make_shared<MultiMP4Demuxer>();
_demuxer->openMP4(_file_path); _demuxer->openMP4(_file_path);
if (tuple.stream.empty()) { 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; _file_repeat = file_repeat;
} }
const MP4Demuxer::Ptr &MP4Reader::getDemuxer() const { const MultiMP4Demuxer::Ptr &MP4Reader::getDemuxer() const {
return _demuxer; return _demuxer;
} }

View File

@ -68,7 +68,7 @@ public:
* [AUTO-TRANSLATED:4f0dfc29] * [AUTO-TRANSLATED:4f0dfc29]
*/ */
const MP4Demuxer::Ptr& getDemuxer() const; const MultiMP4Demuxer::Ptr& getDemuxer() const;
private: private:
//MediaSourceEvent override //MediaSourceEvent override
@ -100,7 +100,7 @@ private:
std::recursive_mutex _mtx; std::recursive_mutex _mtx;
toolkit::Ticker _seek_ticker; toolkit::Ticker _seek_ticker;
toolkit::Timer::Ptr _timer; toolkit::Timer::Ptr _timer;
MP4Demuxer::Ptr _demuxer; MultiMP4Demuxer::Ptr _demuxer;
MultiMediaSourceMuxer::Ptr _muxer; MultiMediaSourceMuxer::Ptr _muxer;
toolkit::EventPoller::Ptr _poller; toolkit::EventPoller::Ptr _poller;
}; };