1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "webrtc/video_engine/vie_capture_impl.h"
12
13 #include <map>
14
15 #include "webrtc/system_wrappers/interface/logging.h"
16 #include "webrtc/video_engine/include/vie_errors.h"
17 #include "webrtc/video_engine/vie_capturer.h"
18 #include "webrtc/video_engine/vie_channel.h"
19 #include "webrtc/video_engine/vie_channel_manager.h"
20 #include "webrtc/video_engine/vie_defines.h"
21 #include "webrtc/video_engine/vie_encoder.h"
22 #include "webrtc/video_engine/vie_impl.h"
23 #include "webrtc/video_engine/vie_input_manager.h"
24 #include "webrtc/video_engine/vie_shared_data.h"
25
26 namespace webrtc {
27
28 class CpuOveruseObserver;
29
GetInterface(VideoEngine * video_engine)30 ViECapture* ViECapture::GetInterface(VideoEngine* video_engine) {
31 #ifdef WEBRTC_VIDEO_ENGINE_CAPTURE_API
32 if (!video_engine) {
33 return NULL;
34 }
35 VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine);
36 ViECaptureImpl* vie_capture_impl = vie_impl;
37 // Increase ref count.
38 (*vie_capture_impl)++;
39 return vie_capture_impl;
40 #else
41 return NULL;
42 #endif
43 }
44
Release()45 int ViECaptureImpl::Release() {
46 // Decrease ref count
47 (*this)--;
48
49 int32_t ref_count = GetCount();
50 if (ref_count < 0) {
51 LOG(LS_WARNING) << "ViECapture released too many times.";
52 shared_data_->SetLastError(kViEAPIDoesNotExist);
53 return -1;
54 }
55 return ref_count;
56 }
57
ViECaptureImpl(ViESharedData * shared_data)58 ViECaptureImpl::ViECaptureImpl(ViESharedData* shared_data)
59 : shared_data_(shared_data) {}
60
~ViECaptureImpl()61 ViECaptureImpl::~ViECaptureImpl() {}
62
NumberOfCaptureDevices()63 int ViECaptureImpl::NumberOfCaptureDevices() {
64 return shared_data_->input_manager()->NumberOfCaptureDevices();
65 }
66
67
GetCaptureDevice(unsigned int list_number,char * device_nameUTF8,unsigned int device_nameUTF8Length,char * unique_idUTF8,unsigned int unique_idUTF8Length)68 int ViECaptureImpl::GetCaptureDevice(unsigned int list_number,
69 char* device_nameUTF8,
70 unsigned int device_nameUTF8Length,
71 char* unique_idUTF8,
72 unsigned int unique_idUTF8Length) {
73 return shared_data_->input_manager()->GetDeviceName(
74 list_number,
75 device_nameUTF8, device_nameUTF8Length,
76 unique_idUTF8, unique_idUTF8Length);
77 }
78
AllocateCaptureDevice(const char * unique_idUTF8,const unsigned int unique_idUTF8Length,int & capture_id)79 int ViECaptureImpl::AllocateCaptureDevice(
80 const char* unique_idUTF8,
81 const unsigned int unique_idUTF8Length,
82 int& capture_id) {
83 LOG(LS_INFO) << "AllocateCaptureDevice " << unique_idUTF8;
84 const int32_t result =
85 shared_data_->input_manager()->CreateCaptureDevice(
86 unique_idUTF8,
87 static_cast<const uint32_t>(unique_idUTF8Length),
88 capture_id);
89 if (result != 0) {
90 shared_data_->SetLastError(result);
91 return -1;
92 }
93 return 0;
94 }
95
AllocateExternalCaptureDevice(int & capture_id,ViEExternalCapture * & external_capture)96 int ViECaptureImpl::AllocateExternalCaptureDevice(
97 int& capture_id, ViEExternalCapture*& external_capture) {
98 const int32_t result =
99 shared_data_->input_manager()->CreateExternalCaptureDevice(
100 external_capture, capture_id);
101
102 if (result != 0) {
103 shared_data_->SetLastError(result);
104 return -1;
105 }
106 LOG(LS_INFO) << "External capture device allocated: " << capture_id;
107 return 0;
108 }
109
AllocateCaptureDevice(VideoCaptureModule & capture_module,int & capture_id)110 int ViECaptureImpl::AllocateCaptureDevice(
111 VideoCaptureModule& capture_module, int& capture_id) { // NOLINT
112 int32_t result = shared_data_->input_manager()->CreateCaptureDevice(
113 &capture_module, capture_id);
114 if (result != 0) {
115 shared_data_->SetLastError(result);
116 return -1;
117 }
118 LOG(LS_INFO) << "External capture device, by module, allocated: "
119 << capture_id;
120 return 0;
121 }
122
123
ReleaseCaptureDevice(const int capture_id)124 int ViECaptureImpl::ReleaseCaptureDevice(const int capture_id) {
125 LOG(LS_INFO) << "ReleaseCaptureDevice " << capture_id;
126 {
127 ViEInputManagerScoped is((*(shared_data_->input_manager())));
128 ViECapturer* vie_capture = is.Capture(capture_id);
129 if (!vie_capture) {
130 shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
131 return -1;
132 }
133 }
134 return shared_data_->input_manager()->DestroyCaptureDevice(capture_id);
135 }
136
ConnectCaptureDevice(const int capture_id,const int video_channel)137 int ViECaptureImpl::ConnectCaptureDevice(const int capture_id,
138 const int video_channel) {
139 LOG(LS_INFO) << "Connect capture id " << capture_id
140 << " to channel " << video_channel;
141
142 ViEInputManagerScoped is(*(shared_data_->input_manager()));
143 ViECapturer* vie_capture = is.Capture(capture_id);
144 if (!vie_capture) {
145 shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
146 return -1;
147 }
148
149 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
150 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
151 if (!vie_encoder) {
152 LOG(LS_ERROR) << "Channel doesn't exist.";
153 shared_data_->SetLastError(kViECaptureDeviceInvalidChannelId);
154 return -1;
155 }
156 if (vie_encoder->Owner() != video_channel) {
157 LOG(LS_ERROR) << "Can't connect capture device to a receive device.";
158 shared_data_->SetLastError(kViECaptureDeviceInvalidChannelId);
159 return -1;
160 }
161 // Check if the encoder already has a connected frame provider
162 if (is.FrameProvider(vie_encoder) != NULL) {
163 LOG(LS_ERROR) << "Channel already connected to capture device.";
164 shared_data_->SetLastError(kViECaptureDeviceAlreadyConnected);
165 return -1;
166 }
167 if (vie_capture->RegisterFrameCallback(video_channel, vie_encoder) != 0) {
168 shared_data_->SetLastError(kViECaptureDeviceUnknownError);
169 return -1;
170 }
171 std::map<int, CpuOveruseObserver*>::iterator it =
172 shared_data_->overuse_observers()->find(video_channel);
173 if (it != shared_data_->overuse_observers()->end()) {
174 vie_capture->RegisterCpuOveruseObserver(it->second);
175 }
176 return 0;
177 }
178
179
DisconnectCaptureDevice(const int video_channel)180 int ViECaptureImpl::DisconnectCaptureDevice(const int video_channel) {
181 LOG(LS_INFO) << "DisconnectCaptureDevice " << video_channel;
182
183 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
184 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
185 if (!vie_encoder) {
186 LOG(LS_ERROR) << "Channel doesn't exist.";
187 shared_data_->SetLastError(kViECaptureDeviceInvalidChannelId);
188 return -1;
189 }
190
191 ViEInputManagerScoped is(*(shared_data_->input_manager()));
192 ViEFrameProviderBase* frame_provider = is.FrameProvider(vie_encoder);
193 if (!frame_provider) {
194 shared_data_->SetLastError(kViECaptureDeviceNotConnected);
195 return -1;
196 }
197 if (frame_provider->Id() < kViECaptureIdBase ||
198 frame_provider->Id() > kViECaptureIdMax) {
199 shared_data_->SetLastError(kViECaptureDeviceNotConnected);
200 return -1;
201 }
202
203 ViECapturer* vie_capture = is.Capture(frame_provider->Id());
204 assert(vie_capture);
205 vie_capture->RegisterCpuOveruseObserver(NULL);
206 if (frame_provider->DeregisterFrameCallback(vie_encoder) != 0) {
207 shared_data_->SetLastError(kViECaptureDeviceUnknownError);
208 return -1;
209 }
210
211 return 0;
212 }
213
StartCapture(const int capture_id,const CaptureCapability & capture_capability)214 int ViECaptureImpl::StartCapture(const int capture_id,
215 const CaptureCapability& capture_capability) {
216 LOG(LS_INFO) << "StartCapture " << capture_id;
217
218 ViEInputManagerScoped is(*(shared_data_->input_manager()));
219 ViECapturer* vie_capture = is.Capture(capture_id);
220 if (!vie_capture) {
221 shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
222 return -1;
223 }
224 if (vie_capture->Started()) {
225 shared_data_->SetLastError(kViECaptureDeviceAlreadyStarted);
226 return -1;
227 }
228 if (vie_capture->Start(capture_capability) != 0) {
229 shared_data_->SetLastError(kViECaptureDeviceUnknownError);
230 return -1;
231 }
232 return 0;
233 }
234
StopCapture(const int capture_id)235 int ViECaptureImpl::StopCapture(const int capture_id) {
236 LOG(LS_INFO) << "StopCapture " << capture_id;
237
238 ViEInputManagerScoped is(*(shared_data_->input_manager()));
239 ViECapturer* vie_capture = is.Capture(capture_id);
240 if (!vie_capture) {
241 shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
242 return -1;
243 }
244 if (!vie_capture->Started()) {
245 shared_data_->SetLastError(kViECaptureDeviceNotStarted);
246 return 0;
247 }
248 if (vie_capture->Stop() != 0) {
249 shared_data_->SetLastError(kViECaptureDeviceUnknownError);
250 return -1;
251 }
252 return 0;
253 }
254
SetRotateCapturedFrames(const int capture_id,const RotateCapturedFrame rotation)255 int ViECaptureImpl::SetRotateCapturedFrames(
256 const int capture_id,
257 const RotateCapturedFrame rotation) {
258 int i_rotation = -1;
259 switch (rotation) {
260 case RotateCapturedFrame_0:
261 i_rotation = 0;
262 break;
263 case RotateCapturedFrame_90:
264 i_rotation = 90;
265 break;
266 case RotateCapturedFrame_180:
267 i_rotation = 180;
268 break;
269 case RotateCapturedFrame_270:
270 i_rotation = 270;
271 break;
272 }
273 LOG(LS_INFO) << "SetRotateCaptureFrames for " << capture_id
274 << ", rotation " << i_rotation;
275
276 ViEInputManagerScoped is(*(shared_data_->input_manager()));
277 ViECapturer* vie_capture = is.Capture(capture_id);
278 if (!vie_capture) {
279 shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
280 return -1;
281 }
282 if (vie_capture->SetRotateCapturedFrames(rotation) != 0) {
283 shared_data_->SetLastError(kViECaptureDeviceUnknownError);
284 return -1;
285 }
286 return 0;
287 }
288
SetCaptureDelay(const int capture_id,const unsigned int capture_delay_ms)289 int ViECaptureImpl::SetCaptureDelay(const int capture_id,
290 const unsigned int capture_delay_ms) {
291 LOG(LS_INFO) << "SetCaptureDelay " << capture_delay_ms
292 << ", for device " << capture_id;
293
294 ViEInputManagerScoped is(*(shared_data_->input_manager()));
295 ViECapturer* vie_capture = is.Capture(capture_id);
296 if (!vie_capture) {
297 shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
298 return -1;
299 }
300
301 if (vie_capture->SetCaptureDelay(capture_delay_ms) != 0) {
302 shared_data_->SetLastError(kViECaptureDeviceUnknownError);
303 return -1;
304 }
305 return 0;
306 }
307
NumberOfCapabilities(const char * unique_idUTF8,const unsigned int unique_idUTF8Length)308 int ViECaptureImpl::NumberOfCapabilities(
309 const char* unique_idUTF8,
310 const unsigned int unique_idUTF8Length) {
311
312 #if defined(WEBRTC_MAC)
313 // TODO(mflodman) Move to capture module!
314 // QTKit framework handles all capabilities and capture settings
315 // automatically (mandatory).
316 // Thus this function cannot be supported on the Mac platform.
317 shared_data_->SetLastError(kViECaptureDeviceMacQtkitNotSupported);
318 LOG_F(LS_ERROR) << "API not supported on Mac OS X.";
319 return -1;
320 #endif
321 return shared_data_->input_manager()->NumberOfCaptureCapabilities(
322 unique_idUTF8);
323 }
324
325
GetCaptureCapability(const char * unique_idUTF8,const unsigned int unique_idUTF8Length,const unsigned int capability_number,CaptureCapability & capability)326 int ViECaptureImpl::GetCaptureCapability(const char* unique_idUTF8,
327 const unsigned int unique_idUTF8Length,
328 const unsigned int capability_number,
329 CaptureCapability& capability) {
330
331 #if defined(WEBRTC_MAC)
332 // TODO(mflodman) Move to capture module!
333 // QTKit framework handles all capabilities and capture settings
334 // automatically (mandatory).
335 // Thus this function cannot be supported on the Mac platform.
336 LOG_F(LS_ERROR) << "API not supported on Mac OS X.";
337 shared_data_->SetLastError(kViECaptureDeviceMacQtkitNotSupported);
338 return -1;
339 #endif
340 if (shared_data_->input_manager()->GetCaptureCapability(
341 unique_idUTF8, capability_number, capability) != 0) {
342 shared_data_->SetLastError(kViECaptureDeviceUnknownError);
343 return -1;
344 }
345 return 0;
346 }
347
ShowCaptureSettingsDialogBox(const char * unique_idUTF8,const unsigned int unique_idUTF8Length,const char * dialog_title,void * parent_window,const unsigned int x,const unsigned int y)348 int ViECaptureImpl::ShowCaptureSettingsDialogBox(
349 const char* unique_idUTF8,
350 const unsigned int unique_idUTF8Length,
351 const char* dialog_title,
352 void* parent_window,
353 const unsigned int x,
354 const unsigned int y) {
355 #if defined(WEBRTC_MAC)
356 // TODO(mflodman) Move to capture module
357 // QTKit framework handles all capabilities and capture settings
358 // automatically (mandatory).
359 // Thus this function cannot be supported on the Mac platform.
360 shared_data_->SetLastError(kViECaptureDeviceMacQtkitNotSupported);
361 LOG_F(LS_ERROR) << "API not supported on Mac OS X.";
362 return -1;
363 #endif
364 return shared_data_->input_manager()->DisplayCaptureSettingsDialogBox(
365 unique_idUTF8, dialog_title,
366 parent_window, x, y);
367 }
368
GetOrientation(const char * unique_idUTF8,RotateCapturedFrame & orientation)369 int ViECaptureImpl::GetOrientation(const char* unique_idUTF8,
370 RotateCapturedFrame& orientation) {
371 if (shared_data_->input_manager()->GetOrientation(
372 unique_idUTF8,
373 orientation) != 0) {
374 shared_data_->SetLastError(kViECaptureDeviceUnknownError);
375 return -1;
376 }
377 return 0;
378 }
379
380
EnableBrightnessAlarm(const int capture_id,const bool enable)381 int ViECaptureImpl::EnableBrightnessAlarm(const int capture_id,
382 const bool enable) {
383 LOG(LS_INFO) << "EnableBrightnessAlarm for device " << capture_id
384 << ", status " << enable;
385 ViEInputManagerScoped is(*(shared_data_->input_manager()));
386 ViECapturer* vie_capture = is.Capture(capture_id);
387 if (!vie_capture) {
388 shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
389 return -1;
390 }
391 if (vie_capture->EnableBrightnessAlarm(enable) != 0) {
392 shared_data_->SetLastError(kViECaptureDeviceUnknownError);
393 return -1;
394 }
395 return 0;
396 }
397
RegisterObserver(const int capture_id,ViECaptureObserver & observer)398 int ViECaptureImpl::RegisterObserver(const int capture_id,
399 ViECaptureObserver& observer) {
400 LOG(LS_INFO) << "Register capture observer " << capture_id;
401 ViEInputManagerScoped is(*(shared_data_->input_manager()));
402 ViECapturer* vie_capture = is.Capture(capture_id);
403 if (!vie_capture) {
404 shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
405 return -1;
406 }
407 if (vie_capture->IsObserverRegistered()) {
408 LOG_F(LS_ERROR) << "Observer already registered.";
409 shared_data_->SetLastError(kViECaptureObserverAlreadyRegistered);
410 return -1;
411 }
412 if (vie_capture->RegisterObserver(&observer) != 0) {
413 shared_data_->SetLastError(kViECaptureDeviceUnknownError);
414 return -1;
415 }
416 return 0;
417 }
418
DeregisterObserver(const int capture_id)419 int ViECaptureImpl::DeregisterObserver(const int capture_id) {
420 ViEInputManagerScoped is(*(shared_data_->input_manager()));
421 ViECapturer* vie_capture = is.Capture(capture_id);
422 if (!vie_capture) {
423 shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
424 return -1;
425 }
426 if (!vie_capture->IsObserverRegistered()) {
427 shared_data_->SetLastError(kViECaptureDeviceObserverNotRegistered);
428 return -1;
429 }
430
431 if (vie_capture->DeRegisterObserver() != 0) {
432 shared_data_->SetLastError(kViECaptureDeviceUnknownError);
433 return -1;
434 }
435 return 0;
436 }
437
438 } // namespace webrtc
439