#include #include "VideoCaptureInterfaceImpl.h" #include "VideoCapturerInterface.h" #include "Manager.h" #include "MediaManager.h" #include "platform/PlatformInterface.h" #include "StaticThreads.h" namespace tgcalls { VideoCaptureInterfaceObject::VideoCaptureInterfaceObject(std::string deviceId, bool isScreenCapture, std::shared_ptr platformContext, Threads &threads) : _videoSource(PlatformInterface::SharedInstance()->makeVideoSource(threads.getMediaThread(), threads.getWorkerThread(), isScreenCapture)) { _platformContext = platformContext; switchToDevice(deviceId, isScreenCapture); } VideoCaptureInterfaceObject::~VideoCaptureInterfaceObject() { if (_videoCapturer && _currentUncroppedSink != nullptr) { _videoCapturer->setUncroppedOutput(nullptr); } } webrtc::VideoTrackSourceInterface *VideoCaptureInterfaceObject::source() { return _videoSource; } int VideoCaptureInterfaceObject::getRotation() { if (_videoCapturer) { return _videoCapturer->getRotation(); } else { return 0; } } bool VideoCaptureInterfaceObject::isScreenCapture() { return _isScreenCapture; } void VideoCaptureInterfaceObject::switchToDevice(std::string deviceId, bool isScreenCapture) { if (_videoCapturer) { _videoCapturer->setUncroppedOutput(nullptr); } _isScreenCapture = isScreenCapture; if (_videoSource) { //this should outlive the capturer _videoCapturer = nullptr; _videoCapturer = PlatformInterface::SharedInstance()->makeVideoCapturer(_videoSource, deviceId, [this](VideoState state) { if (this->_stateUpdated) { this->_stateUpdated(state); } if (this->_onIsActiveUpdated) { switch (state) { case VideoState::Active: { this->_onIsActiveUpdated(true); break; } default: { this->_onIsActiveUpdated(false); break; } } } }, [this](PlatformCaptureInfo info) { if (this->_shouldBeAdaptedToReceiverAspectRate != info.shouldBeAdaptedToReceiverAspectRate) { this->_shouldBeAdaptedToReceiverAspectRate = info.shouldBeAdaptedToReceiverAspectRate; } if (this->_rotationUpdated) { this->_rotationUpdated(info.rotation); } this->updateAspectRateAdaptation(); }, _platformContext, _videoCapturerResolution); } if (_videoCapturer) { // if (_preferredAspectRatio > 0) { // _videoCapturer->setPreferredCaptureAspectRatio(_preferredAspectRatio); // } if (_currentUncroppedSink) { _videoCapturer->setUncroppedOutput(_currentUncroppedSink); } if (_onFatalError) { _videoCapturer->setOnFatalError(_onFatalError); } if (_onPause) { _videoCapturer->setOnPause(_onPause); } _videoCapturer->setState(_state); } } void VideoCaptureInterfaceObject::withNativeImplementation(std::function completion) { if (_videoCapturer) { _videoCapturer->withNativeImplementation(completion); } else { completion(nullptr); } } void VideoCaptureInterfaceObject::setState(VideoState state) { if (_state != state) { _state = state; if (_videoCapturer) { _videoCapturer->setState(state); } } } void VideoCaptureInterfaceObject::setPreferredAspectRatio(float aspectRatio) { _preferredAspectRatio = aspectRatio; updateAspectRateAdaptation(); } void VideoCaptureInterfaceObject::updateAspectRateAdaptation() { if (_videoCapturer) { if (_videoCapturerResolution.first != 0 && _videoCapturerResolution.second != 0) { if (_preferredAspectRatio > 0.01 && _shouldBeAdaptedToReceiverAspectRate) { float originalWidth = (float)_videoCapturerResolution.first; float originalHeight = (float)_videoCapturerResolution.second; float aspectRatio = _preferredAspectRatio; float width = (originalWidth > aspectRatio * originalHeight) ? int(std::round(aspectRatio * originalHeight)) : originalWidth; float height = (originalWidth > aspectRatio * originalHeight) ? originalHeight : int(std::round(originalHeight / aspectRatio)); PlatformInterface::SharedInstance()->adaptVideoSource(_videoSource, (int)width, (int)height, 25); } else { PlatformInterface::SharedInstance()->adaptVideoSource(_videoSource, _videoCapturerResolution.first, _videoCapturerResolution.second, 25); } } } } void VideoCaptureInterfaceObject::setOutput(std::shared_ptr> sink) { if (_videoCapturer) { _videoCapturer->setUncroppedOutput(sink); } _currentUncroppedSink = sink; } void VideoCaptureInterfaceObject::setOnFatalError(std::function error) { if (_videoCapturer) { _videoCapturer->setOnFatalError(error); } _onFatalError = error; } void VideoCaptureInterfaceObject::setOnPause(std::function pause) { if (_videoCapturer) { _videoCapturer->setOnPause(pause); } _onPause = pause; } void VideoCaptureInterfaceObject::setOnIsActiveUpdated(std::function onIsActiveUpdated) { _onIsActiveUpdated = onIsActiveUpdated; } void VideoCaptureInterfaceObject::setStateUpdated(std::function stateUpdated) { _stateUpdated = stateUpdated; } void VideoCaptureInterfaceObject::setRotationUpdated(std::function rotationUpdated) { _rotationUpdated = rotationUpdated; } VideoCaptureInterfaceImpl::VideoCaptureInterfaceImpl(std::string deviceId, bool isScreenCapture, std::shared_ptr platformContext, std::shared_ptr threads) : _platformContext(platformContext), _impl(threads->getMediaThread(), [deviceId, isScreenCapture, platformContext, threads]() { return new VideoCaptureInterfaceObject(deviceId, isScreenCapture, platformContext, *threads); }) { } VideoCaptureInterfaceImpl::~VideoCaptureInterfaceImpl() = default; void VideoCaptureInterfaceImpl::switchToDevice(std::string deviceId, bool isScreenCapture) { _impl.perform(RTC_FROM_HERE, [deviceId, isScreenCapture](VideoCaptureInterfaceObject *impl) { impl->switchToDevice(deviceId, isScreenCapture); }); } void VideoCaptureInterfaceImpl::withNativeImplementation(std::function completion) { _impl.perform(RTC_FROM_HERE, [completion](VideoCaptureInterfaceObject *impl) { impl->withNativeImplementation(completion); }); } void VideoCaptureInterfaceImpl::setState(VideoState state) { _impl.perform(RTC_FROM_HERE, [state](VideoCaptureInterfaceObject *impl) { impl->setState(state); }); } void VideoCaptureInterfaceImpl::setPreferredAspectRatio(float aspectRatio) { _impl.perform(RTC_FROM_HERE, [aspectRatio](VideoCaptureInterfaceObject *impl) { impl->setPreferredAspectRatio(aspectRatio); }); } void VideoCaptureInterfaceImpl::setOnFatalError(std::function error) { _impl.perform(RTC_FROM_HERE, [error](VideoCaptureInterfaceObject *impl) { impl->setOnFatalError(error); }); } void VideoCaptureInterfaceImpl::setOnPause(std::function pause) { _impl.perform(RTC_FROM_HERE, [pause](VideoCaptureInterfaceObject *impl) { impl->setOnPause(pause); }); } void VideoCaptureInterfaceImpl::setOnIsActiveUpdated(std::function onIsActiveUpdated) { _impl.perform(RTC_FROM_HERE, [onIsActiveUpdated](VideoCaptureInterfaceObject *impl) { impl->setOnIsActiveUpdated(onIsActiveUpdated); }); } void VideoCaptureInterfaceImpl::setOutput(std::shared_ptr> sink) { _impl.perform(RTC_FROM_HERE, [sink](VideoCaptureInterfaceObject *impl) { impl->setOutput(sink); }); } std::shared_ptr VideoCaptureInterfaceImpl::getPlatformContext() { return _platformContext; } ThreadLocalObject *VideoCaptureInterfaceImpl::object() { return &_impl; } } // namespace tgcalls