Skip to content

Commit

Permalink
Fix race in video capture enable / disable.
Browse files Browse the repository at this point in the history
In case we disable video capture and instantly enable video capture,
the PostTask already was invoked in setStateUpdated lambda, so
the later setStateUpdated(nullptr) didn't cancel the sent event.

After that we called instantly setOutgoingVideoState(Active),
and later after that the event was delivered,
calling setOutgoingVideoState(Inactive).

Now we use a separate explicit guard for the event, so that it
won't be delivered after setSTateUpdated(nullptr) call.
  • Loading branch information
john-preston committed Dec 8, 2022
1 parent 923ba8c commit 1c27ba1
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 3 deletions.
13 changes: 10 additions & 3 deletions tgcalls/MediaManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -672,20 +672,27 @@ void MediaManager::setSendVideo(std::shared_ptr<VideoCaptureInterface> videoCapt
const auto wasReceiving = computeIsReceivingVideo();

if (_videoCapture) {
_videoCaptureGuard = nullptr;
GetVideoCaptureAssumingSameThread(_videoCapture.get())->setStateUpdated(nullptr);
}
_videoCapture = videoCapture;
if (_videoCapture) {
_videoCapture->setPreferredAspectRatio(_preferredAspectRatio);

const auto thread = _thread;
const auto weak = std::weak_ptr<MediaManager>(shared_from_this());
const auto object = GetVideoCaptureAssumingSameThread(_videoCapture.get());
_isScreenCapture = object->isScreenCapture();
_videoCaptureGuard = std::make_shared<bool>(true);
const auto guard = std::weak_ptr{ _videoCaptureGuard };
object->setStateUpdated([=](VideoState state) {
thread->PostTask([=] {
if (const auto strong = weak.lock()) {
strong->setOutgoingVideoState(state);
// Checking this special guard instead of weak_ptr(this)
// ensures that we won't call setOutgoingVideoState after
// the _videoCapture was already changed and the old
// stateUpdated was already null-ed, but the event
// at that time was already posted.
if (guard.lock()) {
setOutgoingVideoState(state);
}
});
});
Expand Down
1 change: 1 addition & 0 deletions tgcalls/MediaManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ class MediaManager : public sigslot::has_slots<>, public std::enable_shared_from
std::unique_ptr<cricket::VideoMediaChannel> _videoChannel;
std::unique_ptr<webrtc::VideoBitrateAllocatorFactory> _videoBitrateAllocatorFactory;
std::shared_ptr<VideoCaptureInterface> _videoCapture;
std::shared_ptr<bool> _videoCaptureGuard;
bool _isScreenCapture = false;
std::shared_ptr<VideoSinkInterfaceProxyImpl> _incomingVideoSinkProxy;

Expand Down

0 comments on commit 1c27ba1

Please sign in to comment.