1 #include "tgcalls/platform/tdesktop/VideoCapturerInterfaceImpl.h"
2 
3 #include "tgcalls/platform/tdesktop/VideoCapturerTrackSource.h"
4 #include "tgcalls/platform/tdesktop/VideoCameraCapturer.h"
5 
6 #ifndef TGCALLS_UWP_DESKTOP_CAPTURE
7 #include "tgcalls/desktop_capturer/DesktopCaptureSourceHelper.h"
8 #endif // TGCALLS_DISABLE_DESKTOP_CAPTURE
9 
10 #include "api/video_track_source_proxy.h"
11 
12 namespace tgcalls {
13 namespace {
14 
GetSink(const rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> & nativeSource)15 std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> GetSink(
16 	const rtc::scoped_refptr<
17 		webrtc::VideoTrackSourceInterface> &nativeSource) {
18 	const auto proxy = static_cast<webrtc::VideoTrackSourceProxy*>(
19 		nativeSource.get());
20 	const auto internal = static_cast<VideoCapturerTrackSource*>(
21 		proxy->internal());
22 	return internal->sink();
23 }
24 
25 } // namespace
26 
VideoCapturerInterfaceImpl(rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> source,std::string deviceId,std::function<void (VideoState)> stateUpdated,std::shared_ptr<PlatformContext> platformContext,std::pair<int,int> & outResolution)27 VideoCapturerInterfaceImpl::VideoCapturerInterfaceImpl(
28 	rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> source,
29 	std::string deviceId,
30 	std::function<void(VideoState)> stateUpdated,
31 	std::shared_ptr<PlatformContext> platformContext,
32 	std::pair<int, int> &outResolution)
33 : _source(source)
34 , _sink(GetSink(source))
35 , _stateUpdated(stateUpdated) {
36 #ifdef TGCALLS_UWP_DESKTOP_CAPTURE
37 	if (deviceId == "GraphicsCaptureItem")
38 	{
39 		auto uwpContext = std::static_pointer_cast<UwpContext>(platformContext);
40 
41 		_screenCapturer = std::make_unique<UwpScreenCapturer>(_sink, uwpContext->item);
42 		_screenCapturer->setState(VideoState::Active);
43 		outResolution = _screenCapturer->resolution();
44 	}
45 	else
46 #else
47 	if (const auto source = DesktopCaptureSourceForKey(deviceId)) {
48 		const auto data = DesktopCaptureSourceData{
49 			/*.aspectSize = */{ 1280, 720 },
50 			/*.fps = */24.,
51 			/*.captureMouse = */(deviceId != "desktop_capturer_pipewire"),
52 		};
53 		_desktopCapturer = std::make_unique<DesktopCaptureSourceHelper>(
54 			source,
55 			data);
56 		_desktopCapturer->setOutput(_sink);
57 		_desktopCapturer->start();
58 		outResolution = { 1280, 960 };
59 	} else if (!ShouldBeDesktopCapture(deviceId))
60 #endif // TGCALLS_UWP_DESKTOP_CAPTURE
61 	{
62 		_cameraCapturer = std::make_unique<VideoCameraCapturer>(_sink);
63 		_cameraCapturer->setDeviceId(deviceId);
64 		_cameraCapturer->setState(VideoState::Active);
65 		outResolution = _cameraCapturer->resolution();
66 	}
67 }
68 
~VideoCapturerInterfaceImpl()69 VideoCapturerInterfaceImpl::~VideoCapturerInterfaceImpl() {
70 }
71 
setState(VideoState state)72 void VideoCapturerInterfaceImpl::setState(VideoState state) {
73 #ifdef TGCALLS_UWP_DESKTOP_CAPTURE
74 	if (_screenCapturer) {
75 		_screenCapturer->setState(state);
76 	} else
77 #else
78 	if (_desktopCapturer) {
79 		if (state == VideoState::Active) {
80 			_desktopCapturer->start();
81 		} else {
82 			_desktopCapturer->stop();
83 		}
84 	} else
85 #endif // TGCALLS_UWP_DESKTOP_CAPTURE
86 	if (_cameraCapturer) {
87 		_cameraCapturer->setState(state);
88 	}
89 	if (_stateUpdated) {
90 		_stateUpdated(state);
91 	}
92 }
93 
setPreferredCaptureAspectRatio(float aspectRatio)94 void VideoCapturerInterfaceImpl::setPreferredCaptureAspectRatio(
95 		float aspectRatio) {
96 	if (_cameraCapturer) {
97 		_cameraCapturer->setPreferredCaptureAspectRatio(aspectRatio);
98 	}
99 }
100 
setUncroppedOutput(std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink)101 void VideoCapturerInterfaceImpl::setUncroppedOutput(
102 		std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink) {
103 	if (_uncroppedSink != nullptr) {
104 		_source->RemoveSink(_uncroppedSink.get());
105 	}
106 	_uncroppedSink = sink;
107 	if (_uncroppedSink != nullptr) {
108 		_source->AddOrUpdateSink(
109 			_uncroppedSink.get(),
110 			rtc::VideoSinkWants());
111 	}
112 }
113 
setOnFatalError(std::function<void ()> error)114 void VideoCapturerInterfaceImpl::setOnFatalError(std::function<void()> error) {
115 #ifdef TGCALLS_UWP_DESKTOP_CAPTURE
116 	if (_screenCapturer) {
117 		_screenCapturer->setOnFatalError(std::move(error));
118 	} else if (!_screenCapturer && !_cameraCapturer && error) {
119 		error();
120 	}
121 #else // TGCALLS_UWP_DESKTOP_CAPTURE
122 	if (_desktopCapturer) {
123 		_desktopCapturer->setOnFatalError(std::move(error));
124 	} else if (!_desktopCapturer && !_cameraCapturer && error) {
125 		error();
126 	}
127 #endif // TGCALLS_UWP_DESKTOP_CAPTURE
128 	if (_cameraCapturer) {
129 		_cameraCapturer->setOnFatalError(std::move(error));
130 	}
131 }
132 
setOnPause(std::function<void (bool)> pause)133 void VideoCapturerInterfaceImpl::setOnPause(std::function<void(bool)> pause) {
134 #ifdef TGCALLS_UWP_DESKTOP_CAPTURE
135 	if (_screenCapturer) {
136 		_screenCapturer->setOnPause(std::move(pause));
137 	}
138 #else // TGCALLS_UWP_DESKTOP_CAPTURE
139 	if (_desktopCapturer) {
140 		_desktopCapturer->setOnPause(std::move(pause));
141 	}
142 #endif // TGCALLS_UWP_DESKTOP_CAPTURE
143 }
144 
145 } // namespace tgcalls
146