diff --git a/Telegram/SourceFiles/calls/group/calls_group_call.cpp b/Telegram/SourceFiles/calls/group/calls_group_call.cpp index ee230fb8a..50ca9d3a7 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_call.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_call.cpp @@ -496,6 +496,14 @@ void GroupCall::toggleScreenSharing(std::optional uniqueId) { } } +bool GroupCall::hasVideoWithFrames() const { + return _hasVideoWithFrames.current(); +} + +rpl::producer GroupCall::hasVideoWithFramesValue() const { + return _hasVideoWithFrames.value(); +} + void GroupCall::setScheduledDate(TimeId date) { const auto was = _scheduleDate; _scheduleDate = date; @@ -801,6 +809,7 @@ void GroupCall::markEndpointActive(VideoEndpoint endpoint, bool active) { if (!changed) { return; } + auto hasVideoWithFrames = _hasVideoWithFrames.current(); if (active) { const auto i = _activeVideoTracks.emplace( endpoint, @@ -810,15 +819,33 @@ void GroupCall::markEndpointActive(VideoEndpoint endpoint, bool active) { _requireARGB32), .peer = endpoint.peer, }).first; - addVideoOutput(i->first.id, { i->second.track->sink() }); + const auto track = i->second.track.get(); + track->renderNextFrame( + ) | rpl::start_with_next([=] { + if (!track->frameSize().isEmpty()) { + _hasVideoWithFrames = true; + } + }, i->second.lifetime); + if (!track->frameSize().isEmpty()) { + hasVideoWithFrames = true; + } + addVideoOutput(i->first.id, { track->sink() }); } else { if (_videoEndpointPinned.current() == endpoint) { _videoEndpointPinned = VideoEndpoint(); } _activeVideoTracks.erase(i); + hasVideoWithFrames = false; + for (const auto &[endpoint, track] : _activeVideoTracks) { + if (!track.track->frameSize().isEmpty()) { + hasVideoWithFrames = true; + break; + } + } } updateRequestedVideoChannelsDelayed(); _videoStreamActiveUpdates.fire(std::move(endpoint)); + _hasVideoWithFrames = hasVideoWithFrames; } void GroupCall::rejoin() { @@ -1515,11 +1542,9 @@ void GroupCall::setupMediaDevices() { void GroupCall::ensureOutgoingVideo() { Expects(_id != 0); - if (_videoInited) { + if (_cameraOutgoing) { return; } - _videoInited = true; - _cameraOutgoing = std::make_unique( Webrtc::VideoState::Inactive, _requireARGB32); diff --git a/Telegram/SourceFiles/calls/group/calls_group_call.h b/Telegram/SourceFiles/calls/group/calls_group_call.h index 525e18ef6..8c99c087f 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_call.h +++ b/Telegram/SourceFiles/calls/group/calls_group_call.h @@ -297,13 +297,9 @@ public: return _videoEndpointPinned.value(); } struct VideoTrack { - //VideoTrack(); - //VideoTrack(VideoTrack &&other); - //VideoTrack &operator=(VideoTrack &&other); - //~VideoTrack(); - std::unique_ptr track; PeerData *peer = nullptr; + rpl::lifetime lifetime; Group::VideoQuality quality = Group::VideoQuality(); [[nodiscard]] explicit operator bool() const { @@ -342,6 +338,8 @@ public: [[nodiscard]] QString screenSharingDeviceId() const; void toggleVideo(bool active); void toggleScreenSharing(std::optional uniqueId); + [[nodiscard]] bool hasVideoWithFrames() const; + [[nodiscard]] rpl::producer hasVideoWithFramesValue() const; void toggleMute(const Group::MuteRequest &data); void changeVolume(const Group::VolumeRequest &data); @@ -531,13 +529,13 @@ private: rpl::variable _isSharingScreen = false; QString _screenDeviceId; - bool _videoInited = false; bool _requireARGB32 = true; rpl::event_stream _levelUpdates; rpl::event_stream _videoStreamActiveUpdates; base::flat_map _activeVideoTracks; rpl::variable _videoEndpointPinned; + rpl::variable _hasVideoWithFrames = false; base::flat_map _lastSpoke; rpl::event_stream _rejoinEvents; rpl::event_stream<> _allowedToSpeakNotifications; diff --git a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp index 288c95417..b0674d760 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_panel.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_panel.cpp @@ -400,7 +400,6 @@ Panel::Panel(not_null call) st::groupCallTitle)) #endif // !Q_OS_MAC , _viewport(std::make_unique(widget(), _mode.current())) -, _videoMode(true) // #TODO calls , _mute(std::make_unique( widget(), st::callMuteButton, @@ -556,7 +555,9 @@ void Panel::initWindow() { : Flag::None; }); - _call->videoCallValue( + rpl::combine( + _call->hasVideoWithFramesValue(), + _call->videoCallValue() ) | rpl::start_with_next([=] { updateMode(); }, _window->lifetime()); @@ -1656,7 +1657,7 @@ bool Panel::updateMode() { if (!_viewport) { return false; } - const auto wide = _call->videoCall() + const auto wide = _call->hasVideoWithFrames() && (widget()->width() >= st::groupCallWideModeWidthMin); const auto mode = wide ? PanelMode::Wide : PanelMode::Default; if (_mode.current() == mode) { diff --git a/Telegram/SourceFiles/calls/group/calls_group_panel.h b/Telegram/SourceFiles/calls/group/calls_group_panel.h index 33cb7cbc6..c89f6cbff 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_panel.h +++ b/Telegram/SourceFiles/calls/group/calls_group_panel.h @@ -162,7 +162,6 @@ private: std::shared_ptr _countdownData; object_ptr _startsWhen = { nullptr }; ChooseJoinAsProcess _joinAsProcess; - rpl::variable _videoMode; std::optional _lastSmallGeometry; std::optional _lastLargeGeometry; bool _lastLargeMaximized = false;