From d0744b3252cc836c83373a2880e0c8c7b5b5f334 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Blin?= <sebastien.blin@savoirfairelinux.com> Date: Thu, 14 Nov 2019 15:35:14 -0500 Subject: [PATCH] video_input: handle EBUSY error from ffmpeg This solves some bugs: + If we have two calls and the client is holding one of these till the other is creating, the camera will start for the second call + If another process is using the camera, Jami will retry to open the camera till the call ends + If one video input runs cleanup() and the other one createDecoder(), the shmPath_ is set back correctly Change-Id: Id6b02e453dffbe0b231884c2942786407af5eac3 --- src/media/video/video_input.cpp | 25 +++++++++++++++++++++---- src/media/video/video_input.h | 1 + 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/media/video/video_input.cpp b/src/media/video/video_input.cpp index 0ebefcca88..8d081330d4 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 f77c717e66..f7f67f0d50 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_; -- GitLab