diff --git a/server/WebApi.cpp b/server/WebApi.cpp index 148f4500..d99186a2 100755 --- a/server/WebApi.cpp +++ b/server/WebApi.cpp @@ -592,6 +592,17 @@ void getStatisticJson(const function &cb) { #endif } +void updateStreamProxy(const mediakit::MediaTuple &tuple, const std::string &url, const toolkit::mINI &args) { + auto key = tuple.shortUrl(); + auto player = s_player_proxy.find(key); + if (!player) { + throw std::runtime_error("proxy player not found: " + key); + } + player->getPoller()->async([url, args, player]() { + player->update(url, args); + }); +} + void addStreamProxy(const MediaTuple &tuple, const string &url, int retry_count, bool force, const ProtocolOption &option, float timeout_sec, const mINI &args, const function &cb) { diff --git a/server/WebApi.h b/server/WebApi.h index 8883d918..6c405f72 100755 --- a/server/WebApi.h +++ b/server/WebApi.h @@ -252,6 +252,8 @@ void addStreamProxy(const mediakit::MediaTuple &tuple, const std::string &url, i const mediakit::ProtocolOption &option, float timeout_sec, const toolkit::mINI &args, const std::function &cb); +void updateStreamProxy(const mediakit::MediaTuple &tuple, const std::string &url, const toolkit::mINI &args); + template class ServiceController { public: diff --git a/server/pyinvoker.cpp b/server/pyinvoker.cpp index 111a3a03..ccd0ca7f 100644 --- a/server/pyinvoker.cpp +++ b/server/pyinvoker.cpp @@ -374,6 +374,20 @@ PYBIND11_EMBEDDED_MODULE(mk_loader, m) { py::arg("timeout_sec") = 0.0f, py::arg("opt") = py::dict() ); + // update_stream_proxy(vhost, app, stream, url, opt={}) + // 更新已有拉流代理的 url 和参数,流不存在时抛出异常 + m.def("update_stream_proxy", + [](const std::string &vhost, const std::string &app, const std::string &stream, + const std::string &url, const py::dict &opt) { + mINI args = to_native(opt); + MediaTuple tuple { vhost.empty() ? DEFAULT_VHOST : vhost, app, stream, "" }; + py::gil_scoped_release release; + updateStreamProxy(tuple, url, args); + }, + py::arg("vhost"), py::arg("app"), py::arg("stream"), py::arg("url"), + py::arg("opt") = py::dict() + ); + m.def("set_fastapi", [](const py::object &check_route, const py::object &submit_coro) { static void *fastapi_tag = nullptr; NoticeCenter::Instance().delListener(&fastapi_tag, Broadcast::kBroadcastHttpRequest); diff --git a/src/Player/PlayerProxy.cpp b/src/Player/PlayerProxy.cpp index e442cce5..1e1037bb 100644 --- a/src/Player/PlayerProxy.cpp +++ b/src/Player/PlayerProxy.cpp @@ -42,6 +42,16 @@ PlayerProxy::PlayerProxy( (*this)[Client::kWaitTrackReady] = false; } +void PlayerProxy::update(const std::string &url, const toolkit::mINI &args) { + CHECK(getPoller()->isCurrentThread()); + _pull_url = url; + this->mINI::clear(); + (*this)[Client::kWaitTrackReady] = false; + for (auto &pr : args) { + (*this)[pr.first] = pr.second; + } +} + void PlayerProxy::setPlayCallbackOnce(function cb) { _on_play = std::move(cb); } @@ -99,11 +109,12 @@ static int getMaxTrackSize(const std::string &url) { return 2; } -void PlayerProxy::play(const string &strUrlTmp) { - _option.max_track = getMaxTrackSize(strUrlTmp); +void PlayerProxy::play(const string &url) { + _pull_url = url; + _option.max_track = getMaxTrackSize(_pull_url); weak_ptr weakSelf = shared_from_this(); std::shared_ptr piFailedCnt(new int(0)); // 连续播放失败次数 - setOnPlayResult([weakSelf, strUrlTmp, piFailedCnt](const SockException &err) { + setOnPlayResult([weakSelf, piFailedCnt](const SockException &err) { auto strongSelf = weakSelf.lock(); if (!strongSelf) { return; @@ -131,20 +142,20 @@ void PlayerProxy::play(const string &strUrlTmp) { strongSelf->setTranslationInfo(); strongSelf->_on_connect(strongSelf->_transtalion_info); - InfoL << "play " << strUrlTmp << " success"; + InfoL << "play " << strongSelf->_pull_url << " success"; strongSelf->_status = std::make_shared("playing"); } else if (*piFailedCnt < strongSelf->_retry_count || strongSelf->_retry_count < 0) { // 播放失败,延时重试播放 [AUTO-TRANSLATED:d7537c9c] // Play failed, retry playing with delay strongSelf->_on_disconnect(); - strongSelf->rePlay(strUrlTmp, (*piFailedCnt)++); + strongSelf->rePlay((*piFailedCnt)++); } else { // 达到了最大重试次数,回调关闭 [AUTO-TRANSLATED:610f31f3] // Reached the maximum number of retries, callback to close strongSelf->_on_close(err); } }); - setOnShutdown([weakSelf, strUrlTmp, piFailedCnt](const SockException &err) { + setOnShutdown([weakSelf, piFailedCnt](const SockException &err) { auto strongSelf = weakSelf.lock(); if (!strongSelf) { return; @@ -188,7 +199,7 @@ void PlayerProxy::play(const string &strUrlTmp) { // Play interrupted abnormally, retry playing with delay if (*piFailedCnt < strongSelf->_retry_count || strongSelf->_retry_count < 0) { strongSelf->_repull_count++; - strongSelf->rePlay(strUrlTmp, (*piFailedCnt)++); + strongSelf->rePlay((*piFailedCnt)++); } else { // 达到了最大重试次数,回调关闭 [AUTO-TRANSLATED:610f31f3] // Reached the maximum number of retries, callback to close @@ -197,14 +208,13 @@ void PlayerProxy::play(const string &strUrlTmp) { }); try { _status = std::make_shared("connecting"); - MediaPlayer::play(strUrlTmp); + MediaPlayer::play(_pull_url ); } catch (std::exception &ex) { _status = std::make_shared(std::string("play failed: ") + ex.what()); ErrorL << ex.what(); onPlayResult(SockException(Err_other, ex.what())); return; } - _pull_url = strUrlTmp; setDirectProxy(); } @@ -244,24 +254,21 @@ PlayerProxy::~PlayerProxy() { } } -void PlayerProxy::rePlay(const string &strUrl, int iFailedCnt) { +void PlayerProxy::rePlay(int iFailedCnt) { auto iDelay = MAX(_reconnect_delay_min * 1000, MIN(iFailedCnt * _reconnect_delay_step * 1000, _reconnect_delay_max * 1000)); weak_ptr weakSelf = shared_from_this(); - _timer = std::make_shared( - iDelay / 1000.0f, - [weakSelf, strUrl, iFailedCnt]() { - // 播放失败次数越多,则延时越长 [AUTO-TRANSLATED:5af39264] - // The more times the playback fails, the longer the delay - auto strongPlayer = weakSelf.lock(); - if (!strongPlayer) { - return false; - } - WarnL << "重试播放[" << iFailedCnt << "]:" << strUrl; - strongPlayer->MediaPlayer::play(strUrl); - strongPlayer->setDirectProxy(); + _timer = std::make_shared(iDelay / 1000.0f, [weakSelf, iFailedCnt]() { + // 播放失败次数越多,则延时越长 [AUTO-TRANSLATED:5af39264] + // The more times the playback fails, the longer the delay + auto strongPlayer = weakSelf.lock(); + if (!strongPlayer) { return false; - }, - getPoller()); + } + WarnL << "重试播放[" << iFailedCnt << "]:" << strongPlayer->_pull_url; + strongPlayer->MediaPlayer::play(strongPlayer->_pull_url); + strongPlayer->setDirectProxy(); + return false; + }, getPoller()); } bool PlayerProxy::close(MediaSource &sender) { diff --git a/src/Player/PlayerProxy.h b/src/Player/PlayerProxy.h index fe1f468c..853e6632 100644 --- a/src/Player/PlayerProxy.h +++ b/src/Player/PlayerProxy.h @@ -140,6 +140,8 @@ public: const MediaTuple& getMediaTuple() const { return _tuple; } const ProtocolOption& getOption() const { return _option; } + void update(const std::string &url, const toolkit::mINI &args); + private: // MediaSourceEvent override bool close(MediaSource &sender) override; @@ -150,7 +152,7 @@ private: float getLossRate(MediaSource &sender, TrackType type) override; toolkit::EventPoller::Ptr getOwnerPoller(MediaSource &sender) override; - void rePlay(const std::string &strUrl, int iFailedCnt); + void rePlay(int iFailedCnt); void onPlaySuccess(); void setDirectProxy(); void setTranslationInfo();