mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-07-06 19:58:10 +08:00
实现rtsp/rtmp按需转协议功能
This commit is contained in:
@@ -93,13 +93,10 @@ bool MediaSource::close(bool force) {
|
||||
return listener->close(*this,force);
|
||||
}
|
||||
|
||||
void MediaSource::onNoneReader(){
|
||||
void MediaSource::onReaderChanged(int size) {
|
||||
auto listener = _listener.lock();
|
||||
if(!listener){
|
||||
return;
|
||||
}
|
||||
if (listener->totalReaderCount(*this) == 0) {
|
||||
listener->onNoneReader(*this);
|
||||
if (listener) {
|
||||
listener->onReaderChanged(*this, size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -475,45 +472,47 @@ MediaSource::Ptr MediaSource::createFromMP4(const string &schema, const string &
|
||||
|
||||
/////////////////////////////////////MediaSourceEvent//////////////////////////////////////
|
||||
|
||||
void MediaSourceEvent::onNoneReader(MediaSource &sender){
|
||||
void MediaSourceEvent::onReaderChanged(MediaSource &sender, int size){
|
||||
if (size || totalReaderCount(sender)) {
|
||||
//还有人观看该视频,不触发关闭事件
|
||||
return;
|
||||
}
|
||||
//没有任何人观看该视频源,表明该源可以关闭了
|
||||
GET_CONFIG(string, record_app, Record::kAppName);
|
||||
GET_CONFIG(int, stream_none_reader_delay, General::kStreamNoneReaderDelayMS);
|
||||
|
||||
//如果mp4点播, 无人观看时我们强制关闭点播
|
||||
bool is_mp4_vod = sender.getApp() == record_app;
|
||||
weak_ptr<MediaSource> weak_sender = sender.shared_from_this();
|
||||
|
||||
//没有任何人观看该视频源,表明该源可以关闭了
|
||||
weak_ptr<MediaSource> weakSender = sender.shared_from_this();
|
||||
_async_close_timer = std::make_shared<Timer>(stream_none_reader_delay / 1000.0, [weakSender,is_mp4_vod]() {
|
||||
auto strongSender = weakSender.lock();
|
||||
if (!strongSender) {
|
||||
_async_close_timer = std::make_shared<Timer>(stream_none_reader_delay / 1000.0, [weak_sender, is_mp4_vod]() {
|
||||
auto strong_sender = weak_sender.lock();
|
||||
if (!strong_sender) {
|
||||
//对象已经销毁
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strongSender->totalReaderCount() != 0) {
|
||||
//还有人消费
|
||||
if (strong_sender->totalReaderCount()) {
|
||||
//还有人观看该视频,不触发关闭事件
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!is_mp4_vod){
|
||||
if (!is_mp4_vod) {
|
||||
//直播时触发无人观看事件,让开发者自行选择是否关闭
|
||||
WarnL << "无人观看事件:"
|
||||
<< strongSender->getSchema() << "/"
|
||||
<< strongSender->getVhost() << "/"
|
||||
<< strongSender->getApp() << "/"
|
||||
<< strongSender->getId();
|
||||
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastStreamNoneReader, *strongSender);
|
||||
}else{
|
||||
<< strong_sender->getSchema() << "/"
|
||||
<< strong_sender->getVhost() << "/"
|
||||
<< strong_sender->getApp() << "/"
|
||||
<< strong_sender->getId();
|
||||
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastStreamNoneReader, *strong_sender);
|
||||
} else {
|
||||
//这个是mp4点播,我们自动关闭
|
||||
WarnL << "MP4点播无人观看,自动关闭:"
|
||||
<< strongSender->getSchema() << "/"
|
||||
<< strongSender->getVhost() << "/"
|
||||
<< strongSender->getApp() << "/"
|
||||
<< strongSender->getId();
|
||||
strongSender->close(false);
|
||||
<< strong_sender->getSchema() << "/"
|
||||
<< strong_sender->getVhost() << "/"
|
||||
<< strong_sender->getApp() << "/"
|
||||
<< strong_sender->getId();
|
||||
strong_sender->close(false);
|
||||
}
|
||||
|
||||
return false;
|
||||
}, nullptr);
|
||||
}
|
||||
@@ -542,13 +541,13 @@ int MediaSourceEventInterceptor::totalReaderCount(MediaSource &sender) {
|
||||
return listener->totalReaderCount(sender);
|
||||
}
|
||||
|
||||
void MediaSourceEventInterceptor::onNoneReader(MediaSource &sender) {
|
||||
void MediaSourceEventInterceptor::onReaderChanged(MediaSource &sender, int size) {
|
||||
auto listener = _listener.lock();
|
||||
if (!listener) {
|
||||
MediaSourceEvent::onNoneReader(sender);
|
||||
return;
|
||||
MediaSourceEvent::onReaderChanged(sender, size);
|
||||
} else {
|
||||
listener->onReaderChanged(sender, size);
|
||||
}
|
||||
listener->onNoneReader(sender);
|
||||
}
|
||||
|
||||
void MediaSourceEventInterceptor::onRegist(MediaSource &sender, bool regist) {
|
||||
|
||||
@@ -49,8 +49,8 @@ public:
|
||||
virtual bool close(MediaSource &sender, bool force) { return false; }
|
||||
// 获取观看总人数
|
||||
virtual int totalReaderCount(MediaSource &sender) = 0;
|
||||
// 通知无人观看
|
||||
virtual void onNoneReader(MediaSource &sender);
|
||||
// 通知观看人数变化
|
||||
virtual void onReaderChanged(MediaSource &sender, int size);
|
||||
//流注册或注销事件
|
||||
virtual void onRegist(MediaSource &sender, bool regist) {};
|
||||
|
||||
@@ -79,7 +79,7 @@ public:
|
||||
bool seekTo(MediaSource &sender, uint32_t stamp) override;
|
||||
bool close(MediaSource &sender, bool force) override;
|
||||
int totalReaderCount(MediaSource &sender) override;
|
||||
void onNoneReader(MediaSource &sender) override;
|
||||
void onReaderChanged(MediaSource &sender, int size) override;
|
||||
void onRegist(MediaSource &sender, bool regist) override;
|
||||
bool setupRecord(MediaSource &sender, Recorder::type type, bool start, const string &custom_path) override;
|
||||
bool isRecording(MediaSource &sender, Recorder::type type) override;
|
||||
@@ -160,8 +160,8 @@ public:
|
||||
bool seekTo(uint32_t stamp);
|
||||
// 关闭该流
|
||||
bool close(bool force);
|
||||
// 该流无人观看
|
||||
void onNoneReader();
|
||||
// 该流观看人数变化
|
||||
void onReaderChanged(int size);
|
||||
// 开启或关闭录制
|
||||
bool setupRecord(Recorder::type type, bool start, const string &custom_path);
|
||||
// 获取录制状态
|
||||
@@ -249,6 +249,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void clearCache() {
|
||||
_cache->clear();
|
||||
}
|
||||
|
||||
virtual void onFlush(std::shared_ptr<packet_list> &, bool key_pos) = 0;
|
||||
|
||||
private:
|
||||
|
||||
@@ -18,21 +18,17 @@ MultiMuxerPrivate::MultiMuxerPrivate(const string &vhost, const string &app, con
|
||||
bool enable_rtsp, bool enable_rtmp, bool enable_hls, bool enable_mp4) {
|
||||
if (enable_rtmp) {
|
||||
_rtmp = std::make_shared<RtmpMediaSourceMuxer>(vhost, app, stream, std::make_shared<TitleMeta>(dur_sec));
|
||||
_enable_rtxp = true;
|
||||
}
|
||||
if (enable_rtsp) {
|
||||
_rtsp = std::make_shared<RtspMediaSourceMuxer>(vhost, app, stream, std::make_shared<TitleSdp>(dur_sec));
|
||||
_enable_rtxp = true;
|
||||
}
|
||||
|
||||
if (enable_hls) {
|
||||
_hls = Recorder::createRecorder(Recorder::type_hls, vhost, app, stream);
|
||||
_enable_record = true;
|
||||
}
|
||||
|
||||
if (enable_mp4) {
|
||||
_mp4 = Recorder::createRecorder(Recorder::type_mp4, vhost, app, stream);
|
||||
_enable_record = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +97,6 @@ bool MultiMuxerPrivate::setupRecord(MediaSource &sender, Recorder::type type, bo
|
||||
//停止录制
|
||||
_hls = nullptr;
|
||||
}
|
||||
_enable_record = _hls || _mp4;
|
||||
return true;
|
||||
}
|
||||
case Recorder::type_mp4 : {
|
||||
@@ -112,7 +107,6 @@ bool MultiMuxerPrivate::setupRecord(MediaSource &sender, Recorder::type type, bo
|
||||
//停止录制
|
||||
_mp4 = nullptr;
|
||||
}
|
||||
_enable_record = _hls || _mp4;
|
||||
return true;
|
||||
}
|
||||
default : return false;
|
||||
@@ -164,7 +158,7 @@ void MultiMuxerPrivate::onTrackReady(const Track::Ptr &track) {
|
||||
}
|
||||
|
||||
bool MultiMuxerPrivate::isEnabled(){
|
||||
return _enable_rtxp || _enable_record;
|
||||
return (_rtmp ? _rtmp->isEnabled() : false) || (_rtsp ? _rtsp->isEnabled() : false) || _hls || _mp4;
|
||||
}
|
||||
|
||||
void MultiMuxerPrivate::onTrackFrame(const Frame::Ptr &frame) {
|
||||
|
||||
@@ -49,8 +49,6 @@ private:
|
||||
MediaSource::Ptr getHlsMediaSource() const;
|
||||
|
||||
private:
|
||||
bool _enable_rtxp = false;
|
||||
bool _enable_record = false;
|
||||
Listener *_track_listener = nullptr;
|
||||
RtmpMediaSourceMuxer::Ptr _rtmp;
|
||||
RtspMediaSourceMuxer::Ptr _rtsp;
|
||||
|
||||
@@ -63,7 +63,6 @@ const string kMaxStreamWaitTimeMS = GENERAL_FIELD"maxStreamWaitMS";
|
||||
const string kEnableVhost = GENERAL_FIELD"enableVhost";
|
||||
const string kAddMuteAudio = GENERAL_FIELD"addMuteAudio";
|
||||
const string kResetWhenRePlay = GENERAL_FIELD"resetWhenRePlay";
|
||||
const string kPublishToRtxp = GENERAL_FIELD"publishToRtxp";
|
||||
const string kPublishToHls = GENERAL_FIELD"publishToHls";
|
||||
const string kPublishToMP4 = GENERAL_FIELD"publishToMP4";
|
||||
const string kMergeWriteMS = GENERAL_FIELD"mergeWriteMS";
|
||||
@@ -76,7 +75,6 @@ onceToken token([](){
|
||||
mINI::Instance()[kEnableVhost] = 0;
|
||||
mINI::Instance()[kAddMuteAudio] = 1;
|
||||
mINI::Instance()[kResetWhenRePlay] = 1;
|
||||
mINI::Instance()[kPublishToRtxp] = 1;
|
||||
mINI::Instance()[kPublishToHls] = 1;
|
||||
mINI::Instance()[kPublishToMP4] = 0;
|
||||
mINI::Instance()[kMergeWriteMS] = 0;
|
||||
|
||||
@@ -86,8 +86,7 @@ extern const string kBroadcastOnRtspAuth;
|
||||
//如果errMessage为空则代表鉴权成功
|
||||
//enableHls: 是否允许转换hls
|
||||
//enableMP4: 是否运行MP4录制
|
||||
//enableRtxp: rtmp推流时是否运行转rtsp;rtsp推流时,是否允许转rtmp
|
||||
typedef std::function<void(const string &errMessage,bool enableRtxp,bool enableHls,bool enableMP4)> PublishAuthInvoker;
|
||||
typedef std::function<void(const string &errMessage, bool enableHls, bool enableMP4)> PublishAuthInvoker;
|
||||
|
||||
//收到rtsp/rtmp推流事件广播,通过该事件控制推流鉴权
|
||||
extern const string kBroadcastMediaPublish;
|
||||
@@ -165,8 +164,6 @@ extern const string kAddMuteAudio;
|
||||
//拉流代理时如果断流再重连成功是否删除前一次的媒体流数据,如果删除将重新开始,
|
||||
//如果不删除将会接着上一次的数据继续写(录制hls/mp4时会继续在前一个文件后面写)
|
||||
extern const string kResetWhenRePlay;
|
||||
//是否默认推流时转换成rtsp或rtmp,hook接口(on_publish)中可以覆盖该设置
|
||||
extern const string kPublishToRtxp ;
|
||||
//是否默认推流时转换成hls,hook接口(on_publish)中可以覆盖该设置
|
||||
extern const string kPublishToHls ;
|
||||
//是否默认推流时mp4录像,hook接口(on_publish)中可以覆盖该设置
|
||||
|
||||
Reference in New Issue
Block a user