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