diff --git a/submodules/TgVoipWebrtc/Impl/Manager.cpp b/submodules/TgVoipWebrtc/Impl/Manager.cpp index 6ffced3943..3f43b28a99 100644 --- a/submodules/TgVoipWebrtc/Impl/Manager.cpp +++ b/submodules/TgVoipWebrtc/Impl/Manager.cpp @@ -26,8 +26,7 @@ static rtc::Thread *makeMediaThread() { return value.get(); } - -static rtc::Thread *getMediaThread() { +rtc::Thread *Manager::getMediaThread() { static rtc::Thread *value = makeMediaThread(); return value; } @@ -38,6 +37,7 @@ Manager::Manager( bool enableP2P, std::vector const &rtcServers, bool isVideo, + std::shared_ptr videoCapture, std::function stateUpdated, std::function videoStateUpdated, std::function remoteVideoIsActiveUpdated, @@ -48,6 +48,7 @@ _encryptionKey(encryptionKey), _enableP2P(enableP2P), _rtcServers(rtcServers), _startWithVideo(isVideo), +_videoCapture(videoCapture), _stateUpdated(stateUpdated), _videoStateUpdated(videoStateUpdated), _remoteVideoIsActiveUpdated(remoteVideoIsActiveUpdated), @@ -111,11 +112,12 @@ void Manager::start() { ); })); bool isOutgoing = _encryptionKey.isOutgoing; - _mediaManager.reset(new ThreadLocalObject(getMediaThread(), [isOutgoing, thread = _thread, startWithVideo = _startWithVideo, weakThis]() { + _mediaManager.reset(new ThreadLocalObject(getMediaThread(), [isOutgoing, thread = _thread, startWithVideo = _startWithVideo, videoCapture = _videoCapture, weakThis]() { return new MediaManager( getMediaThread(), isOutgoing, startWithVideo, + videoCapture, [thread, weakThis](const rtc::CopyOnWriteBuffer &packet) { thread->PostTask(RTC_FROM_HERE, [weakThis, packet]() { auto strongThis = weakThis.lock(); diff --git a/submodules/TgVoipWebrtc/Impl/Manager.h b/submodules/TgVoipWebrtc/Impl/Manager.h index 79e8583937..7565cf73ea 100644 --- a/submodules/TgVoipWebrtc/Impl/Manager.h +++ b/submodules/TgVoipWebrtc/Impl/Manager.h @@ -12,12 +12,15 @@ namespace TGVOIP_NAMESPACE { class Manager : public std::enable_shared_from_this { public: + static rtc::Thread *getMediaThread(); + Manager( rtc::Thread *thread, TgVoipEncryptionKey encryptionKey, bool enableP2P, std::vector const &rtcServers, bool isVideo, + std::shared_ptr videoCapture, std::function stateUpdated, std::function videoStateUpdated, std::function remoteVideoIsActiveUpdated, @@ -40,6 +43,7 @@ private: bool _enableP2P; std::vector _rtcServers; bool _startWithVideo; + std::shared_ptr _videoCapture; std::function _stateUpdated; std::function _videoStateUpdated; std::function _remoteVideoIsActiveUpdated; diff --git a/submodules/TgVoipWebrtc/Impl/MediaManager.cpp b/submodules/TgVoipWebrtc/Impl/MediaManager.cpp index b1e22eb78f..65fe983313 100644 --- a/submodules/TgVoipWebrtc/Impl/MediaManager.cpp +++ b/submodules/TgVoipWebrtc/Impl/MediaManager.cpp @@ -164,7 +164,7 @@ static rtc::Thread *makeWorkerThread() { } -static rtc::Thread *getWorkerThread() { +static rtc::Thread *MediaManager::getWorkerThread() { static rtc::Thread *value = makeWorkerThread(); return value; } diff --git a/submodules/TgVoipWebrtc/Impl/MediaManager.h b/submodules/TgVoipWebrtc/Impl/MediaManager.h index 5e49c94ff4..9ed8b7819a 100644 --- a/submodules/TgVoipWebrtc/Impl/MediaManager.h +++ b/submodules/TgVoipWebrtc/Impl/MediaManager.h @@ -54,10 +54,13 @@ private: friend class MediaManager::NetworkInterfaceImpl; public: + static rtc::Thread *getWorkerThread(); + MediaManager( rtc::Thread *thread, bool isOutgoing, bool startWithVideo, + std::shared_ptr videoCapture, std::function packetEmitted, std::function localVideoCaptureActiveUpdated ); @@ -99,8 +102,7 @@ private: std::unique_ptr _audioChannel; std::unique_ptr _videoChannel; std::unique_ptr _videoBitrateAllocatorFactory; - rtc::scoped_refptr _nativeVideoSource; - std::unique_ptr _videoCapturer; + std::shared_ptr _videoCapture; std::shared_ptr> _currentIncomingVideoSink; std::shared_ptr> _currentOutgoingVideoSink; diff --git a/submodules/TgVoipWebrtc/Impl/TgVoip.h b/submodules/TgVoipWebrtc/Impl/TgVoip.h index c3be58baf5..463b71caef 100644 --- a/submodules/TgVoipWebrtc/Impl/TgVoip.h +++ b/submodules/TgVoipWebrtc/Impl/TgVoip.h @@ -129,6 +129,16 @@ struct TgVoipAudioDataCallbacks { std::function preprocessed; }; +class TgVoipVideoCaptureInterface { +protected: + TgVoipVideoCaptureInterface() = default; +public: + static std::shared_ptr makeInstance(); + + virtual ~TgVoipVideoCaptureInterface(); + virtual void setVideoOutput(std::shared_ptr> sink) = 0; +}; + class TgVoip { protected: TgVoip() = default; @@ -147,6 +157,7 @@ public: TgVoipNetworkType initialNetworkType, TgVoipEncryptionKey const &encryptionKey, bool isVideo, + std::shared_ptr videoCapture, std::function stateUpdated, std::function videoStateUpdated, std::function remoteVideoIsActiveUpdated, diff --git a/submodules/TgVoipWebrtc/Impl/TgVoip.mm b/submodules/TgVoipWebrtc/Impl/TgVoip.mm index 905f997955..22f5b8d94f 100644 --- a/submodules/TgVoipWebrtc/Impl/TgVoip.mm +++ b/submodules/TgVoipWebrtc/Impl/TgVoip.mm @@ -5,10 +5,19 @@ #include "rtc_base/logging.h" #include "Manager.h" +#include "MediaManager.h" #include #include +#if TARGET_OS_IPHONE + +#include "CodecsApple.h" + +#else +#error "Unsupported platform" +#endif + #import #include @@ -143,6 +152,7 @@ public: TgVoipConfig const &config, TgVoipEncryptionKey const &encryptionKey, bool isVideo, + std::shared_ptr videoCapture, TgVoipNetworkType initialNetworkType, std::function stateUpdated, std::function videoStateUpdated, @@ -160,13 +170,14 @@ public: bool enableP2P = config.enableP2P; - _manager.reset(new ThreadLocalObject(getManagerThread(), [encryptionKey = encryptionKey, enableP2P = enableP2P, isVideo, stateUpdated, videoStateUpdated, remoteVideoIsActiveUpdated, signalingDataEmitted, rtcServers](){ + _manager.reset(new ThreadLocalObject(getManagerThread(), [encryptionKey = encryptionKey, enableP2P = enableP2P, isVideo, stateUpdated, videoStateUpdated, remoteVideoIsActiveUpdated, signalingDataEmitted, rtcServers, videoCapture](){ return new Manager( getManagerThread(), encryptionKey, enableP2P, rtcServers, isVideo, + videoCapture, [stateUpdated](const TgVoipState &state) { stateUpdated(state); }, @@ -388,6 +399,7 @@ TgVoip *TgVoip::makeInstance( TgVoipNetworkType initialNetworkType, TgVoipEncryptionKey const &encryptionKey, bool isVideo, + std::shared_ptr videoCapture, std::function stateUpdated, std::function videoStateUpdated, std::function remoteVideoIsActiveUpdated, @@ -401,6 +413,7 @@ TgVoip *TgVoip::makeInstance( config, encryptionKey, isVideo, + videoCapture, initialNetworkType, stateUpdated, videoStateUpdated, @@ -411,6 +424,78 @@ TgVoip *TgVoip::makeInstance( TgVoip::~TgVoip() = default; +class TgVoipVideoCaptureInterfaceObject { +public: + TgVoipVideoCaptureInterfaceObject() { + _videoSource = makeVideoSource(Manager::getMediaThread(), MediaManager::getWorkerThread()); + //this should outlive the capturer + _videoCapturer = makeVideoCapturer(_videoSource, true, [this](bool isActive) { + if (this->_isActiveUpdated) { + this->_isActiveUpdated(isActive); + } + }); + } + + ~TgVoipVideoCaptureInterfaceObject() { + if (_currentSink != nullptr) { + _videoSource->RemoveSink(_currentSink.get()); + } + } + + void setVideoOutput(std::shared_ptr> sink) { + if (_currentSink != nullptr) { + _videoSource->RemoveSink(_currentSink.get()); + } + _currentSink = sink; + if (_currentSink != nullptr) { + _videoSource->AddOrUpdateSink(_currentSink.get(), rtc::VideoSinkWants()); + } + } + + void setIsActiveUpdated(std::function isActiveUpdated) { + _isActiveUpdated = isActiveUpdated; + } + +public: + rtc::scoped_refptr _videoSource; + std::unique_ptr _videoCapturer; + +private: + std::shared_ptr> _currentSink; + std::function _isActiveUpdated; +}; + +class TgVoipVideoCaptureInterfaceImpl : public TgVoipVideoCaptureInterface { +public: + TgVoipVideoCaptureInterfaceImpl() { + _impl.reset(new ThreadLocalObject( + Manager::getMediaThread(), + []() { + return new TgVoipVideoCaptureInterfaceObject(); + } + )); + } + + virtual ~TgVoipVideoCaptureInterfaceImpl() { + + } + + virtual void setVideoOutput(std::shared_ptr> sink) { + _impl->perform([sink](TgVoipVideoCaptureInterfaceObject *impl) { + impl->setVideoOutput(sink); + }); + } + +public: + std::unique_ptr> _impl; +}; + +std::shared_ptrTgVoipVideoCaptureInterface::makeInstance() { + return std::shared_ptr(new TgVoipVideoCaptureInterfaceImpl()); +} + +TgVoipVideoCaptureInterface::~TgVoipVideoCaptureInterface() = default; + #ifdef TGVOIP_NAMESPACE } #endif diff --git a/submodules/TgVoipWebrtc/Impl/VideoCaptureInterfaceImpl.h b/submodules/TgVoipWebrtc/Impl/VideoCaptureInterfaceImpl.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/submodules/TgVoipWebrtc/Impl/VideoCaptureInterfaceImpl.mm b/submodules/TgVoipWebrtc/Impl/VideoCaptureInterfaceImpl.mm new file mode 100644 index 0000000000..e69de29bb2