2020-04-05 09:26:29 +08:00
|
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
|
|
|
|
*
|
2021-01-17 18:31:50 +08:00
|
|
|
|
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
2020-04-05 09:26:29 +08:00
|
|
|
|
*
|
|
|
|
|
* Use of this source code is governed by MIT license that can be found in the
|
|
|
|
|
* LICENSE file in the root of the source tree. All contributing project authors
|
|
|
|
|
* may be found in the AUTHORS file in the root of the source tree.
|
|
|
|
|
*/
|
|
|
|
|
|
2020-09-12 19:20:18 +08:00
|
|
|
|
#include <math.h>
|
2020-11-15 00:59:31 +08:00
|
|
|
|
#include "Common/config.h"
|
2020-04-05 09:26:29 +08:00
|
|
|
|
#include "MultiMediaSourceMuxer.h"
|
2021-01-23 09:44:37 +08:00
|
|
|
|
|
2022-02-02 20:34:50 +08:00
|
|
|
|
using namespace std;
|
|
|
|
|
using namespace toolkit;
|
|
|
|
|
|
2021-01-23 09:44:37 +08:00
|
|
|
|
namespace toolkit {
|
|
|
|
|
StatisticImp(mediakit::MultiMediaSourceMuxer);
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-05 09:26:29 +08:00
|
|
|
|
namespace mediakit {
|
|
|
|
|
|
2022-03-12 13:19:21 +08:00
|
|
|
|
ProtocolOption::ProtocolOption() {
|
2022-03-12 14:34:48 +08:00
|
|
|
|
GET_CONFIG(bool, s_to_hls, General::kPublishToHls);
|
|
|
|
|
GET_CONFIG(bool, s_to_mp4, General::kPublishToMP4);
|
|
|
|
|
GET_CONFIG(bool, s_enabel_audio, General::kEnableAudio);
|
|
|
|
|
GET_CONFIG(bool, s_add_mute_audio, General::kAddMuteAudio);
|
2022-08-16 11:47:24 +08:00
|
|
|
|
GET_CONFIG(bool, s_mp4_as_player, Record::kMP4AsPlayer);
|
2022-06-04 11:06:35 +08:00
|
|
|
|
GET_CONFIG(uint32_t, s_continue_push_ms, General::kContinuePushMS);
|
2022-09-03 09:54:09 +08:00
|
|
|
|
GET_CONFIG(bool, s_modify_stamp, General::kModifyStamp);
|
2022-06-04 11:06:35 +08:00
|
|
|
|
|
2022-03-12 14:34:48 +08:00
|
|
|
|
enable_hls = s_to_hls;
|
|
|
|
|
enable_mp4 = s_to_mp4;
|
|
|
|
|
enable_audio = s_enabel_audio;
|
|
|
|
|
add_mute_audio = s_add_mute_audio;
|
2022-06-04 11:06:35 +08:00
|
|
|
|
continue_push_ms = s_continue_push_ms;
|
2022-08-16 11:47:24 +08:00
|
|
|
|
mp4_as_player = s_mp4_as_player;
|
2022-09-03 09:54:09 +08:00
|
|
|
|
modify_stamp = s_modify_stamp;
|
2022-03-12 13:19:21 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-20 11:51:26 +08:00
|
|
|
|
static std::shared_ptr<MediaSinkInterface> makeRecorder(MediaSource &sender, const vector<Track::Ptr> &tracks, Recorder::type type, const string &custom_path, size_t max_second){
|
|
|
|
|
auto recorder = Recorder::createRecorder(type, sender.getVhost(), sender.getApp(), sender.getId(), custom_path, max_second);
|
|
|
|
|
for (auto &track : tracks) {
|
|
|
|
|
recorder->addTrack(track);
|
|
|
|
|
}
|
|
|
|
|
return recorder;
|
|
|
|
|
}
|
2020-09-06 17:52:07 +08:00
|
|
|
|
|
2021-07-20 11:51:26 +08:00
|
|
|
|
static string getTrackInfoStr(const TrackSource *track_src){
|
|
|
|
|
_StrPrinter codec_info;
|
|
|
|
|
auto tracks = track_src->getTracks(true);
|
|
|
|
|
for (auto &track : tracks) {
|
|
|
|
|
auto codec_type = track->getTrackType();
|
|
|
|
|
codec_info << track->getCodecName();
|
|
|
|
|
switch (codec_type) {
|
|
|
|
|
case TrackAudio : {
|
|
|
|
|
auto audio_track = dynamic_pointer_cast<AudioTrack>(track);
|
|
|
|
|
codec_info << "["
|
|
|
|
|
<< audio_track->getAudioSampleRate() << "/"
|
|
|
|
|
<< audio_track->getAudioChannel() << "/"
|
|
|
|
|
<< audio_track->getAudioSampleBit() << "] ";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case TrackVideo : {
|
|
|
|
|
auto video_track = dynamic_pointer_cast<VideoTrack>(track);
|
|
|
|
|
codec_info << "["
|
|
|
|
|
<< video_track->getVideoWidth() << "/"
|
|
|
|
|
<< video_track->getVideoHeight() << "/"
|
|
|
|
|
<< round(video_track->getVideoFps()) << "] ";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return std::move(codec_info);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-27 10:53:47 +08:00
|
|
|
|
const std::string &MultiMediaSourceMuxer::getVhost() const {
|
|
|
|
|
return _vhost;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::string &MultiMediaSourceMuxer::getApp() const {
|
|
|
|
|
return _app;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const std::string &MultiMediaSourceMuxer::getStreamId() const {
|
|
|
|
|
return _stream_id;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-12 13:19:21 +08:00
|
|
|
|
MultiMediaSourceMuxer::MultiMediaSourceMuxer(const string &vhost, const string &app, const string &stream, float dur_sec, const ProtocolOption &option) {
|
2022-08-28 17:25:56 +08:00
|
|
|
|
_poller = EventPollerPool::Instance().getPoller();
|
2022-08-27 10:53:47 +08:00
|
|
|
|
_vhost = vhost;
|
|
|
|
|
_app = app;
|
|
|
|
|
_stream_id = stream;
|
2022-08-16 11:47:24 +08:00
|
|
|
|
_option = option;
|
2021-08-16 17:31:13 +08:00
|
|
|
|
_get_origin_url = [this, vhost, app, stream]() {
|
2022-08-23 14:11:32 +08:00
|
|
|
|
auto ret = getOriginUrl(MediaSource::NullMediaSource());
|
2021-08-16 17:31:13 +08:00
|
|
|
|
if (!ret.empty()) {
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
return vhost + "/" + app + "/" + stream;
|
|
|
|
|
};
|
|
|
|
|
|
2022-03-12 13:19:21 +08:00
|
|
|
|
if (option.enable_rtmp) {
|
2020-04-05 09:26:29 +08:00
|
|
|
|
_rtmp = std::make_shared<RtmpMediaSourceMuxer>(vhost, app, stream, std::make_shared<TitleMeta>(dur_sec));
|
|
|
|
|
}
|
2022-03-12 13:19:21 +08:00
|
|
|
|
if (option.enable_rtsp) {
|
2020-04-05 09:26:29 +08:00
|
|
|
|
_rtsp = std::make_shared<RtspMediaSourceMuxer>(vhost, app, stream, std::make_shared<TitleSdp>(dur_sec));
|
|
|
|
|
}
|
2022-03-12 13:19:21 +08:00
|
|
|
|
if (option.enable_hls) {
|
2022-03-12 14:34:48 +08:00
|
|
|
|
_hls = dynamic_pointer_cast<HlsRecorder>(Recorder::createRecorder(Recorder::type_hls, vhost, app, stream, option.hls_save_path));
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
2022-03-12 13:19:21 +08:00
|
|
|
|
if (option.enable_mp4) {
|
2022-03-12 14:34:48 +08:00
|
|
|
|
_mp4 = Recorder::createRecorder(Recorder::type_mp4, vhost, app, stream, option.mp4_save_path, option.mp4_max_second);
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
2022-03-12 13:19:21 +08:00
|
|
|
|
if (option.enable_ts) {
|
|
|
|
|
_ts = std::make_shared<TSMediaSourceMuxer>(vhost, app, stream);
|
|
|
|
|
}
|
2020-09-27 16:54:55 +08:00
|
|
|
|
#if defined(ENABLE_MP4)
|
2022-03-12 13:19:21 +08:00
|
|
|
|
if (option.enable_fmp4) {
|
|
|
|
|
_fmp4 = std::make_shared<FMP4MediaSourceMuxer>(vhost, app, stream);
|
|
|
|
|
}
|
2020-09-27 16:54:55 +08:00
|
|
|
|
#endif
|
2022-03-12 14:34:48 +08:00
|
|
|
|
|
|
|
|
|
//音频相关设置
|
|
|
|
|
enableAudio(option.enable_audio);
|
|
|
|
|
enableMuteAudio(option.add_mute_audio);
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-20 11:51:26 +08:00
|
|
|
|
void MultiMediaSourceMuxer::setMediaListener(const std::weak_ptr<MediaSourceEvent> &listener) {
|
|
|
|
|
setDelegate(listener);
|
|
|
|
|
|
|
|
|
|
auto self = shared_from_this();
|
|
|
|
|
//拦截事件
|
2020-04-05 09:26:29 +08:00
|
|
|
|
if (_rtmp) {
|
2021-07-20 11:51:26 +08:00
|
|
|
|
_rtmp->setListener(self);
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
|
|
|
|
if (_rtsp) {
|
2021-07-20 11:51:26 +08:00
|
|
|
|
_rtsp->setListener(self);
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
2020-09-20 00:21:46 +08:00
|
|
|
|
if (_ts) {
|
2021-07-20 11:51:26 +08:00
|
|
|
|
_ts->setListener(self);
|
2020-09-20 00:21:46 +08:00
|
|
|
|
}
|
2020-09-27 16:54:55 +08:00
|
|
|
|
#if defined(ENABLE_MP4)
|
2020-09-20 19:45:37 +08:00
|
|
|
|
if (_fmp4) {
|
2021-07-20 11:51:26 +08:00
|
|
|
|
_fmp4->setListener(self);
|
2020-09-20 19:45:37 +08:00
|
|
|
|
}
|
2020-09-27 16:54:55 +08:00
|
|
|
|
#endif
|
2020-04-05 09:26:29 +08:00
|
|
|
|
auto hls = _hls;
|
|
|
|
|
if (hls) {
|
2021-07-20 11:51:26 +08:00
|
|
|
|
hls->setListener(self);
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
2021-07-20 11:51:26 +08:00
|
|
|
|
}
|
2020-04-05 09:26:29 +08:00
|
|
|
|
|
2021-07-20 11:51:26 +08:00
|
|
|
|
void MultiMediaSourceMuxer::setTrackListener(const std::weak_ptr<Listener> &listener) {
|
|
|
|
|
_track_listener = listener;
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-20 11:51:26 +08:00
|
|
|
|
int MultiMediaSourceMuxer::totalReaderCount() const {
|
|
|
|
|
auto hls = _hls;
|
|
|
|
|
auto ret = (_rtsp ? _rtsp->readerCount() : 0) +
|
|
|
|
|
(_rtmp ? _rtmp->readerCount() : 0) +
|
|
|
|
|
(_ts ? _ts->readerCount() : 0) +
|
|
|
|
|
#if defined(ENABLE_MP4)
|
|
|
|
|
(_fmp4 ? _fmp4->readerCount() : 0) +
|
|
|
|
|
#endif
|
2022-08-16 11:47:24 +08:00
|
|
|
|
(_mp4 ? _option.mp4_as_player : 0) +
|
2021-07-20 11:51:26 +08:00
|
|
|
|
(hls ? hls->readerCount() : 0);
|
|
|
|
|
|
|
|
|
|
#if defined(ENABLE_RTPPROXY)
|
|
|
|
|
return ret + (int)_rtp_sender.size();
|
|
|
|
|
#else
|
|
|
|
|
return ret;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void MultiMediaSourceMuxer::setTimeStamp(uint32_t stamp) {
|
2020-04-05 09:26:29 +08:00
|
|
|
|
if (_rtmp) {
|
2021-07-20 11:51:26 +08:00
|
|
|
|
_rtmp->setTimeStamp(stamp);
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
|
|
|
|
if (_rtsp) {
|
2021-07-20 11:51:26 +08:00
|
|
|
|
_rtsp->setTimeStamp(stamp);
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-20 11:51:26 +08:00
|
|
|
|
int MultiMediaSourceMuxer::totalReaderCount(MediaSource &sender) {
|
|
|
|
|
auto listener = getDelegate();
|
|
|
|
|
if (!listener) {
|
|
|
|
|
return totalReaderCount();
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
2022-08-28 17:25:56 +08:00
|
|
|
|
try {
|
|
|
|
|
return listener->totalReaderCount(sender);
|
|
|
|
|
} catch (MediaSourceEvent::NotImplemented &) {
|
|
|
|
|
//listener未重载totalReaderCount
|
|
|
|
|
return totalReaderCount();
|
|
|
|
|
}
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//此函数可能跨线程调用
|
2021-07-20 11:51:26 +08:00
|
|
|
|
bool MultiMediaSourceMuxer::setupRecord(MediaSource &sender, Recorder::type type, bool start, const string &custom_path, size_t max_second) {
|
2022-10-06 13:06:54 +08:00
|
|
|
|
onceToken token(nullptr, [&]() {
|
|
|
|
|
if (_option.mp4_as_player && type == Recorder::type_mp4) {
|
|
|
|
|
//开启关闭mp4录制,触发观看人数变化相关事件
|
|
|
|
|
onReaderChanged(sender, totalReaderCount());
|
|
|
|
|
}
|
|
|
|
|
});
|
2020-04-05 09:26:29 +08:00
|
|
|
|
switch (type) {
|
|
|
|
|
case Recorder::type_hls : {
|
|
|
|
|
if (start && !_hls) {
|
|
|
|
|
//开始录制
|
2021-07-20 13:15:57 +08:00
|
|
|
|
auto hls = dynamic_pointer_cast<HlsRecorder>(makeRecorder(sender, getTracks(), type, custom_path, max_second));
|
2020-09-12 19:20:18 +08:00
|
|
|
|
if (hls) {
|
2020-04-05 09:26:29 +08:00
|
|
|
|
//设置HlsMediaSource的事件监听器
|
2021-07-20 11:51:26 +08:00
|
|
|
|
hls->setListener(shared_from_this());
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
2020-09-12 19:20:18 +08:00
|
|
|
|
_hls = hls;
|
2020-04-05 09:26:29 +08:00
|
|
|
|
} else if (!start && _hls) {
|
|
|
|
|
//停止录制
|
|
|
|
|
_hls = nullptr;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
case Recorder::type_mp4 : {
|
|
|
|
|
if (start && !_mp4) {
|
|
|
|
|
//开始录制
|
2021-07-20 13:15:57 +08:00
|
|
|
|
_mp4 = makeRecorder(sender, getTracks(), type, custom_path, max_second);
|
2020-04-05 09:26:29 +08:00
|
|
|
|
} else if (!start && _mp4) {
|
|
|
|
|
//停止录制
|
|
|
|
|
_mp4 = nullptr;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2020-04-29 11:59:45 +08:00
|
|
|
|
default : return false;
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//此函数可能跨线程调用
|
2021-07-20 11:51:26 +08:00
|
|
|
|
bool MultiMediaSourceMuxer::isRecording(MediaSource &sender, Recorder::type type) {
|
2020-04-05 09:26:29 +08:00
|
|
|
|
switch (type){
|
|
|
|
|
case Recorder::type_hls :
|
2021-10-15 18:23:25 +08:00
|
|
|
|
return !!_hls;
|
2020-04-05 09:26:29 +08:00
|
|
|
|
case Recorder::type_mp4 :
|
2021-10-15 18:23:25 +08:00
|
|
|
|
return !!_mp4;
|
2020-04-05 09:26:29 +08:00
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-27 10:17:06 +08:00
|
|
|
|
void MultiMediaSourceMuxer::startSendRtp(MediaSource &sender, const MediaSourceEvent::SendRtpArgs &args, const std::function<void(uint16_t, const toolkit::SockException &)> cb) {
|
2021-07-20 11:51:26 +08:00
|
|
|
|
#if defined(ENABLE_RTPPROXY)
|
2022-08-27 10:17:06 +08:00
|
|
|
|
auto rtp_sender = std::make_shared<RtpSender>(getOwnerPoller(sender));
|
2021-07-20 11:51:26 +08:00
|
|
|
|
weak_ptr<MultiMediaSourceMuxer> weak_self = shared_from_this();
|
2022-08-20 12:48:27 +08:00
|
|
|
|
rtp_sender->startSend(args, [args, weak_self, rtp_sender, cb](uint16_t local_port, const SockException &ex) mutable {
|
2021-07-20 11:51:26 +08:00
|
|
|
|
cb(local_port, ex);
|
|
|
|
|
auto strong_self = weak_self.lock();
|
|
|
|
|
if (!strong_self || ex) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2021-07-20 13:15:57 +08:00
|
|
|
|
for (auto &track : strong_self->getTracks(false)) {
|
2021-07-20 11:51:26 +08:00
|
|
|
|
rtp_sender->addTrack(track);
|
|
|
|
|
}
|
|
|
|
|
rtp_sender->addTrackCompleted();
|
2022-08-20 12:48:27 +08:00
|
|
|
|
|
|
|
|
|
auto ssrc = args.ssrc;
|
2022-08-27 10:53:47 +08:00
|
|
|
|
rtp_sender->setOnClose([weak_self, ssrc](const toolkit::SockException &ex) {
|
2022-08-20 12:48:27 +08:00
|
|
|
|
if (auto strong_self = weak_self.lock()) {
|
2022-08-27 10:53:47 +08:00
|
|
|
|
WarnL << "stream:" << strong_self->_get_origin_url() << " stop send rtp:" << ssrc << ", reason:" << ex.what();
|
2022-08-20 13:16:25 +08:00
|
|
|
|
strong_self->_rtp_sender.erase(ssrc);
|
|
|
|
|
//触发观看人数统计
|
2022-08-23 14:11:32 +08:00
|
|
|
|
strong_self->onReaderChanged(MediaSource::NullMediaSource(), strong_self->totalReaderCount());
|
2022-08-27 10:53:47 +08:00
|
|
|
|
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastSendRtpStopped, *strong_self, ssrc, ex);
|
2022-08-20 12:48:27 +08:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
strong_self->_rtp_sender[args.ssrc] = std::move(rtp_sender);
|
2022-08-23 14:11:32 +08:00
|
|
|
|
strong_self->onReaderChanged(MediaSource::NullMediaSource(), strong_self->totalReaderCount());
|
2021-07-20 11:51:26 +08:00
|
|
|
|
});
|
|
|
|
|
#else
|
|
|
|
|
cb(0, SockException(Err_other, "该功能未启用,编译时请打开ENABLE_RTPPROXY宏"));
|
|
|
|
|
#endif//ENABLE_RTPPROXY
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool MultiMediaSourceMuxer::stopSendRtp(MediaSource &sender, const string &ssrc) {
|
|
|
|
|
#if defined(ENABLE_RTPPROXY)
|
2022-08-20 13:16:25 +08:00
|
|
|
|
onceToken token(nullptr, [&]() {
|
|
|
|
|
//关闭rtp推流,可能触发无人观看事件
|
|
|
|
|
onReaderChanged(sender, totalReaderCount());
|
|
|
|
|
});
|
2021-07-20 11:51:26 +08:00
|
|
|
|
if (ssrc.empty()) {
|
|
|
|
|
//关闭全部
|
|
|
|
|
auto size = _rtp_sender.size();
|
|
|
|
|
_rtp_sender.clear();
|
|
|
|
|
return size;
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
2021-07-20 11:51:26 +08:00
|
|
|
|
//关闭特定的
|
|
|
|
|
return _rtp_sender.erase(ssrc);
|
|
|
|
|
#else
|
|
|
|
|
return false;
|
|
|
|
|
#endif//ENABLE_RTPPROXY
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-20 13:15:57 +08:00
|
|
|
|
vector<Track::Ptr> MultiMediaSourceMuxer::getMediaTracks(MediaSource &sender, bool trackReady) const {
|
|
|
|
|
return getTracks(trackReady);
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-28 17:25:56 +08:00
|
|
|
|
EventPoller::Ptr MultiMediaSourceMuxer::getOwnerPoller(MediaSource &sender) {
|
|
|
|
|
auto listener = getDelegate();
|
|
|
|
|
if (!listener) {
|
|
|
|
|
return _poller;
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
return listener->getOwnerPoller(sender);
|
|
|
|
|
} catch (MediaSourceEvent::NotImplemented &) {
|
|
|
|
|
// listener未重载getOwnerPoller
|
|
|
|
|
return _poller;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-09-27 13:12:53 +08:00
|
|
|
|
bool MultiMediaSourceMuxer::onTrackReady(const Track::Ptr &track) {
|
2020-04-05 09:26:29 +08:00
|
|
|
|
|
2021-09-27 13:12:53 +08:00
|
|
|
|
bool ret = false;
|
2020-04-05 09:26:29 +08:00
|
|
|
|
if (_rtmp) {
|
2021-09-27 13:12:53 +08:00
|
|
|
|
ret = _rtmp->addTrack(track) ? true : ret;
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
|
|
|
|
if (_rtsp) {
|
2021-09-27 13:12:53 +08:00
|
|
|
|
ret = _rtsp->addTrack(track) ? true : ret;
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
2020-09-20 00:21:46 +08:00
|
|
|
|
if (_ts) {
|
2021-09-27 13:12:53 +08:00
|
|
|
|
ret = _ts->addTrack(track) ? true : ret;
|
2020-09-20 00:21:46 +08:00
|
|
|
|
}
|
2020-09-27 16:54:55 +08:00
|
|
|
|
#if defined(ENABLE_MP4)
|
2020-09-20 19:45:37 +08:00
|
|
|
|
if (_fmp4) {
|
2021-09-27 13:12:53 +08:00
|
|
|
|
ret = _fmp4->addTrack(track) ? true : ret;
|
2020-09-20 19:45:37 +08:00
|
|
|
|
}
|
2020-09-27 16:54:55 +08:00
|
|
|
|
#endif
|
2020-04-05 09:26:29 +08:00
|
|
|
|
|
|
|
|
|
//拷贝智能指针,目的是为了防止跨线程调用设置录像相关api导致的线程竞争问题
|
|
|
|
|
auto hls = _hls;
|
|
|
|
|
if (hls) {
|
2021-09-27 13:12:53 +08:00
|
|
|
|
ret = hls->addTrack(track) ? true : ret;
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
|
|
|
|
auto mp4 = _mp4;
|
|
|
|
|
if (mp4) {
|
2021-09-27 13:12:53 +08:00
|
|
|
|
ret = mp4->addTrack(track) ? true : ret;
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
2021-09-27 13:12:53 +08:00
|
|
|
|
return ret;
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-20 11:51:26 +08:00
|
|
|
|
void MultiMediaSourceMuxer::onAllTrackReady() {
|
|
|
|
|
setMediaListener(getDelegate());
|
2020-04-29 11:59:45 +08:00
|
|
|
|
|
2020-04-05 09:26:29 +08:00
|
|
|
|
if (_rtmp) {
|
2021-07-20 11:51:26 +08:00
|
|
|
|
_rtmp->onAllTrackReady();
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
|
|
|
|
if (_rtsp) {
|
2021-07-20 11:51:26 +08:00
|
|
|
|
_rtsp->onAllTrackReady();
|
2020-09-20 00:21:46 +08:00
|
|
|
|
}
|
2020-09-27 16:54:55 +08:00
|
|
|
|
#if defined(ENABLE_MP4)
|
2020-09-20 19:45:37 +08:00
|
|
|
|
if (_fmp4) {
|
2021-07-20 11:51:26 +08:00
|
|
|
|
_fmp4->onAllTrackReady();
|
2020-09-20 19:45:37 +08:00
|
|
|
|
}
|
2020-09-27 16:54:55 +08:00
|
|
|
|
#endif
|
2021-07-20 11:51:26 +08:00
|
|
|
|
auto listener = _track_listener.lock();
|
|
|
|
|
if (listener) {
|
|
|
|
|
listener->onAllTrackReady();
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
2021-08-16 17:31:13 +08:00
|
|
|
|
InfoL << "stream: " << _get_origin_url() << " , codec info: " << getTrackInfoStr(this);
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-20 11:51:26 +08:00
|
|
|
|
void MultiMediaSourceMuxer::resetTracks() {
|
|
|
|
|
MediaSink::resetTracks();
|
2020-09-12 19:20:18 +08:00
|
|
|
|
|
2020-04-05 09:26:29 +08:00
|
|
|
|
if (_rtmp) {
|
2021-07-20 11:51:26 +08:00
|
|
|
|
_rtmp->resetTracks();
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
|
|
|
|
if (_rtsp) {
|
2021-07-20 11:51:26 +08:00
|
|
|
|
_rtsp->resetTracks();
|
|
|
|
|
}
|
|
|
|
|
if (_ts) {
|
|
|
|
|
_ts->resetTracks();
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
2020-09-27 16:54:55 +08:00
|
|
|
|
#if defined(ENABLE_MP4)
|
2020-09-20 19:45:37 +08:00
|
|
|
|
if (_fmp4) {
|
2021-07-20 11:51:26 +08:00
|
|
|
|
_fmp4->resetTracks();
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
2021-04-18 21:27:44 +08:00
|
|
|
|
#endif
|
2020-04-05 09:26:29 +08:00
|
|
|
|
|
2020-09-06 17:56:05 +08:00
|
|
|
|
#if defined(ENABLE_RTPPROXY)
|
2021-07-20 11:51:26 +08:00
|
|
|
|
for (auto &pr : _rtp_sender) {
|
|
|
|
|
pr.second->resetTracks();
|
2020-12-26 16:52:36 +08:00
|
|
|
|
}
|
2021-07-20 11:51:26 +08:00
|
|
|
|
#endif
|
2020-04-05 09:26:29 +08:00
|
|
|
|
|
2021-07-20 11:51:26 +08:00
|
|
|
|
//拷贝智能指针,目的是为了防止跨线程调用设置录像相关api导致的线程竞争问题
|
|
|
|
|
auto hls = _hls;
|
|
|
|
|
if (hls) {
|
|
|
|
|
hls->resetTracks();
|
2020-08-08 12:20:13 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-07-20 11:51:26 +08:00
|
|
|
|
auto mp4 = _mp4;
|
|
|
|
|
if (mp4) {
|
|
|
|
|
mp4->resetTracks();
|
|
|
|
|
}
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
2021-09-27 13:12:53 +08:00
|
|
|
|
bool MultiMediaSourceMuxer::onTrackFrame(const Frame::Ptr &frame_in) {
|
2020-09-06 17:56:05 +08:00
|
|
|
|
auto frame = frame_in;
|
2022-09-03 09:54:09 +08:00
|
|
|
|
if (_option.modify_stamp) {
|
2020-05-25 12:07:38 +08:00
|
|
|
|
//开启了时间戳覆盖
|
2022-06-26 00:54:31 +08:00
|
|
|
|
frame = std::make_shared<FrameStamp>(frame, _stamp[frame->getTrackType()],true);
|
2020-05-25 12:07:38 +08:00
|
|
|
|
}
|
2021-07-20 11:51:26 +08:00
|
|
|
|
|
2021-09-27 13:12:53 +08:00
|
|
|
|
bool ret = false;
|
2021-07-20 11:51:26 +08:00
|
|
|
|
if (_rtmp) {
|
2021-09-27 13:12:53 +08:00
|
|
|
|
ret = _rtmp->inputFrame(frame) ? true : ret;
|
2021-07-20 11:51:26 +08:00
|
|
|
|
}
|
|
|
|
|
if (_rtsp) {
|
2021-09-27 13:12:53 +08:00
|
|
|
|
ret = _rtsp->inputFrame(frame) ? true : ret;
|
2021-07-20 11:51:26 +08:00
|
|
|
|
}
|
|
|
|
|
if (_ts) {
|
2021-09-27 13:12:53 +08:00
|
|
|
|
ret = _ts->inputFrame(frame) ? true : ret;
|
2021-07-20 11:51:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//拷贝智能指针,目的是为了防止跨线程调用设置录像相关api导致的线程竞争问题
|
|
|
|
|
//此处使用智能指针拷贝来确保线程安全,比互斥锁性能更优
|
|
|
|
|
auto hls = _hls;
|
|
|
|
|
if (hls) {
|
2021-09-27 13:12:53 +08:00
|
|
|
|
ret = hls->inputFrame(frame) ? true : ret;
|
2021-07-20 11:51:26 +08:00
|
|
|
|
}
|
|
|
|
|
auto mp4 = _mp4;
|
|
|
|
|
if (mp4) {
|
2021-09-27 13:12:53 +08:00
|
|
|
|
ret = mp4->inputFrame(frame) ? true : ret;
|
2021-07-20 11:51:26 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if defined(ENABLE_MP4)
|
|
|
|
|
if (_fmp4) {
|
2021-09-27 13:12:53 +08:00
|
|
|
|
ret = _fmp4->inputFrame(frame) ? true : ret;
|
2021-07-20 11:51:26 +08:00
|
|
|
|
}
|
|
|
|
|
#endif
|
2020-09-06 17:56:05 +08:00
|
|
|
|
|
|
|
|
|
#if defined(ENABLE_RTPPROXY)
|
2020-12-27 18:41:53 +08:00
|
|
|
|
for (auto &pr : _rtp_sender) {
|
2021-09-27 13:12:53 +08:00
|
|
|
|
ret = pr.second->inputFrame(frame) ? true : ret;
|
2020-09-06 17:56:05 +08:00
|
|
|
|
}
|
|
|
|
|
#endif //ENABLE_RTPPROXY
|
2021-09-27 13:12:53 +08:00
|
|
|
|
return ret;
|
2020-04-05 09:26:29 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-29 11:59:45 +08:00
|
|
|
|
bool MultiMediaSourceMuxer::isEnabled(){
|
2020-11-15 00:59:31 +08:00
|
|
|
|
GET_CONFIG(uint32_t, stream_none_reader_delay_ms, General::kStreamNoneReaderDelayMS);
|
|
|
|
|
if (!_is_enable || _last_check.elapsedTime() > stream_none_reader_delay_ms) {
|
|
|
|
|
//无人观看时,每次检查是否真的无人观看
|
|
|
|
|
//有人观看时,则延迟一定时间检查一遍是否无人观看了(节省性能)
|
2021-07-20 11:51:26 +08:00
|
|
|
|
auto hls = _hls;
|
|
|
|
|
auto flag = (_rtmp ? _rtmp->isEnabled() : false) ||
|
|
|
|
|
(_rtsp ? _rtsp->isEnabled() : false) ||
|
|
|
|
|
(_ts ? _ts->isEnabled() : false) ||
|
|
|
|
|
#if defined(ENABLE_MP4)
|
|
|
|
|
(_fmp4 ? _fmp4->isEnabled() : false) ||
|
|
|
|
|
#endif
|
|
|
|
|
(hls ? hls->isEnabled() : false) || _mp4;
|
|
|
|
|
|
2020-09-10 19:28:30 +08:00
|
|
|
|
#if defined(ENABLE_RTPPROXY)
|
2021-07-20 11:51:26 +08:00
|
|
|
|
_is_enable = flag || _rtp_sender.size();
|
2020-09-12 19:20:18 +08:00
|
|
|
|
#else
|
2021-07-20 11:51:26 +08:00
|
|
|
|
_is_enable = flag;
|
2020-09-12 19:20:18 +08:00
|
|
|
|
#endif //ENABLE_RTPPROXY
|
2020-11-15 00:59:31 +08:00
|
|
|
|
if (_is_enable) {
|
|
|
|
|
//无人观看时,不刷新计时器,因为无人观看时每次都会检查一遍,所以刷新计数器无意义且浪费cpu
|
|
|
|
|
_last_check.resetTime();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return _is_enable;
|
2020-04-29 11:59:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
2022-09-03 09:54:09 +08:00
|
|
|
|
}//namespace mediakit
|