diff --git a/src/media/video/video_input.cpp b/src/media/video/video_input.cpp index 0ebefcca88d37c21a886e5c3c468067160020d97..8d081330d42ec1e08adbe203b5cc31cfd1c86e51 100644 --- a/src/media/video/video_input.cpp +++ b/src/media/video/video_input.cpp @@ -66,6 +66,7 @@ VideoInput::VideoInput() VideoInput::~VideoInput() { + isStopped_ = true; #if VIDEO_CLIENT_INPUT emitSignal<DRing::VideoSignal::StopCapture>(); capturing_ = false; @@ -210,10 +211,26 @@ VideoInput::createDecoder() [](void* data) -> int { return not static_cast<VideoInput*>(data)->isCapturing(); }, this); - if (decoder->openInput(decOpts_) < 0) { - JAMI_ERR("Could not open input \"%s\"", decOpts_.input.c_str()); - foundDecOpts(decOpts_); - return; + bool ready = false, restartSink = false; + while (!ready && !isStopped_) { + // Retry to open the video till the input is opened + auto ret = decoder->openInput(decOpts_); + ready = ret >= 0; + if (ret < 0 && -ret != EBUSY) { + JAMI_ERR("Could not open input \"%s\" with status %i", decOpts_.input.c_str(), ret); + foundDecOpts(decOpts_); + return; + } else if (-ret == EBUSY) { + // If the device is busy, this means that it can be used by another call. + // If this is the case, cleanup() can occurs and this will erase shmPath_ + // So, be sure to regenerate a correct shmPath for clients. + restartSink = true; + } + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + + if (restartSink && !isStopped_) { + sink_->start(); } /* Data available, finish the decoding */ diff --git a/src/media/video/video_input.h b/src/media/video/video_input.h index f77c717e66a45f31db0e9a43eb1027ada4faed91..f7f67f0d509c6ca572ecc3824daaca09ed1daccb 100644 --- a/src/media/video/video_input.h +++ b/src/media/video/video_input.h @@ -85,6 +85,7 @@ private: std::string currentResource_; std::atomic<bool> switchPending_ = {false}; + std::atomic_bool isStopped_ = {false}; DeviceParams decOpts_; std::promise<DeviceParams> foundDecOpts_;