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 "gflags/gflags.h"
12#include "webrtc/common_types.h"
13#include "webrtc/engine_configurations.h"
14#include "webrtc/modules/video_capture/include/video_capture_factory.h"
15#include "webrtc/system_wrappers/interface/tick_util.h"
16#include "webrtc/video_engine/include/vie_base.h"
17#include "webrtc/video_engine/include/vie_capture.h"
18#include "webrtc/video_engine/include/vie_codec.h"
19#include "webrtc/video_engine/include/vie_network.h"
20#include "webrtc/video_engine/include/vie_render.h"
21#include "webrtc/video_engine/include/vie_rtp_rtcp.h"
22#include "webrtc/video_engine/test/auto_test/interface/vie_autotest.h"
23#include "webrtc/video_engine/test/auto_test/interface/vie_autotest_defines.h"
24#include "webrtc/video_engine/test/libvietest/include/tb_interfaces.h"
25#include "webrtc/video_engine/test/libvietest/include/tb_video_channel.h"
26#include "webrtc/voice_engine/include/voe_base.h"
27
28DEFINE_bool(capture_test_ensure_resolution_alignment_in_capture_device, true,
29            "If true, we will give resolutions slightly below a reasonable "
30            "value to test the camera's ability to choose a good resolution. "
31            "If false, we will provide reasonable resolutions instead.");
32
33class CaptureObserver : public webrtc::ViECaptureObserver {
34 public:
35  CaptureObserver()
36      : brightness_(webrtc::Normal),
37        alarm_(webrtc::AlarmCleared),
38        frame_rate_(0) {}
39
40  virtual void BrightnessAlarm(const int capture_id,
41                               const webrtc::Brightness brightness) {
42    brightness_ = brightness;
43    switch (brightness) {
44      case webrtc::Normal:
45        ViETest::Log("  BrightnessAlarm Normal");
46        break;
47      case webrtc::Bright:
48        ViETest::Log("  BrightnessAlarm Bright");
49        break;
50      case webrtc::Dark:
51        ViETest::Log("  BrightnessAlarm Dark");
52        break;
53    }
54  }
55
56  virtual void CapturedFrameRate(const int capture_id,
57                                 const unsigned char frame_rate) {
58    ViETest::Log("  CapturedFrameRate %u", frame_rate);
59    frame_rate_ = frame_rate;
60  }
61
62  virtual void NoPictureAlarm(const int capture_id,
63                              const webrtc::CaptureAlarm alarm) {
64    alarm_ = alarm;
65    if (alarm == webrtc::AlarmRaised) {
66      ViETest::Log("NoPictureAlarm CARaised.");
67    } else {
68      ViETest::Log("NoPictureAlarm CACleared.");
69    }
70  }
71
72  webrtc::Brightness brightness_;
73  webrtc::CaptureAlarm alarm_;
74  unsigned char frame_rate_;
75};
76
77class CaptureEffectFilter : public webrtc::ViEEffectFilter {
78 public:
79  CaptureEffectFilter(unsigned int expected_width, unsigned int expected_height)
80      : number_of_captured_frames_(0),
81        expected_width_(expected_width),
82        expected_height_(expected_height) {
83  }
84
85  // Implements video_engineEffectFilter.
86  virtual int Transform(int size,
87                        unsigned char* frame_buffer,
88                        int64_t ntp_time_ms,
89                        unsigned int timestamp,
90                        unsigned int width,
91                        unsigned int height) {
92    EXPECT_TRUE(frame_buffer != NULL);
93    EXPECT_EQ(expected_width_, width);
94    EXPECT_EQ(expected_height_, height);
95    ++number_of_captured_frames_;
96    return 0;
97  }
98
99  int number_of_captured_frames_;
100
101 protected:
102  unsigned int expected_width_;
103  unsigned int expected_height_;
104};
105
106void ViEAutoTest::ViECaptureStandardTest() {
107  /// **************************************************************
108  //  Begin create/initialize WebRTC Video Engine for testing
109  /// **************************************************************
110
111  /// **************************************************************
112  //  Engine ready. Begin testing class
113  /// **************************************************************
114
115  TbInterfaces video_engine("video_engineCaptureStandardTest");
116
117  webrtc::VideoCaptureModule::DeviceInfo* dev_info =
118      webrtc::VideoCaptureFactory::CreateDeviceInfo(0);
119  ASSERT_TRUE(dev_info != NULL);
120
121  int number_of_capture_devices = dev_info->NumberOfDevices();
122  ViETest::Log("Number of capture devices %d",
123                        number_of_capture_devices);
124  ASSERT_GT(number_of_capture_devices, 0)
125      << "This test requires a capture device (i.e. a webcam)";
126
127#if !defined(WEBRTC_MAC)
128  int capture_device_id[10] = {0};
129  webrtc::VideoCaptureModule* vcpms[10] = {0};
130#endif
131
132  // Check capabilities
133  for (int device_index = 0; device_index < number_of_capture_devices;
134       ++device_index) {
135    char device_name[128];
136    char device_unique_name[512];
137
138    EXPECT_EQ(0, dev_info->GetDeviceName(device_index,
139                                         device_name,
140                                         sizeof(device_name),
141                                         device_unique_name,
142                                         sizeof(device_unique_name)));
143    ViETest::Log("Found capture device %s\nUnique name %s",
144                          device_name, device_unique_name);
145
146#if !defined(WEBRTC_MAC)  // these functions will return -1
147    int number_of_capabilities =
148        dev_info->NumberOfCapabilities(device_unique_name);
149    EXPECT_GT(number_of_capabilities, 0);
150
151    for (int cap_index = 0; cap_index < number_of_capabilities; ++cap_index) {
152      webrtc::VideoCaptureCapability capability;
153      EXPECT_EQ(0, dev_info->GetCapability(device_unique_name, cap_index,
154                                           capability));
155      ViETest::Log("Capture capability %d (of %u)", cap_index + 1,
156                   number_of_capabilities);
157      ViETest::Log("width %d, height %d, frame rate %d",
158                   capability.width, capability.height, capability.maxFPS);
159      ViETest::Log("expected delay %d, color type %d, encoding %d",
160                   capability.expectedCaptureDelay, capability.rawType,
161                   capability.codecType);
162      EXPECT_GT(capability.width, 0);
163      EXPECT_GT(capability.height, 0);
164      EXPECT_GT(capability.maxFPS, -1);  // >= 0
165      EXPECT_GT(capability.expectedCaptureDelay, 0);
166    }
167#endif
168  }
169  // Capture Capability Functions are not supported on WEBRTC_MAC.
170#if !defined(WEBRTC_MAC)
171
172  // Check allocation. Try to allocate them all after each other.
173  for (int device_index = 0; device_index < number_of_capture_devices;
174       ++device_index) {
175    char device_name[128];
176    char device_unique_name[512];
177    EXPECT_EQ(0, dev_info->GetDeviceName(device_index,
178                                         device_name,
179                                         sizeof(device_name),
180                                         device_unique_name,
181                                         sizeof(device_unique_name)));
182    webrtc::VideoCaptureModule* vcpm =
183        webrtc::VideoCaptureFactory::Create(device_index, device_unique_name);
184    EXPECT_TRUE(vcpm != NULL);
185    if (!vcpm)
186      continue;
187
188    vcpm->AddRef();
189    vcpms[device_index] = vcpm;
190
191    EXPECT_EQ(0, video_engine.capture->AllocateCaptureDevice(
192        *vcpm, capture_device_id[device_index]));
193
194    webrtc::VideoCaptureCapability capability;
195    EXPECT_EQ(0, dev_info->GetCapability(device_unique_name, 0, capability));
196
197    // Test that the camera select the closest capability to the selected
198    // width and height.
199    CaptureEffectFilter filter(capability.width, capability.height);
200    EXPECT_EQ(0, video_engine.image_process->RegisterCaptureEffectFilter(
201        capture_device_id[device_index], filter));
202
203    ViETest::Log("Testing Device %s capability width %d  height %d",
204                 device_unique_name, capability.width, capability.height);
205
206    if (FLAGS_capture_test_ensure_resolution_alignment_in_capture_device) {
207      // This tests that the capture device properly aligns to a
208      // multiple of 16 (or at least 8).
209      capability.height = capability.height - 2;
210      capability.width  = capability.width  - 2;
211    }
212
213    webrtc::CaptureCapability vie_capability;
214    vie_capability.width = capability.width;
215    vie_capability.height = capability.height;
216    vie_capability.codecType = capability.codecType;
217    vie_capability.maxFPS = capability.maxFPS;
218    vie_capability.rawType = capability.rawType;
219
220    EXPECT_EQ(0, video_engine.capture->StartCapture(
221        capture_device_id[device_index], vie_capability));
222    webrtc::TickTime start_time = webrtc::TickTime::Now();
223
224    while (filter.number_of_captured_frames_ < 10 &&
225           (webrtc::TickTime::Now() - start_time).Milliseconds() < 10000) {
226      AutoTestSleep(100);
227    }
228
229    EXPECT_GT(filter.number_of_captured_frames_, 9)
230        << "Should capture at least some frames";
231
232    EXPECT_EQ(0, video_engine.image_process->DeregisterCaptureEffectFilter(
233        capture_device_id[device_index]));
234
235#ifdef WEBRTC_ANDROID  // Can only allocate one camera at the time on Android.
236    EXPECT_EQ(0, video_engine.capture->StopCapture(
237        capture_device_id[device_index]));
238    EXPECT_EQ(0, video_engine.capture->ReleaseCaptureDevice(
239        capture_device_id[device_index]));
240#endif
241  }
242
243  /// **************************************************************
244  //  Testing finished. Tear down Video Engine
245  /// **************************************************************
246  delete dev_info;
247
248  // Stop all started capture devices.
249  for (int device_index = 0; device_index < number_of_capture_devices;
250       ++device_index) {
251#if !defined(WEBRTC_ANDROID)
252    // Don't stop on Android since we can only allocate one camera.
253    EXPECT_EQ(0, video_engine.capture->StopCapture(
254        capture_device_id[device_index]));
255    EXPECT_EQ(0, video_engine.capture->ReleaseCaptureDevice(
256        capture_device_id[device_index]));
257#endif  // !WEBRTC_ANDROID
258    if (vcpms[device_index])
259      vcpms[device_index]->Release();
260  }
261#endif  // !WEBRTC_MAC
262}
263
264void ViEAutoTest::ViECaptureExtendedTest() {
265  ViECaptureExternalCaptureTest();
266}
267
268void ViEAutoTest::ViECaptureAPITest() {
269  /// **************************************************************
270  //  Begin create/initialize WebRTC Video Engine for testing
271  /// **************************************************************
272
273  /// **************************************************************
274  //  Engine ready. Begin testing class
275  /// **************************************************************
276  TbInterfaces video_engine("video_engineCaptureAPITest");
277
278  video_engine.capture->NumberOfCaptureDevices();
279
280  char device_name[128];
281  char device_unique_name[512];
282  int capture_id = 0;
283
284  webrtc::VideoCaptureModule::DeviceInfo* dev_info =
285      webrtc::VideoCaptureFactory::CreateDeviceInfo(0);
286  ASSERT_TRUE(dev_info != NULL);
287  ASSERT_GT(dev_info->NumberOfDevices(), 0u)
288      << "This test requires a capture device (i.e. a webcam)";
289
290  // Get the first capture device
291  EXPECT_EQ(0, dev_info->GetDeviceName(0, device_name,
292                                       sizeof(device_name),
293                                       device_unique_name,
294                                       sizeof(device_unique_name)));
295
296  webrtc::VideoCaptureModule* vcpm =
297      webrtc::VideoCaptureFactory::Create(0, device_unique_name);
298  vcpm->AddRef();
299  EXPECT_TRUE(vcpm != NULL);
300
301  // Allocate capture device.
302  EXPECT_EQ(0, video_engine.capture->AllocateCaptureDevice(*vcpm, capture_id));
303
304  // Start the capture device.
305  EXPECT_EQ(0, video_engine.capture->StartCapture(capture_id));
306
307  // Start again. Should fail.
308  EXPECT_NE(0, video_engine.capture->StartCapture(capture_id));
309  EXPECT_EQ(kViECaptureDeviceAlreadyStarted, video_engine.LastError());
310
311  // Start invalid capture device.
312  EXPECT_NE(0, video_engine.capture->StartCapture(capture_id + 1));
313  EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError());
314
315  // Stop invalid capture device.
316  EXPECT_NE(0, video_engine.capture->StopCapture(capture_id + 1));
317  EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError());
318
319  // Stop the capture device.
320  EXPECT_EQ(0, video_engine.capture->StopCapture(capture_id));
321
322  // Stop the capture device again.
323  EXPECT_NE(0, video_engine.capture->StopCapture(capture_id));
324  EXPECT_EQ(kViECaptureDeviceNotStarted, video_engine.LastError());
325
326  // Connect to invalid channel.
327  EXPECT_NE(0, video_engine.capture->ConnectCaptureDevice(capture_id, 0));
328  EXPECT_EQ(kViECaptureDeviceInvalidChannelId,
329            video_engine.LastError());
330
331  TbVideoChannel channel(video_engine);
332
333  // Connect invalid capture_id.
334  EXPECT_NE(0, video_engine.capture->ConnectCaptureDevice(capture_id + 1,
335                                                 channel.videoChannel));
336  EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError());
337
338  // Connect the capture device to the channel.
339  EXPECT_EQ(0, video_engine.capture->ConnectCaptureDevice(capture_id,
340                                                 channel.videoChannel));
341
342  // Connect the channel again.
343  EXPECT_NE(0, video_engine.capture->ConnectCaptureDevice(capture_id,
344                                                 channel.videoChannel));
345  EXPECT_EQ(kViECaptureDeviceAlreadyConnected,
346            video_engine.LastError());
347
348  // Start the capture device.
349  EXPECT_EQ(0, video_engine.capture->StartCapture(capture_id));
350
351  // Release invalid capture device.
352  EXPECT_NE(0, video_engine.capture->ReleaseCaptureDevice(capture_id + 1));
353  EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError());
354
355  // Release the capture device.
356  EXPECT_EQ(0, video_engine.capture->ReleaseCaptureDevice(capture_id));
357
358  // Release the capture device again.
359  EXPECT_NE(0, video_engine.capture->ReleaseCaptureDevice(capture_id));
360  EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError());
361
362  // Test GetOrientation.
363  webrtc::VideoCaptureRotation orientation;
364  char dummy_name[5];
365  EXPECT_NE(0, dev_info->GetOrientation(dummy_name, orientation));
366
367  // Test SetRotation.
368  EXPECT_NE(0, video_engine.capture->SetRotateCapturedFrames(
369      capture_id, webrtc::RotateCapturedFrame_90));
370  EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError());
371
372  // Allocate capture device.
373  EXPECT_EQ(0, video_engine.capture->AllocateCaptureDevice(*vcpm, capture_id));
374
375  EXPECT_EQ(0, video_engine.capture->SetRotateCapturedFrames(
376      capture_id, webrtc::RotateCapturedFrame_0));
377  EXPECT_EQ(0, video_engine.capture->SetRotateCapturedFrames(
378      capture_id, webrtc::RotateCapturedFrame_90));
379  EXPECT_EQ(0, video_engine.capture->SetRotateCapturedFrames(
380      capture_id, webrtc::RotateCapturedFrame_180));
381  EXPECT_EQ(0, video_engine.capture->SetRotateCapturedFrames(
382      capture_id, webrtc::RotateCapturedFrame_270));
383
384  // Release the capture device
385  EXPECT_EQ(0, video_engine.capture->ReleaseCaptureDevice(capture_id));
386
387  /// **************************************************************
388  //  Testing finished. Tear down Video Engine
389  /// **************************************************************
390  delete dev_info;
391  vcpm->Release();
392}
393
394void ViEAutoTest::ViECaptureExternalCaptureTest() {
395  /// **************************************************************
396  //  Begin create/initialize WebRTC Video Engine for testing
397  /// **************************************************************
398
399  TbInterfaces video_engine("video_engineCaptureExternalCaptureTest");
400  TbVideoChannel channel(video_engine);
401  channel.StartReceive();
402  channel.StartSend();
403
404  webrtc::VideoCaptureExternal* external_capture = NULL;
405  int capture_id = 0;
406
407  // Allocate the external capture device.
408  webrtc::VideoCaptureModule* vcpm =
409      webrtc::VideoCaptureFactory::Create(0, external_capture);
410  EXPECT_TRUE(vcpm != NULL);
411  EXPECT_TRUE(external_capture != NULL);
412  vcpm->AddRef();
413
414  EXPECT_EQ(0, video_engine.capture->AllocateCaptureDevice(*vcpm, capture_id));
415
416  // Connect the capture device to the channel.
417  EXPECT_EQ(0, video_engine.capture->ConnectCaptureDevice(capture_id,
418                                                 channel.videoChannel));
419
420  // Render the local capture.
421  EXPECT_EQ(0, video_engine.render->AddRenderer(capture_id, _window1, 1, 0.0,
422                                                0.0, 1.0, 1.0));
423
424  // Render the remote capture.
425  EXPECT_EQ(0, video_engine.render->AddRenderer(channel.videoChannel, _window2,
426                                                1, 0.0, 0.0, 1.0, 1.0));
427  EXPECT_EQ(0, video_engine.render->StartRender(capture_id));
428  EXPECT_EQ(0, video_engine.render->StartRender(channel.videoChannel));
429
430  // Register observer.
431  CaptureObserver observer;
432  EXPECT_EQ(0, video_engine.capture->RegisterObserver(capture_id, observer));
433
434  // Enable brightness alarm.
435  EXPECT_EQ(0, video_engine.capture->EnableBrightnessAlarm(capture_id, true));
436
437  CaptureEffectFilter effect_filter(176, 144);
438  EXPECT_EQ(0, video_engine.image_process->RegisterCaptureEffectFilter(
439      capture_id, effect_filter));
440
441  // Call started.
442  ViETest::Log("You should see local preview from external capture\n"
443               "in window 1 and the remote video in window 2.\n");
444
445  /// **************************************************************
446  //  Engine ready. Begin testing class
447  /// **************************************************************
448  const unsigned int video_frame_length = (176 * 144 * 3) / 2;
449  unsigned char* video_frame = new unsigned char[video_frame_length];
450  memset(video_frame, 128, 176 * 144);
451
452  int frame_count = 0;
453  webrtc::VideoCaptureCapability capability;
454  capability.width = 176;
455  capability.height = 144;
456  capability.rawType = webrtc::kVideoI420;
457
458  ViETest::Log("Testing external capturing and frame rate callbacks.");
459  // TODO(mflodman) Change when using a real file!
460  // while (fread(video_frame, video_frame_length, 1, foreman) == 1)
461  while (frame_count < 120) {
462    external_capture->IncomingFrame(
463        video_frame, video_frame_length, capability,
464        webrtc::TickTime::MillisecondTimestamp());
465    AutoTestSleep(33);
466
467    if (effect_filter.number_of_captured_frames_ > 2) {
468      EXPECT_EQ(webrtc::Normal, observer.brightness_) <<
469          "Brightness or picture alarm should not have been called yet.";
470      EXPECT_EQ(webrtc::AlarmCleared, observer.alarm_) <<
471          "Brightness or picture alarm should not have been called yet.";
472    }
473    frame_count++;
474  }
475
476  // Test brightness alarm.
477  // Test bright image.
478  for (int i = 0; i < 176 * 144; ++i) {
479    if (video_frame[i] <= 155)
480      video_frame[i] = video_frame[i] + 100;
481    else
482      video_frame[i] = 255;
483  }
484  ViETest::Log("Testing Brighness alarm");
485  for (int frame = 0; frame < 30; ++frame) {
486    external_capture->IncomingFrame(
487        video_frame, video_frame_length, capability,
488        webrtc::TickTime::MillisecondTimestamp());
489    AutoTestSleep(33);
490  }
491  EXPECT_EQ(webrtc::Bright, observer.brightness_) <<
492      "Should be bright at this point since we are using a bright image.";
493
494  // Test Dark image
495  for (int i = 0; i < 176 * 144; ++i) {
496    video_frame[i] = video_frame[i] > 200 ? video_frame[i] - 200 : 0;
497  }
498  for (int frame = 0; frame < 30; ++frame) {
499    external_capture->IncomingFrame(
500        video_frame, video_frame_length, capability,
501        webrtc::TickTime::MillisecondTimestamp());
502    AutoTestSleep(33);
503  }
504  EXPECT_EQ(webrtc::Dark, observer.brightness_) <<
505      "Should be dark at this point since we are using a dark image.";
506  EXPECT_GT(effect_filter.number_of_captured_frames_, 150) <<
507      "Frames should have been played.";
508
509  EXPECT_GE(observer.frame_rate_, 29) <<
510      "Frame rate callback should be approximately correct.";
511  EXPECT_LE(observer.frame_rate_, 30) <<
512      "Frame rate callback should be approximately correct.";
513
514  // Test no picture alarm
515  ViETest::Log("Testing NoPictureAlarm.");
516  AutoTestSleep(1050);
517
518  EXPECT_EQ(webrtc::AlarmRaised, observer.alarm_) <<
519      "No picture alarm should be raised.";
520  for (int frame = 0; frame < 10; ++frame) {
521    external_capture->IncomingFrame(
522        video_frame, video_frame_length, capability,
523        webrtc::TickTime::MillisecondTimestamp());
524    AutoTestSleep(33);
525  }
526  EXPECT_EQ(webrtc::AlarmCleared, observer.alarm_) <<
527  "Alarm should be cleared since ge just got some data.";
528
529  delete video_frame;
530
531  // Release the capture device
532  EXPECT_EQ(0, video_engine.capture->ReleaseCaptureDevice(capture_id));
533
534  // Release the capture device again
535  EXPECT_NE(0, video_engine.capture->ReleaseCaptureDevice(capture_id));
536  EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError());
537  vcpm->Release();
538
539  /// **************************************************************
540  //  Testing finished. Tear down Video Engine
541  /// **************************************************************
542}
543