diff --git a/postman/ZLMediaKit.postman_collection.json b/postman/ZLMediaKit.postman_collection.json index e7ddec35..c3d6666b 100644 --- a/postman/ZLMediaKit.postman_collection.json +++ b/postman/ZLMediaKit.postman_collection.json @@ -875,6 +875,12 @@ "description": "推流重试次数,不传此参数或传值<=0时,则无限重试", "disabled": true }, + { + "key": "force", + "value": null, + "description": "是否强制添加代理,默认0,设置为1时如果拉流失败也会不断重试", + "disabled": true + }, { "key": "latency", "value": null, diff --git a/server/WebApi.cpp b/server/WebApi.cpp index fd27dc13..537aa1ed 100755 --- a/server/WebApi.cpp +++ b/server/WebApi.cpp @@ -583,7 +583,7 @@ void getStatisticJson(const function &cb) { #endif } -void addStreamProxy(const MediaTuple &tuple, const string &url, int retry_count, +void addStreamProxy(const MediaTuple &tuple, const string &url, int retry_count, bool force, const ProtocolOption &option, int rtp_type, float timeout_sec, const mINI &args, const function &cb) { auto key = tuple.shortUrl(); @@ -615,11 +615,18 @@ void addStreamProxy(const MediaTuple &tuple, const string &url, int retry_count, // 开始播放,如果播放失败或者播放中止,将会自动重试若干次,默认一直重试 [AUTO-TRANSLATED:ac8499e5] // Start playing. If playback fails or is stopped, it will automatically retry several times, by default it will retry indefinitely - player->setPlayCallbackOnce([cb, key](const SockException &ex) { - if (ex) { - s_player_proxy.erase(key); + player->setPlayCallbackOnce([cb, key, force](const SockException &ex) { + if (force) { + // 强制添加成功 + cb(SockException(), key); + } else { + // 非强制添加 + if (ex) { + // 失败则移除记录 + s_player_proxy.erase(key); + } + cb(ex, key); } - cb(ex, key); }); // 被主动关闭拉流 [AUTO-TRANSLATED:41a19476] @@ -1264,6 +1271,7 @@ void installWebApi() { addStreamProxy(tuple, allArgs["url"], retry_count, + allArgs["force"], option, allArgs["rtp_type"], allArgs["timeout_sec"], diff --git a/server/WebApi.h b/server/WebApi.h index cd642f0e..7881aff9 100755 --- a/server/WebApi.h +++ b/server/WebApi.h @@ -248,7 +248,7 @@ uint16_t openRtpServer(uint16_t local_port, const mediakit::MediaTuple &tuple, i Json::Value makeMediaSourceJson(mediakit::MediaSource &media); ApiArgsType getAllArgs(const mediakit::Parser &parser); void getStatisticJson(const std::function &cb); -void addStreamProxy(const mediakit::MediaTuple &tuple, const std::string &url, int retry_count, +void addStreamProxy(const mediakit::MediaTuple &tuple, const std::string &url, int retry_count, bool force, const mediakit::ProtocolOption &option, int rtp_type, float timeout_sec, const toolkit::mINI &args, const std::function &cb); diff --git a/server/WebHook.cpp b/server/WebHook.cpp index 5ecdc9fe..a0268b56 100755 --- a/server/WebHook.cpp +++ b/server/WebHook.cpp @@ -321,7 +321,7 @@ static void pullStreamFromOrigin(const vector &urls, size_t index, size_ option.enable_hls = option.enable_hls || (args.schema == HLS_SCHEMA); option.enable_mp4 = false; - addStreamProxy(args, url, retry_count, option, Rtsp::RTP_TCP, timeout_sec, mINI{}, [=](const SockException &ex, const string &key) mutable { + addStreamProxy(args, url, retry_count, false, option, Rtsp::RTP_TCP, timeout_sec, mINI{}, [=](const SockException &ex, const string &key) mutable { if (!ex) { return; } diff --git a/src/Http/TsplayerImp.cpp b/src/Http/TsplayerImp.cpp index ec607edb..0b99d115 100644 --- a/src/Http/TsplayerImp.cpp +++ b/src/Http/TsplayerImp.cpp @@ -46,6 +46,10 @@ void TsPlayerImp::onPlayResult(const SockException &ex) { } void TsPlayerImp::onShutdown(const SockException &ex) { + if (!ex) { + // http-ts拉流,如果为eof正常断开,那么强制为异常状态 + const_cast(ex).reset(Err_other, ex.what()); + } while (_demuxer) { try { // shared_from_this()可能抛异常 [AUTO-TRANSLATED:6af9bd3c] diff --git a/src/Player/PlayerProxy.cpp b/src/Player/PlayerProxy.cpp index 0d465eb2..c7ca3ee6 100644 --- a/src/Player/PlayerProxy.cpp +++ b/src/Player/PlayerProxy.cpp @@ -32,7 +32,7 @@ PlayerProxy::PlayerProxy( setOnClose(nullptr); setOnConnect(nullptr); setOnDisconnect(nullptr); - + _reconnect_delay_min = reconnect_delay_min > 0 ? reconnect_delay_min : 2; _reconnect_delay_max = reconnect_delay_max > 0 ? reconnect_delay_max : 60; _reconnect_delay_step = reconnect_delay_step > 0 ? reconnect_delay_step : 3; @@ -51,15 +51,14 @@ void PlayerProxy::setOnClose(function cb) { } void PlayerProxy::setOnDisconnect(std::function cb) { - _on_disconnect = cb ? std::move(cb) : [] () {}; + _on_disconnect = cb ? std::move(cb) : []() {}; } -void PlayerProxy::setOnConnect(std::function cb) { - _on_connect = cb ? std::move(cb) : [](const TranslationInfo&) {}; +void PlayerProxy::setOnConnect(std::function cb) { + _on_connect = cb ? std::move(cb) : [](const TranslationInfo &) {}; } -void PlayerProxy::setTranslationInfo() -{ +void PlayerProxy::setTranslationInfo() { _transtalion_info.byte_speed = _media_src ? _media_src->getBytesSpeed() : -1; _transtalion_info.start_time_stamp = _media_src ? _media_src->getCreateStamp() : 0; _transtalion_info.stream_info.clear(); @@ -72,22 +71,21 @@ void PlayerProxy::setTranslationInfo() back.codec_type = track->getTrackType(); back.codec_name = track->getCodecName(); switch (back.codec_type) { - case TrackAudio : { + case TrackAudio: { auto audio_track = dynamic_pointer_cast(track); back.audio_sample_rate = audio_track->getAudioSampleRate(); back.audio_channel = audio_track->getAudioChannel(); back.audio_sample_bit = audio_track->getAudioSampleBit(); break; } - case TrackVideo : { + case TrackVideo: { auto video_track = dynamic_pointer_cast(track); back.video_width = video_track->getVideoWidth(); back.video_height = video_track->getVideoHeight(); back.video_fps = video_track->getVideoFps(); break; } - default: - break; + default: break; } } } @@ -120,7 +118,8 @@ void PlayerProxy::play(const string &strUrlTmp) { if (!err) { // 取消定时器,避免hls拉流索引文件因为网络波动失败重连成功后出现循环重试的情况 [AUTO-TRANSLATED:91e5f0c8] - // Cancel the timer to avoid the situation where the hls stream index file fails to reconnect due to network fluctuations and then retries in a loop after successful reconnection + // Cancel the timer to avoid the situation where the hls stream index file fails to reconnect due to network fluctuations and then retries in a loop + // after successful reconnection strongSelf->_timer.reset(); strongSelf->_live_ticker.resetTime(); strongSelf->_live_status = 0; @@ -129,7 +128,7 @@ void PlayerProxy::play(const string &strUrlTmp) { *piFailedCnt = 0; // 连续播放失败次数清0 strongSelf->onPlaySuccess(); strongSelf->setTranslationInfo(); - strongSelf->_on_connect(strongSelf->_transtalion_info); + strongSelf->_on_connect(strongSelf->_transtalion_info); InfoL << "play " << strUrlTmp << " success"; } else if (*piFailedCnt < strongSelf->_retry_count || strongSelf->_retry_count < 0) { @@ -151,6 +150,10 @@ void PlayerProxy::play(const string &strUrlTmp) { if (err) { NOTICE_EMIT(BroadcastPlayerProxyFailedArgs, Broadcast::kBroadcastPlayerProxyFailed, *strongSelf, err); } + if (strongSelf->_on_play) { + strongSelf->_on_play(err); + strongSelf->_on_play = nullptr; + } // 注销直接拉流代理产生的流:#532 [AUTO-TRANSLATED:c6343a3b] // Unregister the stream generated by the direct stream proxy: #532 @@ -291,7 +294,7 @@ float PlayerProxy::getLossRate(MediaSource &sender, TrackType type) { return getPacketLossRate(type); } -toolkit::EventPoller::Ptr PlayerProxy::getOwnerPoller(MediaSource &sender) { +toolkit::EventPoller::Ptr PlayerProxy::getOwnerPoller(MediaSource &sender) { return getPoller(); } @@ -314,10 +317,10 @@ void PlayerProxy::onPlaySuccess() { // rtmp拉流代理 [AUTO-TRANSLATED:21173335] // Rtmp stream proxy if (reset_when_replay || !_muxer) { - auto old = _option.enable_rtmp; + auto old = _option.enable_rtmp; _option.enable_rtmp = false; _muxer = std::make_shared(_tuple, getDuration(), _option); - _option.enable_rtmp = old; + _option.enable_rtmp = old; } } else { // 其他拉流代理 [AUTO-TRANSLATED:e5f2e45d]