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
26namespace webrtc {
27
28class CpuOveruseObserver;
29
30ViECapture* 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
45int 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
58ViECaptureImpl::ViECaptureImpl(ViESharedData* shared_data)
59    : shared_data_(shared_data) {}
60
61ViECaptureImpl::~ViECaptureImpl() {}
62
63int ViECaptureImpl::NumberOfCaptureDevices() {
64  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) {
73  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) {
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
96int 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
110int 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
124int 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
137int 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
180int 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
214int 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
235int 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
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  }
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
289int 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
308int 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
326int 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
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);
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
369int 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
381int 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
398int 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
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) {
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