1 #include "VideoCaptureInterfaceImpl.h"
2
3 #include "VideoCapturerInterface.h"
4 #include "Manager.h"
5 #include "MediaManager.h"
6 #include "platform/PlatformInterface.h"
7 #include "StaticThreads.h"
8
9 namespace tgcalls {
10
VideoCaptureInterfaceObject(std::string deviceId,bool isScreenCapture,std::shared_ptr<PlatformContext> platformContext,Threads & threads)11 VideoCaptureInterfaceObject::VideoCaptureInterfaceObject(std::string deviceId, bool isScreenCapture, std::shared_ptr<PlatformContext> platformContext, Threads &threads)
12 : _videoSource(PlatformInterface::SharedInstance()->makeVideoSource(threads.getMediaThread(), threads.getWorkerThread())) {
13 _platformContext = platformContext;
14
15 switchToDevice(deviceId, isScreenCapture);
16 }
17
~VideoCaptureInterfaceObject()18 VideoCaptureInterfaceObject::~VideoCaptureInterfaceObject() {
19 if (_videoCapturer) {
20 _videoCapturer->setUncroppedOutput(nullptr);
21 }
22 }
23
source()24 webrtc::VideoTrackSourceInterface *VideoCaptureInterfaceObject::source() {
25 return _videoSource;
26 }
27
getRotation()28 int VideoCaptureInterfaceObject::getRotation() {
29 if (_videoCapturer) {
30 return _videoCapturer->getRotation();
31 } else {
32 return 0;
33 }
34 }
35
isScreenCapture()36 bool VideoCaptureInterfaceObject::isScreenCapture() {
37 return _isScreenCapture;
38 }
39
switchToDevice(std::string deviceId,bool isScreenCapture)40 void VideoCaptureInterfaceObject::switchToDevice(std::string deviceId, bool isScreenCapture) {
41 if (_videoCapturer) {
42 _videoCapturer->setUncroppedOutput(nullptr);
43 }
44 _isScreenCapture = isScreenCapture;
45 if (_videoSource) {
46 //this should outlive the capturer
47 _videoCapturer = nullptr;
48 _videoCapturer = PlatformInterface::SharedInstance()->makeVideoCapturer(_videoSource, deviceId, [this](VideoState state) {
49 if (this->_stateUpdated) {
50 this->_stateUpdated(state);
51 }
52 if (this->_onIsActiveUpdated) {
53 switch (state) {
54 case VideoState::Active: {
55 this->_onIsActiveUpdated(true);
56 break;
57 }
58 default: {
59 this->_onIsActiveUpdated(false);
60 break;
61 }
62 }
63 }
64 }, [this](PlatformCaptureInfo info) {
65 if (this->_shouldBeAdaptedToReceiverAspectRate != info.shouldBeAdaptedToReceiverAspectRate) {
66 this->_shouldBeAdaptedToReceiverAspectRate = info.shouldBeAdaptedToReceiverAspectRate;
67 }
68 if (this->_rotationUpdated) {
69 this->_rotationUpdated(info.rotation);
70 }
71 this->updateAspectRateAdaptation();
72 }, _platformContext, _videoCapturerResolution);
73 }
74 if (_videoCapturer) {
75 if (_preferredAspectRatio > 0) {
76 _videoCapturer->setPreferredCaptureAspectRatio(_preferredAspectRatio);
77 }
78 if (const auto currentUncroppedSink = _currentUncroppedSink.lock()) {
79 _videoCapturer->setUncroppedOutput(currentUncroppedSink);
80 }
81 if (_onFatalError) {
82 _videoCapturer->setOnFatalError(_onFatalError);
83 }
84 if (_onPause) {
85 _videoCapturer->setOnPause(_onPause);
86 }
87 _videoCapturer->setState(_state);
88 }
89 }
90
withNativeImplementation(std::function<void (void *)> completion)91 void VideoCaptureInterfaceObject::withNativeImplementation(std::function<void(void *)> completion) {
92 if (_videoCapturer) {
93 _videoCapturer->withNativeImplementation(completion);
94 } else {
95 completion(nullptr);
96 }
97 }
98
setState(VideoState state)99 void VideoCaptureInterfaceObject::setState(VideoState state) {
100 if (_state != state) {
101 _state = state;
102 if (_videoCapturer) {
103 _videoCapturer->setState(state);
104 }
105 }
106 }
107
setPreferredAspectRatio(float aspectRatio)108 void VideoCaptureInterfaceObject::setPreferredAspectRatio(float aspectRatio) {
109 _preferredAspectRatio = aspectRatio;
110 updateAspectRateAdaptation();
111 }
112
updateAspectRateAdaptation()113 void VideoCaptureInterfaceObject::updateAspectRateAdaptation() {
114 if (_videoCapturer) {
115 if (_videoCapturerResolution.first != 0 && _videoCapturerResolution.second != 0) {
116 if (_preferredAspectRatio > 0.01 && _shouldBeAdaptedToReceiverAspectRate) {
117 float originalWidth = (float)_videoCapturerResolution.first;
118 float originalHeight = (float)_videoCapturerResolution.second;
119
120 float aspectRatio = _preferredAspectRatio;
121
122 float width = (originalWidth > aspectRatio * originalHeight)
123 ? int(std::round(aspectRatio * originalHeight))
124 : originalWidth;
125 float height = (originalWidth > aspectRatio * originalHeight)
126 ? originalHeight
127 : int(std::round(originalHeight / aspectRatio));
128
129 PlatformInterface::SharedInstance()->adaptVideoSource(_videoSource, (int)width, (int)height, 25);
130 } else {
131 PlatformInterface::SharedInstance()->adaptVideoSource(_videoSource, _videoCapturerResolution.first, _videoCapturerResolution.second, 25);
132 }
133 }
134 }
135 }
136
setOutput(std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink)137 void VideoCaptureInterfaceObject::setOutput(std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink) {
138 if (_videoCapturer) {
139 _videoCapturer->setUncroppedOutput(sink);
140 }
141 _currentUncroppedSink = sink;
142 }
143
setOnFatalError(std::function<void ()> error)144 void VideoCaptureInterfaceObject::setOnFatalError(std::function<void()> error) {
145 if (_videoCapturer) {
146 _videoCapturer->setOnFatalError(error);
147 }
148 _onFatalError = error;
149 }
setOnPause(std::function<void (bool)> pause)150 void VideoCaptureInterfaceObject::setOnPause(std::function<void(bool)> pause) {
151 if (_videoCapturer) {
152 _videoCapturer->setOnPause(pause);
153 }
154 _onPause = pause;
155 }
156
setOnIsActiveUpdated(std::function<void (bool)> onIsActiveUpdated)157 void VideoCaptureInterfaceObject::setOnIsActiveUpdated(std::function<void(bool)> onIsActiveUpdated) {
158 _onIsActiveUpdated = onIsActiveUpdated;
159 }
160
setStateUpdated(std::function<void (VideoState)> stateUpdated)161 void VideoCaptureInterfaceObject::setStateUpdated(std::function<void(VideoState)> stateUpdated) {
162 _stateUpdated = stateUpdated;
163 }
164
setRotationUpdated(std::function<void (int)> rotationUpdated)165 void VideoCaptureInterfaceObject::setRotationUpdated(std::function<void(int)> rotationUpdated) {
166 _rotationUpdated = rotationUpdated;
167 }
168
VideoCaptureInterfaceImpl(std::string deviceId,bool isScreenCapture,std::shared_ptr<PlatformContext> platformContext,std::shared_ptr<Threads> threads)169 VideoCaptureInterfaceImpl::VideoCaptureInterfaceImpl(std::string deviceId, bool isScreenCapture, std::shared_ptr<PlatformContext> platformContext, std::shared_ptr<Threads> threads) :
170 _impl(threads->getMediaThread(), [deviceId, isScreenCapture, platformContext, threads]() {
171 return new VideoCaptureInterfaceObject(deviceId, isScreenCapture, platformContext, *threads);
172 }) {
173 }
174
175 VideoCaptureInterfaceImpl::~VideoCaptureInterfaceImpl() = default;
176
switchToDevice(std::string deviceId,bool isScreenCapture)177 void VideoCaptureInterfaceImpl::switchToDevice(std::string deviceId, bool isScreenCapture) {
178 _impl.perform(RTC_FROM_HERE, [deviceId, isScreenCapture](VideoCaptureInterfaceObject *impl) {
179 impl->switchToDevice(deviceId, isScreenCapture);
180 });
181 }
182
withNativeImplementation(std::function<void (void *)> completion)183 void VideoCaptureInterfaceImpl::withNativeImplementation(std::function<void(void *)> completion) {
184 _impl.perform(RTC_FROM_HERE, [completion](VideoCaptureInterfaceObject *impl) {
185 impl->withNativeImplementation(completion);
186 });
187 }
188
setState(VideoState state)189 void VideoCaptureInterfaceImpl::setState(VideoState state) {
190 _impl.perform(RTC_FROM_HERE, [state](VideoCaptureInterfaceObject *impl) {
191 impl->setState(state);
192 });
193 }
194
setPreferredAspectRatio(float aspectRatio)195 void VideoCaptureInterfaceImpl::setPreferredAspectRatio(float aspectRatio) {
196 _impl.perform(RTC_FROM_HERE, [aspectRatio](VideoCaptureInterfaceObject *impl) {
197 impl->setPreferredAspectRatio(aspectRatio);
198 });
199 }
setOnFatalError(std::function<void ()> error)200 void VideoCaptureInterfaceImpl::setOnFatalError(std::function<void()> error) {
201 _impl.perform(RTC_FROM_HERE, [error](VideoCaptureInterfaceObject *impl) {
202 impl->setOnFatalError(error);
203 });
204 }
setOnPause(std::function<void (bool)> pause)205 void VideoCaptureInterfaceImpl::setOnPause(std::function<void(bool)> pause) {
206 _impl.perform(RTC_FROM_HERE, [pause](VideoCaptureInterfaceObject *impl) {
207 impl->setOnPause(pause);
208 });
209 }
210
setOnIsActiveUpdated(std::function<void (bool)> onIsActiveUpdated)211 void VideoCaptureInterfaceImpl::setOnIsActiveUpdated(std::function<void(bool)> onIsActiveUpdated) {
212 _impl.perform(RTC_FROM_HERE, [onIsActiveUpdated](VideoCaptureInterfaceObject *impl) {
213 impl->setOnIsActiveUpdated(onIsActiveUpdated);
214 });
215 }
216
setOutput(std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink)217 void VideoCaptureInterfaceImpl::setOutput(std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink) {
218 _impl.perform(RTC_FROM_HERE, [sink](VideoCaptureInterfaceObject *impl) {
219 impl->setOutput(sink);
220 });
221 }
222
object()223 ThreadLocalObject<VideoCaptureInterfaceObject> *VideoCaptureInterfaceImpl::object() {
224 return &_impl;
225 }
226
227 } // namespace tgcalls
228