blob: 9581fb7f2cf203d56567febd2c69f19c932e810c [file] [log] [blame]
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +00001/*
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
pbos@webrtc.org281cff82013-05-17 13:44:48 +000011#include "webrtc/video_engine/vie_capture_impl.h"
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000012
mflodman@webrtc.orgbf76ae22013-07-23 11:35:00 +000013#include <map>
14
mflodman@webrtc.org022615b2014-04-07 10:56:31 +000015#include "webrtc/system_wrappers/interface/logging.h"
pbos@webrtc.org281cff82013-05-17 13:44:48 +000016#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"
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000025
26namespace webrtc {
27
mflodman@webrtc.orgbf76ae22013-07-23 11:35:00 +000028class CpuOveruseObserver;
29
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000030ViECapture* ViECapture::GetInterface(VideoEngine* video_engine) {
31#ifdef WEBRTC_VIDEO_ENGINE_CAPTURE_API
32 if (!video_engine) {
33 return NULL;
34 }
andrew@webrtc.org7ab72682013-05-09 02:12:07 +000035 VideoEngineImpl* vie_impl = static_cast<VideoEngineImpl*>(video_engine);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000036 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
45int ViECaptureImpl::Release() {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000046 // Decrease ref count
47 (*this)--;
48
pbos@webrtc.org67879bc2013-04-09 13:41:51 +000049 int32_t ref_count = GetCount();
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000050 if (ref_count < 0) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +000051 LOG(LS_WARNING) << "ViECapture released too many times.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000052 shared_data_->SetLastError(kViEAPIDoesNotExist);
53 return -1;
54 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000055 return ref_count;
56}
57
58ViECaptureImpl::ViECaptureImpl(ViESharedData* shared_data)
mflodman@webrtc.org022615b2014-04-07 10:56:31 +000059 : shared_data_(shared_data) {}
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000060
mflodman@webrtc.org022615b2014-04-07 10:56:31 +000061ViECaptureImpl::~ViECaptureImpl() {}
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000062
63int ViECaptureImpl::NumberOfCaptureDevices() {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000064 return shared_data_->input_manager()->NumberOfCaptureDevices();
65}
66
67
68int ViECaptureImpl::GetCaptureDevice(unsigned int list_number,
69 char* device_nameUTF8,
70 unsigned int device_nameUTF8Length,
71 char* unique_idUTF8,
72 unsigned int unique_idUTF8Length) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000073 return shared_data_->input_manager()->GetDeviceName(
74 list_number,
75 device_nameUTF8, device_nameUTF8Length,
76 unique_idUTF8, unique_idUTF8Length);
77}
78
79int ViECaptureImpl::AllocateCaptureDevice(
80 const char* unique_idUTF8,
81 const unsigned int unique_idUTF8Length,
82 int& capture_id) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +000083 LOG(LS_INFO) << "AllocateCaptureDevice " << unique_idUTF8;
pbos@webrtc.org67879bc2013-04-09 13:41:51 +000084 const int32_t result =
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000085 shared_data_->input_manager()->CreateCaptureDevice(
86 unique_idUTF8,
pbos@webrtc.org67879bc2013-04-09 13:41:51 +000087 static_cast<const uint32_t>(unique_idUTF8Length),
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000088 capture_id);
89 if (result != 0) {
90 shared_data_->SetLastError(result);
91 return -1;
92 }
93 return 0;
94}
95
96int ViECaptureImpl::AllocateExternalCaptureDevice(
97 int& capture_id, ViEExternalCapture*& external_capture) {
pbos@webrtc.org67879bc2013-04-09 13:41:51 +000098 const int32_t result =
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +000099 shared_data_->input_manager()->CreateExternalCaptureDevice(
100 external_capture, capture_id);
101
102 if (result != 0) {
103 shared_data_->SetLastError(result);
104 return -1;
105 }
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000106 LOG(LS_INFO) << "External capture device allocated: " << capture_id;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000107 return 0;
108}
109
110int ViECaptureImpl::AllocateCaptureDevice(
111 VideoCaptureModule& capture_module, int& capture_id) { // NOLINT
mflodman@webrtc.org7645e4d2013-05-16 11:13:18 +0000112 int32_t result = shared_data_->input_manager()->CreateCaptureDevice(
113 &capture_module, capture_id);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000114 if (result != 0) {
115 shared_data_->SetLastError(result);
116 return -1;
117 }
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000118 LOG(LS_INFO) << "External capture device, by module, allocated: "
119 << capture_id;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000120 return 0;
121}
122
123
124int ViECaptureImpl::ReleaseCaptureDevice(const int capture_id) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000125 LOG(LS_INFO) << "ReleaseCaptureDevice " << capture_id;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000126 {
127 ViEInputManagerScoped is((*(shared_data_->input_manager())));
128 ViECapturer* vie_capture = is.Capture(capture_id);
129 if (!vie_capture) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000130 shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
131 return -1;
132 }
133 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000134 return shared_data_->input_manager()->DestroyCaptureDevice(capture_id);
135}
136
137int ViECaptureImpl::ConnectCaptureDevice(const int capture_id,
138 const int video_channel) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000139 LOG(LS_INFO) << "Connect capture id " << capture_id
140 << " to channel " << video_channel;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000141
142 ViEInputManagerScoped is(*(shared_data_->input_manager()));
143 ViECapturer* vie_capture = is.Capture(capture_id);
144 if (!vie_capture) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000145 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) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000152 LOG(LS_ERROR) << "Channel doesn't exist.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000153 shared_data_->SetLastError(kViECaptureDeviceInvalidChannelId);
154 return -1;
155 }
156 if (vie_encoder->Owner() != video_channel) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000157 LOG(LS_ERROR) << "Can't connect capture device to a receive device.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000158 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) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000163 LOG(LS_ERROR) << "Channel already connected to capture device.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000164 shared_data_->SetLastError(kViECaptureDeviceAlreadyConnected);
165 return -1;
166 }
mflodman@webrtc.orga18c6e52013-06-07 13:57:57 +0000167 if (vie_capture->RegisterFrameCallback(video_channel, vie_encoder) != 0) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000168 shared_data_->SetLastError(kViECaptureDeviceUnknownError);
169 return -1;
170 }
mflodman@webrtc.orgbf76ae22013-07-23 11:35:00 +0000171 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 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000176 return 0;
177}
178
179
180int ViECaptureImpl::DisconnectCaptureDevice(const int video_channel) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000181 LOG(LS_INFO) << "DisconnectCaptureDevice " << video_channel;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000182
183 ViEChannelManagerScoped cs(*(shared_data_->channel_manager()));
184 ViEEncoder* vie_encoder = cs.Encoder(video_channel);
185 if (!vie_encoder) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000186 LOG(LS_ERROR) << "Channel doesn't exist.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000187 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) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000194 shared_data_->SetLastError(kViECaptureDeviceNotConnected);
195 return -1;
196 }
197 if (frame_provider->Id() < kViECaptureIdBase ||
198 frame_provider->Id() > kViECaptureIdMax) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000199 shared_data_->SetLastError(kViECaptureDeviceNotConnected);
200 return -1;
201 }
202
mflodman@webrtc.orgbf76ae22013-07-23 11:35:00 +0000203 ViECapturer* vie_capture = is.Capture(frame_provider->Id());
204 assert(vie_capture);
205 vie_capture->RegisterCpuOveruseObserver(NULL);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000206 if (frame_provider->DeregisterFrameCallback(vie_encoder) != 0) {
207 shared_data_->SetLastError(kViECaptureDeviceUnknownError);
208 return -1;
209 }
210
211 return 0;
212}
213
214int ViECaptureImpl::StartCapture(const int capture_id,
215 const CaptureCapability& capture_capability) {
asapersson@webrtc.org1d95c5a2014-04-25 07:02:52 +0000216 LOG(LS_INFO) << "StartCapture " << capture_id;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000217
218 ViEInputManagerScoped is(*(shared_data_->input_manager()));
219 ViECapturer* vie_capture = is.Capture(capture_id);
220 if (!vie_capture) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000221 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
235int ViECaptureImpl::StopCapture(const int capture_id) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000236 LOG(LS_INFO) << "StopCapture " << capture_id;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000237
238 ViEInputManagerScoped is(*(shared_data_->input_manager()));
239 ViECapturer* vie_capture = is.Capture(capture_id);
240 if (!vie_capture) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000241 shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
242 return -1;
243 }
244 if (!vie_capture->Started()) {
245 shared_data_->SetLastError(kViECaptureDeviceNotStarted);
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000246 return 0;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000247 }
248 if (vie_capture->Stop() != 0) {
249 shared_data_->SetLastError(kViECaptureDeviceUnknownError);
250 return -1;
251 }
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000252 return 0;
253}
254
255int 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 }
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000273 LOG(LS_INFO) << "SetRotateCaptureFrames for " << capture_id
274 << ", rotation " << i_rotation;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000275
276 ViEInputManagerScoped is(*(shared_data_->input_manager()));
277 ViECapturer* vie_capture = is.Capture(capture_id);
278 if (!vie_capture) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000279 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
289int ViECaptureImpl::SetCaptureDelay(const int capture_id,
290 const unsigned int capture_delay_ms) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000291 LOG(LS_INFO) << "SetCaptureDelay " << capture_delay_ms
292 << ", for device " << capture_id;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000293
294 ViEInputManagerScoped is(*(shared_data_->input_manager()));
295 ViECapturer* vie_capture = is.Capture(capture_id);
296 if (!vie_capture) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000297 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
308int ViECaptureImpl::NumberOfCapabilities(
309 const char* unique_idUTF8,
310 const unsigned int unique_idUTF8Length) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000311
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);
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000318 LOG_F(LS_ERROR) << "API not supported on Mac OS X.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000319 return -1;
320#endif
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000321 return shared_data_->input_manager()->NumberOfCaptureCapabilities(
322 unique_idUTF8);
323}
324
325
326int ViECaptureImpl::GetCaptureCapability(const char* unique_idUTF8,
327 const unsigned int unique_idUTF8Length,
328 const unsigned int capability_number,
329 CaptureCapability& capability) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000330
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.
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000336 LOG_F(LS_ERROR) << "API not supported on Mac OS X.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000337 shared_data_->SetLastError(kViECaptureDeviceMacQtkitNotSupported);
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000338 return -1;
339#endif
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000340 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
348int 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);
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000361 LOG_F(LS_ERROR) << "API not supported on Mac OS X.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000362 return -1;
363#endif
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000364 return shared_data_->input_manager()->DisplayCaptureSettingsDialogBox(
365 unique_idUTF8, dialog_title,
366 parent_window, x, y);
367}
368
369int ViECaptureImpl::GetOrientation(const char* unique_idUTF8,
370 RotateCapturedFrame& orientation) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000371 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
381int ViECaptureImpl::EnableBrightnessAlarm(const int capture_id,
382 const bool enable) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000383 LOG(LS_INFO) << "EnableBrightnessAlarm for device " << capture_id
384 << ", status " << enable;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000385 ViEInputManagerScoped is(*(shared_data_->input_manager()));
386 ViECapturer* vie_capture = is.Capture(capture_id);
387 if (!vie_capture) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000388 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
398int ViECaptureImpl::RegisterObserver(const int capture_id,
399 ViECaptureObserver& observer) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000400 LOG(LS_INFO) << "Register capture observer " << capture_id;
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000401 ViEInputManagerScoped is(*(shared_data_->input_manager()));
402 ViECapturer* vie_capture = is.Capture(capture_id);
403 if (!vie_capture) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000404 shared_data_->SetLastError(kViECaptureDeviceDoesNotExist);
405 return -1;
406 }
407 if (vie_capture->IsObserverRegistered()) {
mflodman@webrtc.org022615b2014-04-07 10:56:31 +0000408 LOG_F(LS_ERROR) << "Observer already registered.";
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000409 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
419int 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) {
andrew@webrtc.orgb015cbe2012-10-22 18:19:23 +0000423 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