mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-07-04 01:37:33 +08:00
同时主要优化点包括: 1、编译宏特性开关优化。 2、转协议复用器相关创建代码移动至Recorder类。 3、转协议复用器onAllTrackReady函数修改为addTrackCompleted。 4、startRecord/stopRecord/isRecording接口新增支持ts/fmp4/hls-fmp4协议。 Co-authored-by: xia-chu <771730766@qq.com> Co-authored-by: linxiaoyan87 <linxiaoyan87@foxmail.com>
This commit is contained in:
@@ -59,6 +59,7 @@ ProtocolOption::ProtocolOption() {
|
||||
GET_CONFIG(uint32_t, s_continue_push_ms, Protocol::kContinuePushMS);
|
||||
|
||||
GET_CONFIG(bool, s_enable_hls, Protocol::kEnableHls);
|
||||
GET_CONFIG(bool, s_enable_hls_fmp4, Protocol::kEnableHlsFmp4);
|
||||
GET_CONFIG(bool, s_enable_mp4, Protocol::kEnableMP4);
|
||||
GET_CONFIG(bool, s_enable_rtsp, Protocol::kEnableRtsp);
|
||||
GET_CONFIG(bool, s_enable_rtmp, Protocol::kEnableRtmp);
|
||||
@@ -83,6 +84,7 @@ ProtocolOption::ProtocolOption() {
|
||||
continue_push_ms = s_continue_push_ms;
|
||||
|
||||
enable_hls = s_enable_hls;
|
||||
enable_hls_fmp4 = s_enable_hls_fmp4;
|
||||
enable_mp4 = s_enable_mp4;
|
||||
enable_rtsp = s_enable_rtsp;
|
||||
enable_rtmp = s_enable_rtmp;
|
||||
|
||||
@@ -151,8 +151,10 @@ public:
|
||||
//断连续推延时,单位毫秒,默认采用配置文件
|
||||
uint32_t continue_push_ms;
|
||||
|
||||
//是否开启转换为hls
|
||||
//是否开启转换为hls(mpegts)
|
||||
bool enable_hls;
|
||||
//是否开启转换为hls(fmp4)
|
||||
bool enable_hls_fmp4;
|
||||
//是否开启MP4录制
|
||||
bool enable_mp4;
|
||||
//是否开启转换为rtsp/webrtc
|
||||
@@ -194,6 +196,7 @@ public:
|
||||
GET_OPT_VALUE(continue_push_ms);
|
||||
|
||||
GET_OPT_VALUE(enable_hls);
|
||||
GET_OPT_VALUE(enable_hls_fmp4);
|
||||
GET_OPT_VALUE(enable_mp4);
|
||||
GET_OPT_VALUE(enable_rtsp);
|
||||
GET_OPT_VALUE(enable_rtmp);
|
||||
|
||||
@@ -37,6 +37,7 @@ static std::shared_ptr<MediaSinkInterface> makeRecorder(MediaSource &sender, con
|
||||
for (auto &track : tracks) {
|
||||
recorder->addTrack(track);
|
||||
}
|
||||
recorder->addTrackCompleted();
|
||||
return recorder;
|
||||
}
|
||||
|
||||
@@ -97,17 +98,18 @@ MultiMediaSourceMuxer::MultiMediaSourceMuxer(const MediaTuple& tuple, float dur_
|
||||
if (option.enable_hls) {
|
||||
_hls = dynamic_pointer_cast<HlsRecorder>(Recorder::createRecorder(Recorder::type_hls, _tuple, option));
|
||||
}
|
||||
if (option.enable_hls_fmp4) {
|
||||
_hls_fmp4 = dynamic_pointer_cast<HlsFMP4Recorder>(Recorder::createRecorder(Recorder::type_hls_fmp4, _tuple, option));
|
||||
}
|
||||
if (option.enable_mp4) {
|
||||
_mp4 = Recorder::createRecorder(Recorder::type_mp4, _tuple, option);
|
||||
}
|
||||
if (option.enable_ts) {
|
||||
_ts = std::make_shared<TSMediaSourceMuxer>(_tuple, option);
|
||||
_ts = dynamic_pointer_cast<TSMediaSourceMuxer>(Recorder::createRecorder(Recorder::type_ts, _tuple, option));
|
||||
}
|
||||
#if defined(ENABLE_MP4)
|
||||
if (option.enable_fmp4) {
|
||||
_fmp4 = std::make_shared<FMP4MediaSourceMuxer>(_tuple, option);
|
||||
_fmp4 = dynamic_pointer_cast<FMP4MediaSourceMuxer>(Recorder::createRecorder(Recorder::type_fmp4, _tuple, option));
|
||||
}
|
||||
#endif
|
||||
|
||||
//音频相关设置
|
||||
enableAudio(option.enable_audio);
|
||||
@@ -128,14 +130,14 @@ void MultiMediaSourceMuxer::setMediaListener(const std::weak_ptr<MediaSourceEven
|
||||
if (_ts) {
|
||||
_ts->setListener(self);
|
||||
}
|
||||
#if defined(ENABLE_MP4)
|
||||
if (_fmp4) {
|
||||
_fmp4->setListener(self);
|
||||
}
|
||||
#endif
|
||||
auto hls = _hls;
|
||||
if (hls) {
|
||||
hls->setListener(self);
|
||||
if (_hls_fmp4) {
|
||||
_hls_fmp4->setListener(self);
|
||||
}
|
||||
if (_hls) {
|
||||
_hls->setListener(self);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,15 +146,13 @@ void MultiMediaSourceMuxer::setTrackListener(const std::weak_ptr<Listener> &list
|
||||
}
|
||||
|
||||
int MultiMediaSourceMuxer::totalReaderCount() const {
|
||||
auto hls = _hls;
|
||||
return (_rtsp ? _rtsp->readerCount() : 0) +
|
||||
(_rtmp ? _rtmp->readerCount() : 0) +
|
||||
(_ts ? _ts->readerCount() : 0) +
|
||||
#if defined(ENABLE_MP4)
|
||||
(_fmp4 ? _fmp4->readerCount() : 0) +
|
||||
#endif
|
||||
(_mp4 ? _option.mp4_as_player : 0) +
|
||||
(hls ? hls->readerCount() : 0) +
|
||||
(_hls ? _hls->readerCount() : 0) +
|
||||
(_hls_fmp4 ? _hls_fmp4->readerCount() : 0) +
|
||||
(_ring ? _ring->readerCount() : 0);
|
||||
}
|
||||
|
||||
@@ -180,6 +180,7 @@ int MultiMediaSourceMuxer::totalReaderCount(MediaSource &sender) {
|
||||
|
||||
//此函数可能跨线程调用
|
||||
bool MultiMediaSourceMuxer::setupRecord(MediaSource &sender, Recorder::type type, bool start, const string &custom_path, size_t max_second) {
|
||||
CHECK(getOwnerPoller(MediaSource::NullMediaSource())->isCurrentThread(), "Can only call setupRecord in it's owner poller");
|
||||
onceToken token(nullptr, [&]() {
|
||||
if (_option.mp4_as_player && type == Recorder::type_mp4) {
|
||||
//开启关闭mp4录制,触发观看人数变化相关事件
|
||||
@@ -215,19 +216,59 @@ bool MultiMediaSourceMuxer::setupRecord(MediaSource &sender, Recorder::type type
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case Recorder::type_hls_fmp4: {
|
||||
if (start && !_hls_fmp4) {
|
||||
//开始录制
|
||||
_option.hls_save_path = custom_path;
|
||||
auto hls = dynamic_pointer_cast<HlsFMP4Recorder>(makeRecorder(sender, getTracks(), type, _option));
|
||||
if (hls) {
|
||||
//设置HlsMediaSource的事件监听器
|
||||
hls->setListener(shared_from_this());
|
||||
}
|
||||
_hls_fmp4 = hls;
|
||||
} else if (!start && _hls_fmp4) {
|
||||
//停止录制
|
||||
_hls_fmp4 = nullptr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case Recorder::type_fmp4: {
|
||||
if (start && !_fmp4) {
|
||||
auto fmp4 = dynamic_pointer_cast<FMP4MediaSourceMuxer>(makeRecorder(sender, getTracks(), type, _option));
|
||||
if (fmp4) {
|
||||
fmp4->setListener(shared_from_this());
|
||||
}
|
||||
_fmp4 = fmp4;
|
||||
} else if (!start && _fmp4) {
|
||||
_fmp4 = nullptr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
case Recorder::type_ts: {
|
||||
if (start && !_ts) {
|
||||
auto ts = dynamic_pointer_cast<TSMediaSourceMuxer>(makeRecorder(sender, getTracks(), type, _option));
|
||||
if (ts) {
|
||||
ts->setListener(shared_from_this());
|
||||
}
|
||||
_ts = ts;
|
||||
} else if (!start && _ts) {
|
||||
_ts = nullptr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
default : return false;
|
||||
}
|
||||
}
|
||||
|
||||
//此函数可能跨线程调用
|
||||
bool MultiMediaSourceMuxer::isRecording(MediaSource &sender, Recorder::type type) {
|
||||
switch (type){
|
||||
case Recorder::type_hls :
|
||||
return !!_hls;
|
||||
case Recorder::type_mp4 :
|
||||
return !!_mp4;
|
||||
default:
|
||||
return false;
|
||||
switch (type) {
|
||||
case Recorder::type_hls: return !!_hls;
|
||||
case Recorder::type_mp4: return !!_mp4;
|
||||
case Recorder::type_hls_fmp4: return !!_hls_fmp4;
|
||||
case Recorder::type_fmp4: return !!_fmp4;
|
||||
case Recorder::type_ts: return !!_ts;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,20 +368,17 @@ bool MultiMediaSourceMuxer::onTrackReady(const Track::Ptr &track) {
|
||||
if (_ts) {
|
||||
ret = _ts->addTrack(track) ? true : ret;
|
||||
}
|
||||
#if defined(ENABLE_MP4)
|
||||
if (_fmp4) {
|
||||
ret = _fmp4->addTrack(track) ? true : ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
//拷贝智能指针,目的是为了防止跨线程调用设置录像相关api导致的线程竞争问题
|
||||
auto hls = _hls;
|
||||
if (hls) {
|
||||
ret = hls->addTrack(track) ? true : ret;
|
||||
if (_hls) {
|
||||
ret = _hls->addTrack(track) ? true : ret;
|
||||
}
|
||||
auto mp4 = _mp4;
|
||||
if (mp4) {
|
||||
ret = mp4->addTrack(track) ? true : ret;
|
||||
if (_hls_fmp4) {
|
||||
ret = _hls_fmp4->addTrack(track) ? true : ret;
|
||||
}
|
||||
if (_mp4) {
|
||||
ret = _mp4->addTrack(track) ? true : ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -350,16 +388,27 @@ void MultiMediaSourceMuxer::onAllTrackReady() {
|
||||
setMediaListener(getDelegate());
|
||||
|
||||
if (_rtmp) {
|
||||
_rtmp->onAllTrackReady();
|
||||
_rtmp->addTrackCompleted();
|
||||
}
|
||||
if (_rtsp) {
|
||||
_rtsp->onAllTrackReady();
|
||||
_rtsp->addTrackCompleted();
|
||||
}
|
||||
if (_ts) {
|
||||
_ts->addTrackCompleted();
|
||||
}
|
||||
if (_mp4) {
|
||||
_mp4->addTrackCompleted();
|
||||
}
|
||||
#if defined(ENABLE_MP4)
|
||||
if (_fmp4) {
|
||||
_fmp4->onAllTrackReady();
|
||||
_fmp4->addTrackCompleted();
|
||||
}
|
||||
#endif
|
||||
if (_hls) {
|
||||
_hls->addTrackCompleted();
|
||||
}
|
||||
if (_hls_fmp4) {
|
||||
_hls_fmp4->addTrackCompleted();
|
||||
}
|
||||
|
||||
auto listener = _track_listener.lock();
|
||||
if (listener) {
|
||||
listener->onAllTrackReady();
|
||||
@@ -407,21 +456,17 @@ void MultiMediaSourceMuxer::resetTracks() {
|
||||
if (_ts) {
|
||||
_ts->resetTracks();
|
||||
}
|
||||
#if defined(ENABLE_MP4)
|
||||
if (_fmp4) {
|
||||
_fmp4->resetTracks();
|
||||
}
|
||||
#endif
|
||||
|
||||
//拷贝智能指针,目的是为了防止跨线程调用设置录像相关api导致的线程竞争问题
|
||||
auto hls = _hls;
|
||||
if (hls) {
|
||||
hls->resetTracks();
|
||||
if (_hls_fmp4) {
|
||||
_hls_fmp4->resetTracks();
|
||||
}
|
||||
|
||||
auto mp4 = _mp4;
|
||||
if (mp4) {
|
||||
mp4->resetTracks();
|
||||
if (_hls) {
|
||||
_hls->resetTracks();
|
||||
}
|
||||
if (_mp4) {
|
||||
_mp4->resetTracks();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,23 +488,20 @@ bool MultiMediaSourceMuxer::onTrackFrame(const Frame::Ptr &frame_in) {
|
||||
ret = _ts->inputFrame(frame) ? true : ret;
|
||||
}
|
||||
|
||||
//拷贝智能指针,目的是为了防止跨线程调用设置录像相关api导致的线程竞争问题
|
||||
//此处使用智能指针拷贝来确保线程安全,比互斥锁性能更优
|
||||
auto hls = _hls;
|
||||
if (hls) {
|
||||
ret = hls->inputFrame(frame) ? true : ret;
|
||||
}
|
||||
auto mp4 = _mp4;
|
||||
if (mp4) {
|
||||
ret = mp4->inputFrame(frame) ? true : ret;
|
||||
if (_hls) {
|
||||
ret = _hls->inputFrame(frame) ? true : ret;
|
||||
}
|
||||
|
||||
#if defined(ENABLE_MP4)
|
||||
if (_hls_fmp4) {
|
||||
ret = _hls_fmp4->inputFrame(frame) ? true : ret;
|
||||
}
|
||||
|
||||
if (_mp4) {
|
||||
ret = _mp4->inputFrame(frame) ? true : ret;
|
||||
}
|
||||
if (_fmp4) {
|
||||
ret = _fmp4->inputFrame(frame) ? true : ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_ring) {
|
||||
if (frame->getTrackType() == TrackVideo) {
|
||||
// 视频时,遇到第一帧配置帧或关键帧则标记为gop开始处
|
||||
@@ -481,15 +523,14 @@ bool MultiMediaSourceMuxer::isEnabled(){
|
||||
if (!_is_enable || _last_check.elapsedTime() > stream_none_reader_delay_ms) {
|
||||
//无人观看时,每次检查是否真的无人观看
|
||||
//有人观看时,则延迟一定时间检查一遍是否无人观看了(节省性能)
|
||||
auto hls = _hls;
|
||||
_is_enable = (_rtmp ? _rtmp->isEnabled() : false) ||
|
||||
(_rtsp ? _rtsp->isEnabled() : false) ||
|
||||
(_ts ? _ts->isEnabled() : false) ||
|
||||
#if defined(ENABLE_MP4)
|
||||
(_fmp4 ? _fmp4->isEnabled() : false) ||
|
||||
#endif
|
||||
(_ring ? (bool)_ring->readerCount() : false) ||
|
||||
(hls ? hls->isEnabled() : false) || _mp4;
|
||||
(_hls ? _hls->isEnabled() : false) ||
|
||||
(_hls_fmp4 ? _hls_fmp4->isEnabled() : false) ||
|
||||
_mp4;
|
||||
|
||||
if (_is_enable) {
|
||||
//无人观看时,不刷新计时器,因为无人观看时每次都会检查一遍,所以刷新计数器无意义且浪费cpu
|
||||
|
||||
@@ -164,18 +164,14 @@ private:
|
||||
toolkit::Ticker _last_check;
|
||||
Stamp _stamp[2];
|
||||
std::weak_ptr<Listener> _track_listener;
|
||||
#if defined(ENABLE_RTPPROXY)
|
||||
std::unordered_map<std::string, RingType::RingReader::Ptr> _rtp_sender;
|
||||
#endif //ENABLE_RTPPROXY
|
||||
|
||||
#if defined(ENABLE_MP4)
|
||||
FMP4MediaSourceMuxer::Ptr _fmp4;
|
||||
#endif
|
||||
RtmpMediaSourceMuxer::Ptr _rtmp;
|
||||
RtspMediaSourceMuxer::Ptr _rtsp;
|
||||
TSMediaSourceMuxer::Ptr _ts;
|
||||
MediaSinkInterface::Ptr _mp4;
|
||||
HlsRecorder::Ptr _hls;
|
||||
HlsFMP4Recorder::Ptr _hls_fmp4;
|
||||
toolkit::EventPoller::Ptr _poller;
|
||||
RingType::Ptr _ring;
|
||||
|
||||
|
||||
@@ -102,6 +102,7 @@ const string kAddMuteAudio = PROTOCOL_FIELD "add_mute_audio";
|
||||
const string kContinuePushMS = PROTOCOL_FIELD "continue_push_ms";
|
||||
|
||||
const string kEnableHls = PROTOCOL_FIELD "enable_hls";
|
||||
const string kEnableHlsFmp4 = PROTOCOL_FIELD "enable_hls_fmp4";
|
||||
const string kEnableMP4 = PROTOCOL_FIELD "enable_mp4";
|
||||
const string kEnableRtsp = PROTOCOL_FIELD "enable_rtsp";
|
||||
const string kEnableRtmp = PROTOCOL_FIELD "enable_rtmp";
|
||||
@@ -127,6 +128,7 @@ static onceToken token([]() {
|
||||
mINI::Instance()[kContinuePushMS] = 15000;
|
||||
|
||||
mINI::Instance()[kEnableHls] = 1;
|
||||
mINI::Instance()[kEnableHlsFmp4] = 0;
|
||||
mINI::Instance()[kEnableMP4] = 0;
|
||||
mINI::Instance()[kEnableRtsp] = 1;
|
||||
mINI::Instance()[kEnableRtmp] = 1;
|
||||
|
||||
@@ -193,8 +193,10 @@ extern const std::string kAddMuteAudio;
|
||||
//断连续推延时,单位毫秒,默认采用配置文件
|
||||
extern const std::string kContinuePushMS;
|
||||
|
||||
//是否开启转换为hls
|
||||
//是否开启转换为hls(mpegts)
|
||||
extern const std::string kEnableHls;
|
||||
//是否开启转换为hls(fmp4)
|
||||
extern const std::string kEnableHlsFmp4;
|
||||
//是否开启MP4录制
|
||||
extern const std::string kEnableMP4;
|
||||
//是否开启转换为rtsp/webrtc
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
#define HLS_SCHEMA "hls"
|
||||
#define TS_SCHEMA "ts"
|
||||
#define FMP4_SCHEMA "fmp4"
|
||||
#define HLS_FMP4_SCHEMA "hls.fmp4"
|
||||
#define SRT_SCHEMA "srt"
|
||||
#define DEFAULT_VHOST "__defaultVhost__"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user