From 38cb1b195ddde799dd2cb44a347369dc75cbebaf Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 16 Apr 2021 18:15:56 +0400 Subject: [PATCH] Add proof-of-concept screen sharing on Windows. --- .../SourceFiles/calls/calls_group_call.cpp | 85 ++++++++++++++----- Telegram/SourceFiles/calls/calls_group_call.h | 9 ++ .../SourceFiles/calls/calls_group_panel.cpp | 7 +- Telegram/ThirdParty/tgcalls | 2 +- Telegram/cmake/lib_tgcalls.cmake | 32 +++++++ 5 files changed, 111 insertions(+), 24 deletions(-) diff --git a/Telegram/SourceFiles/calls/calls_group_call.cpp b/Telegram/SourceFiles/calls/calls_group_call.cpp index ece53bff9d..fb47c903ce 100644 --- a/Telegram/SourceFiles/calls/calls_group_call.cpp +++ b/Telegram/SourceFiles/calls/calls_group_call.cpp @@ -368,6 +368,9 @@ GroupCall::GroupCall( _realChanges.fire_copy(real); }, _lifetime); } + + setupMediaDevices(); + if (_id) { join(inputCall); } else { @@ -376,26 +379,31 @@ GroupCall::GroupCall( if (_scheduleDate) { saveDefaultJoinAs(_joinAs); } - - _mediaDevices->audioInputId( - ) | rpl::start_with_next([=](QString id) { - _audioInputId = id; - if (_instance) { - _instance->setAudioInputDevice(id.toStdString()); - } - }, _lifetime); - - _mediaDevices->audioOutputId( - ) | rpl::start_with_next([=](QString id) { - _audioOutputId = id; - if (_instance) { - _instance->setAudioOutputDevice(id.toStdString()); - } - }, _lifetime); } GroupCall::~GroupCall() { destroyController(); + switchToCamera(); +} + +bool GroupCall::isScreenSharing() const { + return (_videoDeviceId != _videoInputId); +} + +void GroupCall::switchToCamera() { + if (!_videoCapture || !isScreenSharing()) { + return; + } + _videoDeviceId = _videoInputId; + _videoCapture->switchToDevice(_videoDeviceId.toStdString()); +} + +void GroupCall::switchToScreenSharing() { + if (isScreenSharing()) { + return; + } + _videoDeviceId = "desktop_capturer_"; + _videoCapture->switchToDevice(_videoDeviceId.toStdString()); } void GroupCall::setScheduledDate(TimeId date) { @@ -1322,6 +1330,41 @@ void GroupCall::applyOtherParticipantUpdate( }); } +void GroupCall::setupMediaDevices() { + _mediaDevices->audioInputId( + ) | rpl::start_with_next([=](QString id) { + _audioInputId = id; + if (_instance) { + _instance->setAudioInputDevice(id.toStdString()); + } + }, _lifetime); + + _mediaDevices->audioOutputId( + ) | rpl::start_with_next([=](QString id) { + _audioOutputId = id; + if (_instance) { + _instance->setAudioOutputDevice(id.toStdString()); + } + }, _lifetime); + + _mediaDevices->videoInputId( + ) | rpl::start_with_next([=](QString id) { + const auto usedCamera = !isScreenSharing(); + _videoInputId = id; + if (_videoCapture && usedCamera) { + _videoCapture->switchToDevice(_videoDeviceId.toStdString()); + } + }, _lifetime); + setupOutgoingVideo(); +} + +void GroupCall::setupOutgoingVideo() { + _videoCapture = _delegate->groupCallGetVideoCapture(); + _videoOutgoing->setState(Webrtc::VideoState::Active); + _videoCapture->setOutput(_videoOutgoing->sink()); + _videoDeviceId = _videoInputId; +} + void GroupCall::changeTitle(const QString &title) { const auto real = lookupReal(); if (!real || real->title() == title) { @@ -1372,12 +1415,6 @@ void GroupCall::ensureControllerCreated() { } const auto &settings = Core::App().settings(); - if (!_videoCapture) { - _videoCapture = _delegate->groupCallGetVideoCapture(); - _videoOutgoing->setState(Webrtc::VideoState::Active); - _videoCapture->setOutput(_videoOutgoing->sink()); - } - const auto weak = base::make_weak(this); const auto myLevel = std::make_shared(); tgcalls::GroupInstanceDescriptor descriptor = { @@ -1821,6 +1858,10 @@ void GroupCall::setCurrentAudioDevice(bool input, const QString &deviceId) { } } +void GroupCall::setCurrentVideoDevice(const QString &deviceId) { + _mediaDevices->switchToVideoInput(deviceId); +} + void GroupCall::toggleMute(const Group::MuteRequest &data) { if (data.locallyOnly) { applyParticipantLocally(data.peer, data.mute, std::nullopt); diff --git a/Telegram/SourceFiles/calls/calls_group_call.h b/Telegram/SourceFiles/calls/calls_group_call.h index c1173780f8..e88f7c20dd 100644 --- a/Telegram/SourceFiles/calls/calls_group_call.h +++ b/Telegram/SourceFiles/calls/calls_group_call.h @@ -209,6 +209,10 @@ public: static constexpr auto kSpeakLevelThreshold = 0.2; void setCurrentAudioDevice(bool input, const QString &deviceId); + void setCurrentVideoDevice(const QString &deviceId); + bool isScreenSharing() const; + void switchToCamera(); + void switchToScreenSharing(); //void setAudioVolume(bool input, float level); void setAudioDuckingEnabled(bool enabled); @@ -314,6 +318,9 @@ private: void applySelfUpdate(const MTPDgroupCallParticipant &data); void applyOtherParticipantUpdate(const MTPDgroupCallParticipant &data); + void setupMediaDevices(); + void setupOutgoingVideo(); + [[nodiscard]] MTPInputGroupCall inputCall() const; const not_null _delegate; @@ -377,6 +384,8 @@ private: std::unique_ptr _mediaDevices; QString _audioInputId; QString _audioOutputId; + QString _videoInputId; + QString _videoDeviceId; rpl::lifetime _lifetime; diff --git a/Telegram/SourceFiles/calls/calls_group_panel.cpp b/Telegram/SourceFiles/calls/calls_group_panel.cpp index caa7009531..7767c20291 100644 --- a/Telegram/SourceFiles/calls/calls_group_panel.cpp +++ b/Telegram/SourceFiles/calls/calls_group_panel.cpp @@ -673,7 +673,12 @@ void Panel::refreshLeftButton() { _share.destroy(); _settings.create(widget(), st::groupCallSettings); _settings->setClickedCallback([=] { - _layerBg->showBox(Box(SettingsBox, _call)); + if (_call->isScreenSharing()) { + _call->switchToCamera(); + } else { + _call->switchToScreenSharing(); + } + //_layerBg->showBox(Box(SettingsBox, _call)); }); _settings->setText(tr::lng_group_call_settings()); } diff --git a/Telegram/ThirdParty/tgcalls b/Telegram/ThirdParty/tgcalls index cdd2803ad4..082b938cbf 160000 --- a/Telegram/ThirdParty/tgcalls +++ b/Telegram/ThirdParty/tgcalls @@ -1 +1 @@ -Subproject commit cdd2803ad40cbba455f64ee93bc434698afc2e06 +Subproject commit 082b938cbfef6539bdf6b71f9b46f9c2b2880d24 diff --git a/Telegram/cmake/lib_tgcalls.cmake b/Telegram/cmake/lib_tgcalls.cmake index f417f963da..0d870dadec 100644 --- a/Telegram/cmake/lib_tgcalls.cmake +++ b/Telegram/cmake/lib_tgcalls.cmake @@ -56,6 +56,19 @@ PRIVATE VideoCaptureInterfaceImpl.h VideoCapturerInterface.h + # Desktop capturer + desktop_capturer/DesktopCaptureSource.h + desktop_capturer/DesktopCaptureSource.mm + desktop_capturer/DesktopCaptureSourceHelper.h + desktop_capturer/DesktopCaptureSourceHelper.mm + desktop_capturer/DesktopCaptureSourceManager.h + desktop_capturer/DesktopCaptureSourceManager.mm + desktop_capturer/DesktopCaptureSourceView.h + desktop_capturer/DesktopCaptureSourceView.mm + desktop_capturer/DesktopSharingCapturer.h + desktop_capturer/DesktopSharingCapturer.mm + + # Group calls group/GroupInstanceCustomImpl.cpp group/GroupInstanceCustomImpl.h group/GroupNetworkManager.cpp @@ -80,6 +93,8 @@ PRIVATE platform/darwin/DarwinInterface.mm platform/darwin/GLVideoView.h platform/darwin/GLVideoView.mm + platform/darwin/GLVideoViewMac.h + platform/darwin/GLVideoViewMac.mm platform/darwin/TGRTCCVPixelBuffer.h platform/darwin/TGRTCCVPixelBuffer.mm platform/darwin/TGRTCDefaultVideoDecoderFactory.h @@ -108,6 +123,8 @@ PRIVATE # POSIX # Teleram Desktop + platform/tdesktop/DesktopCapturer.cpp + platform/tdesktop/DesktopCapturer.h platform/tdesktop/DesktopInterface.cpp platform/tdesktop/DesktopInterface.h platform/tdesktop/VideoCapturerInterfaceImpl.cpp @@ -122,6 +139,19 @@ PRIVATE reference/InstanceImplReference.h ) +remove_target_sources(lib_tgcalls ${tgcalls_loc} + desktop_capturer/DesktopCaptureSource.h + desktop_capturer/DesktopCaptureSource.mm + desktop_capturer/DesktopCaptureSourceHelper.h + desktop_capturer/DesktopCaptureSourceHelper.mm + desktop_capturer/DesktopCaptureSourceManager.h + desktop_capturer/DesktopCaptureSourceManager.mm + desktop_capturer/DesktopCaptureSourceView.h + desktop_capturer/DesktopCaptureSourceView.mm + desktop_capturer/DesktopSharingCapturer.h + desktop_capturer/DesktopSharingCapturer.mm +) + target_link_libraries(lib_tgcalls PRIVATE desktop-app::external_webrtc @@ -152,6 +182,8 @@ elseif (APPLE) remove_target_sources(lib_tgcalls ${tgcalls_loc} platform/darwin/GLVideoView.h platform/darwin/GLVideoView.mm + platform/darwin/GLVideoViewMac.h + platform/darwin/GLVideoViewMac.mm platform/darwin/VideoCameraCapturer.h platform/darwin/VideoCameraCapturer.mm platform/darwin/VideoMetalView.h