From e39ffbc83c9b76c11257c2f6169046b0baa5be61 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 12 May 2021 14:49:26 +0400 Subject: [PATCH] Update tgcalls, request required video channels. --- .../calls/group/calls_group_call.cpp | 158 +++++++++--------- .../calls/group/calls_group_call.h | 7 +- .../calls/group/calls_group_members.cpp | 52 +++--- .../calls/group/calls_group_members.h | 2 +- Telegram/ThirdParty/tgcalls | 2 +- 5 files changed, 116 insertions(+), 105 deletions(-) diff --git a/Telegram/SourceFiles/calls/group/calls_group_call.cpp b/Telegram/SourceFiles/calls/group/calls_group_call.cpp index 6ad83a6b4..5567d2642 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_call.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_call.cpp @@ -538,6 +538,7 @@ void GroupCall::subscribeToReal(not_null real) { using Update = Data::GroupCall::ParticipantUpdate; real->participantUpdated( ) | rpl::start_with_next([=](const Update &data) { + auto changed = false; auto newLarge = _videoEndpointLarge.current(); auto updateCameraNotStreams = std::string(); auto updateScreenNotStreams = std::string(); @@ -555,6 +556,8 @@ void GroupCall::subscribeToReal(not_null real) { } if (_videoEndpointLarge.current() != newLarge) { setVideoEndpointLarge(newLarge); + } else if (changed) { + updateRequestedVideoChannelsDelayed(); } if (!updateCameraNotStreams.empty()) { _streamsVideoUpdated.fire({ updateCameraNotStreams, false }); @@ -575,13 +578,13 @@ void GroupCall::subscribeToReal(not_null real) { if (!nowCameraEndpoint.empty() && _activeVideoEndpoints.emplace( nowCameraEndpoint, - EndpointType::Camera).second - && _incomingVideoEndpoints.contains(nowCameraEndpoint)) { + EndpointType::Camera).second) { + changed = true; _streamsVideoUpdated.fire({ nowCameraEndpoint, true }); } if (!wasCameraEndpoint.empty() - && _activeVideoEndpoints.remove(wasCameraEndpoint) - && _incomingVideoEndpoints.contains(wasCameraEndpoint)) { + && _activeVideoEndpoints.remove(wasCameraEndpoint)) { + changed = true; updateCameraNotStreams = wasCameraEndpoint; if (newLarge.endpoint == wasCameraEndpoint) { newLarge = VideoEndpoint(); @@ -599,13 +602,13 @@ void GroupCall::subscribeToReal(not_null real) { if (!nowScreenEndpoint.empty() && _activeVideoEndpoints.emplace( nowScreenEndpoint, - EndpointType::Screen).second - && _incomingVideoEndpoints.contains(nowScreenEndpoint)) { + EndpointType::Screen).second) { + changed = true; _streamsVideoUpdated.fire({ nowScreenEndpoint, true }); } if (!wasScreenEndpoint.empty() - && _activeVideoEndpoints.remove(wasScreenEndpoint) - && _incomingVideoEndpoints.contains(wasScreenEndpoint)) { + && _activeVideoEndpoints.remove(wasScreenEndpoint)) { + changed = true; updateScreenNotStreams = wasScreenEndpoint; if (newLarge.endpoint == wasScreenEndpoint) { newLarge = VideoEndpoint(); @@ -872,9 +875,8 @@ void GroupCall::setMyEndpointType( if (endpoint.empty()) { return; } else if (type == EndpointType::None) { - const auto was1 = _incomingVideoEndpoints.remove(endpoint); - const auto was2 = _activeVideoEndpoints.remove(endpoint); - if (was1 && was2) { + const auto was = _activeVideoEndpoints.remove(endpoint); + if (was) { auto newLarge = _videoEndpointLarge.current(); if (newLarge.endpoint == endpoint) { _videoEndpointPinned = false; @@ -883,11 +885,10 @@ void GroupCall::setMyEndpointType( _streamsVideoUpdated.fire({ endpoint, false }); } } else { - const auto now1 = _incomingVideoEndpoints.emplace(endpoint).second; - const auto now2 = _activeVideoEndpoints.emplace( + const auto now = _activeVideoEndpoints.emplace( endpoint, type).second; - if (now1 || now2) { + if (now) { _streamsVideoUpdated.fire({ endpoint, true }); } const auto nowLarge = activeVideoEndpointType( @@ -913,9 +914,6 @@ void GroupCall::setScreenEndpoint(std::string endpoint) { if (_screenEndpoint.empty()) { return; } - if (_instance) { - _instance->setIgnoreVideoEndpointIds({ _screenEndpoint }); - } if (isSharingScreen()) { setMyEndpointType(_screenEndpoint, EndpointType::Screen); } @@ -1014,13 +1012,19 @@ void GroupCall::rejoin(not_null as) { const auto json = QByteArray::fromStdString(payload.json); const auto wasMuteState = muted(); + const auto wasVideoMuted = !isSharingCamera(); using Flag = MTPphone_JoinGroupCall::Flag; + const auto flags = (wasMuteState != MuteState::Active + ? Flag::f_muted + : Flag(0)) + | (_joinHash.isEmpty() + ? Flag(0) + : Flag::f_invite_hash) + | (wasVideoMuted + ? Flag::f_video_muted + : Flag(0)); _api.request(MTPphone_JoinGroupCall( - MTP_flags((wasMuteState != MuteState::Active - ? Flag::f_muted - : Flag(0)) | (_joinHash.isEmpty() - ? Flag(0) - : Flag::f_invite_hash)), + MTP_flags(flags), inputCall(), _joinAs->input, MTP_string(_joinHash), @@ -1037,7 +1041,9 @@ void GroupCall::rejoin(not_null as) { _peer->session().api().applyUpdates(updates); applyQueuedSelfUpdates(); checkFirstTimeJoined(); - sendSelfUpdate(SendUpdateType::VideoMuted); + if (wasVideoMuted == isSharingCamera()) { + sendSelfUpdate(SendUpdateType::VideoMuted); + } if (_screenSsrc && isSharingScreen()) { LOG(("Call Info: Screen rejoin after rejoin().")); rejoinPresentation(); @@ -1452,8 +1458,9 @@ void GroupCall::handlePossibleCreateOrJoinResponse( const auto json = data.vdata().v; setCameraEndpoint(ParseVideoEndpoint(json)); _instance->setJoinResponsePayload(json.toStdString()); + updateRequestedVideoChannels(); + checkMediaChannelDescriptions(); }); - checkMediaChannelDescriptions(); } } @@ -1800,12 +1807,6 @@ void GroupCall::ensureControllerCreated() { .createAudioDeviceModule = Webrtc::AudioDeviceModuleCreator( settings.callAudioBackend()), .videoCapture = _cameraCapture, - .incomingVideoSourcesUpdated = [=]( - std::vector endpointIds) { - crl::on_main(weak, [=, endpoints = std::move(endpointIds)] { - setIncomingVideoEndpoints(endpoints); - }); - }, .requestBroadcastPart = [=, call = base::make_weak(this)]( int64_t time, int64_t period, @@ -1854,9 +1855,10 @@ void GroupCall::ensureControllerCreated() { _instance = std::make_unique( std::move(descriptor)); - _videoEndpointLarge.changes( + _videoEndpointLarge.value( ) | rpl::start_with_next([=](const VideoEndpoint &endpoint) { - _instance->setFullSizeVideoEndpointId(endpoint.endpoint); + updateRequestedVideoChannels(); + _videoLargeTrack = LargeTrack(); _videoLargeTrackWrap = nullptr; if (!endpoint) { @@ -1873,10 +1875,6 @@ void GroupCall::ensureControllerCreated() { updateInstanceMuteState(); updateInstanceVolumes(); - - if (!_screenEndpoint.empty()) { - _instance->setIgnoreVideoEndpointIds({ _screenEndpoint }); - } //raw->setAudioOutputDuckingEnabled(settings.callAudioDuckingEnabled()); } @@ -2071,43 +2069,52 @@ void GroupCall::mediaChannelDescriptionsCancel( } } -void GroupCall::setIncomingVideoEndpoints( - const std::vector &endpoints) { - auto newLarge = _videoEndpointLarge.current(); - auto newLargeFound = false; - auto removed = _incomingVideoEndpoints; - const auto feedOne = [&](const std::string &endpoint) { - if (endpoint.empty()) { - return; - } else if (endpoint == newLarge.endpoint) { - newLargeFound = true; - } - if (!removed.remove(endpoint)) { - _incomingVideoEndpoints.emplace(endpoint); - if (_activeVideoEndpoints.contains(endpoint)) { - _streamsVideoUpdated.fire({ endpoint, true }); - } - } - }; - for (const auto &endpoint : endpoints) { - if (endpoint != _cameraEndpoint && endpoint != _screenEndpoint) { - feedOne(endpoint); - } +void GroupCall::updateRequestedVideoChannels() { + _requestedVideoChannelsUpdateScheduled = false; + const auto real = lookupReal(); + if (!real || !_instance) { + return; } - feedOne(cameraSharingEndpoint()); - feedOne(screenSharingEndpoint()); - if (newLarge && !newLargeFound) { - _videoEndpointPinned = false; - newLarge = VideoEndpoint(); - } - if (newLarge.empty()) { - setVideoEndpointLarge(chooseLargeVideoEndpoint()); - } - for (const auto &endpoint : removed) { - if (_activeVideoEndpoints.contains(endpoint)) { - _streamsVideoUpdated.fire({ endpoint, false }); + auto channels = std::vector(); + using Quality = tgcalls::VideoChannelDescription::Quality; + channels.reserve(_activeVideoEndpoints.size()); + const auto &camera = cameraSharingEndpoint(); + const auto &screen = screenSharingEndpoint(); + const auto &large = _videoEndpointLarge.current().endpoint; + for (const auto &[endpoint, endpointType] : _activeVideoEndpoints) { + if (endpoint == camera || endpoint == screen) { + continue; } + const auto participant = real->participantByEndpoint(endpoint); + const auto params = (participant && participant->ssrc) + ? participant->videoParams.get() + : nullptr; + if (!params) { + continue; + } + channels.push_back({ + .audioSsrc = participant->ssrc, + .videoInformation = (params->camera.endpoint == endpoint + ? params->camera.json.toStdString() + : params->screen.json.toStdString()), + .quality = (endpoint == large + ? Quality::Full + : Quality::Thumbnail), + }); } + _instance->setRequestedVideoChannels(std::move(channels)); +} + +void GroupCall::updateRequestedVideoChannelsDelayed() { + if (_requestedVideoChannelsUpdateScheduled) { + return; + } + _requestedVideoChannelsUpdateScheduled = true; + crl::on_main(this, [=] { + if (_requestedVideoChannelsUpdateScheduled) { + updateRequestedVideoChannels(); + } + }); } void GroupCall::fillActiveVideoEndpoints() { @@ -2128,9 +2135,7 @@ void GroupCall::fillActiveVideoEndpoints() { } if (!removed.remove(endpoint)) { _activeVideoEndpoints.emplace(endpoint, type); - if (_incomingVideoEndpoints.contains(endpoint)) { - _streamsVideoUpdated.fire({ endpoint, true }); - } + _streamsVideoUpdated.fire({ endpoint, true }); } }; for (const auto &participant : participants) { @@ -2157,6 +2162,7 @@ void GroupCall::fillActiveVideoEndpoints() { _streamsVideoUpdated.fire({ endpoint, false }); } } + updateRequestedVideoChannels(); } GroupCall::EndpointType GroupCall::activeVideoEndpointType( @@ -2182,10 +2188,8 @@ VideoEndpoint GroupCall::chooseLargeVideoEndpoint() const { const auto &myCameraEndpoint = cameraSharingEndpoint(); const auto &myScreenEndpoint = screenSharingEndpoint(); const auto &participants = real->participants(); - for (const auto &endpoint : _incomingVideoEndpoints) { - if (!_activeVideoEndpoints.contains(endpoint) - || endpoint == _cameraEndpoint - || endpoint == _screenEndpoint) { + for (const auto &[endpoint, endpointType] : _activeVideoEndpoints) { + if (endpoint == _cameraEndpoint || endpoint == _screenEndpoint) { continue; } if (const auto participant = real->participantByEndpoint(endpoint)) { diff --git a/Telegram/SourceFiles/calls/group/calls_group_call.h b/Telegram/SourceFiles/calls/group/calls_group_call.h index f78e17098..72e53033a 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_call.h +++ b/Telegram/SourceFiles/calls/group/calls_group_call.h @@ -280,7 +280,6 @@ public: } [[nodiscard]] bool streamsVideo(const std::string &endpoint) const { return !endpoint.empty() - && _incomingVideoEndpoints.contains(endpoint) && activeVideoEndpointType(endpoint) != EndpointType::None; } [[nodiscard]] bool videoEndpointPinned() const { @@ -446,8 +445,8 @@ private: void stopConnectingSound(); void playConnectingSoundOnce(); - void setIncomingVideoEndpoints( - const std::vector &endpoints); + void updateRequestedVideoChannels(); + void updateRequestedVideoChannelsDelayed(); void fillActiveVideoEndpoints(); [[nodiscard]] VideoEndpoint chooseLargeVideoEndpoint() const; [[nodiscard]] EndpointType activeVideoEndpointType( @@ -484,6 +483,7 @@ private: rpl::variable _state = State::Creating; base::flat_set _unresolvedSsrcs; bool _recordingStoppedByMe = false; + bool _requestedVideoChannelsUpdateScheduled = false; MTP::DcId _broadcastDcId = 0; base::flat_map, LoadingPart> _broadcastParts; @@ -537,7 +537,6 @@ private: rpl::event_stream _levelUpdates; rpl::event_stream _streamsVideoUpdated; - base::flat_set _incomingVideoEndpoints; base::flat_map _activeVideoEndpoints; rpl::variable _videoEndpointLarge; rpl::variable _videoEndpointPinned; diff --git a/Telegram/SourceFiles/calls/group/calls_group_members.cpp b/Telegram/SourceFiles/calls/group/calls_group_members.cpp index e19e38707..f1557eeed 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_members.cpp +++ b/Telegram/SourceFiles/calls/group/calls_group_members.cpp @@ -221,8 +221,6 @@ Members::Controller::Controller( ImageRoundRadius::Large, st::groupCallMembersBgOver) , _narrowRoundRect(ImageRoundRadius::Large, st::groupCallMembersBg) { - setupListChangeViewers(); - style::PaletteChanged( ) | rpl::start_with_next([=] { _inactiveCrossLine.invalidate(); @@ -304,12 +302,12 @@ void Members::Controller::setupListChangeViewers() { subscribeToChanges(real); }, _lifetime); - _call->stateValue( - ) | rpl::start_with_next([=] { - if (const auto real = _call->lookupReal()) { - //updateRow(channel->session().user()); - } - }, _lifetime); + //_call->stateValue( + //) | rpl::start_with_next([=] { + // if (const auto real = _call->lookupReal()) { + // updateRow(channel->session().user()); + // } + //}, _lifetime); _call->levelUpdates( ) | rpl::start_with_next([=](const LevelUpdate &update) { @@ -769,6 +767,8 @@ void Members::Controller::prepare() { loadMoreRows(); appendInvitedUsers(); _prepared = true; + + setupListChangeViewers(); } bool Members::Controller::isMe(not_null participantPeer) const { @@ -1435,6 +1435,14 @@ std::unique_ptr Members::Controller::createRow( const Data::GroupCallParticipant &participant) { auto result = std::make_unique(this, participant.peer); updateRow(result.get(), &participant); + + const auto &camera = computeCameraEndpoint(&participant); + const auto &screen = computeScreenEndpoint(&participant); + if (!screen.empty() && _largeEndpoint != screen) { + setRowVideoEndpoint(result.get(), screen); + } else if (!camera.empty() && _largeEndpoint != camera) { + setRowVideoEndpoint(result.get(), camera); + } return result; } @@ -1457,25 +1465,13 @@ Members::Members( , _listController(std::make_unique(call, parent)) , _layout(_scroll->setOwnedWidget( object_ptr(_scroll.data()))) -, _pinnedVideoWrap(_layout->add(object_ptr(_layout.get()))) -, _pinnedVideo( - std::make_unique( - _pinnedVideoWrap.get(), - st::groupCallLargeVideoNarrow, - true, - _call->videoLargeTrackValue( - ) | rpl::map([=](GroupCall::LargeTrack track) { - const auto row = track ? lookupRow(track.peer) : nullptr; - Assert(!track || row != nullptr); - return LargeVideoTrack{ row ? track.track : nullptr, row }; - }), - _call->videoEndpointPinnedValue())) { +, _pinnedVideoWrap(_layout->add(object_ptr(_layout.get()))) { setupAddMember(call); setupList(); - setupPinnedVideo(); setContent(_list); setupFakeRoundCorners(); _listController->setDelegate(static_cast(this)); + setupPinnedVideo(); } Members::~Members() = default; @@ -1652,6 +1648,18 @@ void Members::setupList() { void Members::setupPinnedVideo() { using namespace rpl::mappers; + _pinnedVideo = std::make_unique( + _pinnedVideoWrap.get(), + st::groupCallLargeVideoNarrow, + true, + _call->videoLargeTrackValue( + ) | rpl::map([=](GroupCall::LargeTrack track) { + const auto row = track ? lookupRow(track.peer) : nullptr; + Assert(!track || row != nullptr); + return LargeVideoTrack{ row ? track.track : nullptr, row }; + }), + _call->videoEndpointPinnedValue()); + _pinnedVideo->pinToggled( ) | rpl::start_with_next([=](bool pinned) { if (!pinned) { diff --git a/Telegram/SourceFiles/calls/group/calls_group_members.h b/Telegram/SourceFiles/calls/group/calls_group_members.h index 3ab0a19b3..c33fd1771 100644 --- a/Telegram/SourceFiles/calls/group/calls_group_members.h +++ b/Telegram/SourceFiles/calls/group/calls_group_members.h @@ -94,7 +94,7 @@ private: std::unique_ptr _listController; not_null _layout; const not_null _pinnedVideoWrap; - const std::unique_ptr _pinnedVideo; + std::unique_ptr _pinnedVideo; rpl::variable _addMemberButton = nullptr; ListWidget *_list = nullptr; rpl::event_stream<> _addMemberRequests; diff --git a/Telegram/ThirdParty/tgcalls b/Telegram/ThirdParty/tgcalls index 9a2b95507..a362d24ee 160000 --- a/Telegram/ThirdParty/tgcalls +++ b/Telegram/ThirdParty/tgcalls @@ -1 +1 @@ -Subproject commit 9a2b95507fe19de2e969517453ae0874fbe1ae62 +Subproject commit a362d24ee97ed1a5c2e3a82656e897adf3354613