diff --git a/daemon/src/media/video/video_input.cpp b/daemon/src/media/video/video_input.cpp index a9483cbe9d6e30d8f775acd71ce40ecc255f1a84..e9d12236de32857eda0f07f9d57e07dded1c8ba6 100644 --- a/daemon/src/media/video/video_input.cpp +++ b/daemon/src/media/video/video_input.cpp @@ -275,9 +275,12 @@ VideoInput::initFile(std::string path) return true; } -std::future<DeviceParams> +std::shared_future<DeviceParams> VideoInput::switchInput(const std::string& resource) { + if (resource == currentResource_) + return futureDecOpts_; + RING_DBG("MRL: '%s'", resource.c_str()); if (switchPending_) { @@ -285,6 +288,8 @@ VideoInput::switchInput(const std::string& resource) return {}; } + currentResource_ = resource; + std::promise<DeviceParams> p; foundDecOpts_.swap(p); @@ -294,7 +299,8 @@ VideoInput::switchInput(const std::string& resource) switchPending_ = true; if (!loop_.isRunning()) loop_.start(); - return foundDecOpts_.get_future(); + futureDecOpts_ = foundDecOpts_.get_future(); + return futureDecOpts_; } // Supported MRL schemes @@ -323,16 +329,17 @@ VideoInput::switchInput(const std::string& resource) valid = initFile(suffix); } - /* Unsupported MRL or failed initialization */ - if (valid) { - switchPending_ = true; - if (!loop_.isRunning()) - loop_.start(); - } - else + // Unsupported MRL or failed initialization + if (not valid) { RING_ERR("Failed to init input for MRL '%s'\n", resource.c_str()); + return {}; + } - return valid ? foundDecOpts_.get_future() : std::future<DeviceParams> {}; + switchPending_ = true; + if (!loop_.isRunning()) + loop_.start(); + futureDecOpts_ = foundDecOpts_.get_future().share(); + return futureDecOpts_; } int VideoInput::getWidth() const diff --git a/daemon/src/media/video/video_input.h b/daemon/src/media/video/video_input.h index 0e4610ea978566d5ad39bcbcfbb9edede247f139..8cada82677c3eabce229c74fed9f166cdd5954cc 100644 --- a/daemon/src/media/video/video_input.h +++ b/daemon/src/media/video/video_input.h @@ -63,17 +63,20 @@ public: int getPixelFormat() const; DeviceParams getParams() const; - std::future<DeviceParams> switchInput(const std::string& resource); + std::shared_future<DeviceParams> switchInput(const std::string& resource); private: NON_COPYABLE(VideoInput); + std::string currentResource_; + MediaDecoder *decoder_ = nullptr; std::shared_ptr<SinkClient> sink_; std::atomic<bool> switchPending_ = {false}; DeviceParams decOpts_; std::promise<DeviceParams> foundDecOpts_; + std::shared_future<DeviceParams> futureDecOpts_; bool emulateRate_ = false; ThreadLoop loop_; diff --git a/daemon/src/media/video/video_rtp_session.cpp b/daemon/src/media/video/video_rtp_session.cpp index 3db519a20afe550a39012711495f32e0a0dd5e4e..22877c6a50f44475935be318a89ae0de318e3db5 100644 --- a/daemon/src/media/video/video_rtp_session.cpp +++ b/daemon/src/media/video/video_rtp_session.cpp @@ -49,6 +49,8 @@ namespace ring { namespace video { using std::map; using std::string; +constexpr static auto NEWPARAMS_TIMEOUT = std::chrono::milliseconds(1000); + VideoRtpSession::VideoRtpSession(const string &callID, const DeviceParams& localVideoParams) : RtpSession(callID), localVideoParams_(localVideoParams) @@ -68,12 +70,12 @@ void VideoRtpSession::startSender() RING_WARN("Restarting video sender"); } - std::future<DeviceParams> newParams; if (not conference_) { videoLocal_ = getVideoCamera(); if (auto input = videoManager.videoInput.lock()) { - newParams = input->switchInput(input_); - if (newParams.valid()) + auto newParams = input->switchInput(input_); + if (newParams.valid() && + newParams.wait_for(NEWPARAMS_TIMEOUT) == std::future_status::ready) localVideoParams_ = newParams.get(); else RING_WARN("No valid new video parameters.");