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
28 DEFINE_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
33 class CaptureObserver : public webrtc::ViECaptureObserver {
34 public:
CaptureObserver()35 CaptureObserver()
36 : brightness_(webrtc::Normal),
37 alarm_(webrtc::AlarmCleared),
38 frame_rate_(0) {}
39
BrightnessAlarm(const int capture_id,const webrtc::Brightness brightness)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
CapturedFrameRate(const int capture_id,const unsigned char frame_rate)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
NoPictureAlarm(const int capture_id,const webrtc::CaptureAlarm alarm)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
77 class CaptureEffectFilter : public webrtc::ViEEffectFilter {
78 public:
CaptureEffectFilter(unsigned int expected_width,unsigned int expected_height)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.
Transform(int size,unsigned char * frame_buffer,int64_t ntp_time_ms,unsigned int timestamp,unsigned int width,unsigned int height)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
ViECaptureStandardTest()106 void 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
ViECaptureExtendedTest()264 void ViEAutoTest::ViECaptureExtendedTest() {
265 ViECaptureExternalCaptureTest();
266 }
267
ViECaptureAPITest()268 void 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
ViECaptureExternalCaptureTest()394 void 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