2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
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"
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.");
33 class CaptureObserver : public webrtc::ViECaptureObserver {
36 : brightness_(webrtc::Normal),
37 alarm_(webrtc::AlarmCleared),
40 virtual void BrightnessAlarm(const int capture_id,
41 const webrtc::Brightness brightness) {
42 brightness_ = brightness;
45 ViETest::Log(" BrightnessAlarm Normal");
48 ViETest::Log(" BrightnessAlarm Bright");
51 ViETest::Log(" BrightnessAlarm Dark");
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;
62 virtual void NoPictureAlarm(const int capture_id,
63 const webrtc::CaptureAlarm alarm) {
65 if (alarm == webrtc::AlarmRaised) {
66 ViETest::Log("NoPictureAlarm CARaised.");
68 ViETest::Log("NoPictureAlarm CACleared.");
72 webrtc::Brightness brightness_;
73 webrtc::CaptureAlarm alarm_;
74 unsigned char frame_rate_;
77 class CaptureEffectFilter : public webrtc::ViEEffectFilter {
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) {
85 // Implements video_engineEffectFilter.
86 virtual int Transform(int size,
87 unsigned char* frame_buffer,
89 unsigned int timestamp,
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_;
99 int number_of_captured_frames_;
102 unsigned int expected_width_;
103 unsigned int expected_height_;
106 void ViEAutoTest::ViECaptureStandardTest() {
107 /// **************************************************************
108 // Begin create/initialize WebRTC Video Engine for testing
109 /// **************************************************************
111 /// **************************************************************
112 // Engine ready. Begin testing class
113 /// **************************************************************
115 TbInterfaces video_engine("video_engineCaptureStandardTest");
117 webrtc::VideoCaptureModule::DeviceInfo* dev_info =
118 webrtc::VideoCaptureFactory::CreateDeviceInfo(0);
119 ASSERT_TRUE(dev_info != NULL);
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)";
127 #if !defined(WEBRTC_MAC)
128 int capture_device_id[10] = {0};
129 webrtc::VideoCaptureModule* vcpms[10] = {0};
132 // Check capabilities
133 for (int device_index = 0; device_index < number_of_capture_devices;
135 char device_name[128];
136 char device_unique_name[512];
138 EXPECT_EQ(0, dev_info->GetDeviceName(device_index,
142 sizeof(device_unique_name)));
143 ViETest::Log("Found capture device %s\nUnique name %s",
144 device_name, device_unique_name);
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);
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,
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);
169 // Capture Capability Functions are not supported on WEBRTC_MAC.
170 #if !defined(WEBRTC_MAC)
172 // Check allocation. Try to allocate them all after each other.
173 for (int device_index = 0; device_index < number_of_capture_devices;
175 char device_name[128];
176 char device_unique_name[512];
177 EXPECT_EQ(0, dev_info->GetDeviceName(device_index,
181 sizeof(device_unique_name)));
182 webrtc::VideoCaptureModule* vcpm =
183 webrtc::VideoCaptureFactory::Create(device_index, device_unique_name);
184 EXPECT_TRUE(vcpm != NULL);
189 vcpms[device_index] = vcpm;
191 EXPECT_EQ(0, video_engine.capture->AllocateCaptureDevice(
192 *vcpm, capture_device_id[device_index]));
194 webrtc::VideoCaptureCapability capability;
195 EXPECT_EQ(0, dev_info->GetCapability(device_unique_name, 0, capability));
197 // Test that the camera select the closest capability to the selected
199 CaptureEffectFilter filter(capability.width, capability.height);
200 EXPECT_EQ(0, video_engine.image_process->RegisterCaptureEffectFilter(
201 capture_device_id[device_index], filter));
203 ViETest::Log("Testing Device %s capability width %d height %d",
204 device_unique_name, capability.width, capability.height);
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;
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;
220 EXPECT_EQ(0, video_engine.capture->StartCapture(
221 capture_device_id[device_index], vie_capability));
222 webrtc::TickTime start_time = webrtc::TickTime::Now();
224 while (filter.number_of_captured_frames_ < 10 &&
225 (webrtc::TickTime::Now() - start_time).Milliseconds() < 10000) {
229 EXPECT_GT(filter.number_of_captured_frames_, 9)
230 << "Should capture at least some frames";
232 EXPECT_EQ(0, video_engine.image_process->DeregisterCaptureEffectFilter(
233 capture_device_id[device_index]));
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]));
243 /// **************************************************************
244 // Testing finished. Tear down Video Engine
245 /// **************************************************************
248 // Stop all started capture devices.
249 for (int device_index = 0; device_index < number_of_capture_devices;
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();
261 #endif // !WEBRTC_MAC
264 void ViEAutoTest::ViECaptureExtendedTest() {
265 ViECaptureExternalCaptureTest();
268 void ViEAutoTest::ViECaptureAPITest() {
269 /// **************************************************************
270 // Begin create/initialize WebRTC Video Engine for testing
271 /// **************************************************************
273 /// **************************************************************
274 // Engine ready. Begin testing class
275 /// **************************************************************
276 TbInterfaces video_engine("video_engineCaptureAPITest");
278 video_engine.capture->NumberOfCaptureDevices();
280 char device_name[128];
281 char device_unique_name[512];
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)";
290 // Get the first capture device
291 EXPECT_EQ(0, dev_info->GetDeviceName(0, device_name,
294 sizeof(device_unique_name)));
296 webrtc::VideoCaptureModule* vcpm =
297 webrtc::VideoCaptureFactory::Create(0, device_unique_name);
299 EXPECT_TRUE(vcpm != NULL);
301 // Allocate capture device.
302 EXPECT_EQ(0, video_engine.capture->AllocateCaptureDevice(*vcpm, capture_id));
304 // Start the capture device.
305 EXPECT_EQ(0, video_engine.capture->StartCapture(capture_id));
307 // Start again. Should fail.
308 EXPECT_NE(0, video_engine.capture->StartCapture(capture_id));
309 EXPECT_EQ(kViECaptureDeviceAlreadyStarted, video_engine.LastError());
311 // Start invalid capture device.
312 EXPECT_NE(0, video_engine.capture->StartCapture(capture_id + 1));
313 EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError());
315 // Stop invalid capture device.
316 EXPECT_NE(0, video_engine.capture->StopCapture(capture_id + 1));
317 EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError());
319 // Stop the capture device.
320 EXPECT_EQ(0, video_engine.capture->StopCapture(capture_id));
322 // Stop the capture device again.
323 EXPECT_NE(0, video_engine.capture->StopCapture(capture_id));
324 EXPECT_EQ(kViECaptureDeviceNotStarted, video_engine.LastError());
326 // Connect to invalid channel.
327 EXPECT_NE(0, video_engine.capture->ConnectCaptureDevice(capture_id, 0));
328 EXPECT_EQ(kViECaptureDeviceInvalidChannelId,
329 video_engine.LastError());
331 TbVideoChannel channel(video_engine);
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());
338 // Connect the capture device to the channel.
339 EXPECT_EQ(0, video_engine.capture->ConnectCaptureDevice(capture_id,
340 channel.videoChannel));
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());
348 // Start the capture device.
349 EXPECT_EQ(0, video_engine.capture->StartCapture(capture_id));
351 // Release invalid capture device.
352 EXPECT_NE(0, video_engine.capture->ReleaseCaptureDevice(capture_id + 1));
353 EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError());
355 // Release the capture device.
356 EXPECT_EQ(0, video_engine.capture->ReleaseCaptureDevice(capture_id));
358 // Release the capture device again.
359 EXPECT_NE(0, video_engine.capture->ReleaseCaptureDevice(capture_id));
360 EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError());
362 // Test GetOrientation.
363 webrtc::VideoCaptureRotation orientation;
365 EXPECT_NE(0, dev_info->GetOrientation(dummy_name, orientation));
368 EXPECT_NE(0, video_engine.capture->SetRotateCapturedFrames(
369 capture_id, webrtc::RotateCapturedFrame_90));
370 EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError());
372 // Allocate capture device.
373 EXPECT_EQ(0, video_engine.capture->AllocateCaptureDevice(*vcpm, capture_id));
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));
384 // Release the capture device
385 EXPECT_EQ(0, video_engine.capture->ReleaseCaptureDevice(capture_id));
387 /// **************************************************************
388 // Testing finished. Tear down Video Engine
389 /// **************************************************************
394 void ViEAutoTest::ViECaptureExternalCaptureTest() {
395 /// **************************************************************
396 // Begin create/initialize WebRTC Video Engine for testing
397 /// **************************************************************
399 TbInterfaces video_engine("video_engineCaptureExternalCaptureTest");
400 TbVideoChannel channel(video_engine);
401 channel.StartReceive();
404 webrtc::VideoCaptureExternal* external_capture = NULL;
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);
414 EXPECT_EQ(0, video_engine.capture->AllocateCaptureDevice(*vcpm, capture_id));
416 // Connect the capture device to the channel.
417 EXPECT_EQ(0, video_engine.capture->ConnectCaptureDevice(capture_id,
418 channel.videoChannel));
420 // Render the local capture.
421 EXPECT_EQ(0, video_engine.render->AddRenderer(capture_id, _window1, 1, 0.0,
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));
430 // Register observer.
431 CaptureObserver observer;
432 EXPECT_EQ(0, video_engine.capture->RegisterObserver(capture_id, observer));
434 // Enable brightness alarm.
435 EXPECT_EQ(0, video_engine.capture->EnableBrightnessAlarm(capture_id, true));
437 CaptureEffectFilter effect_filter(176, 144);
438 EXPECT_EQ(0, video_engine.image_process->RegisterCaptureEffectFilter(
439 capture_id, effect_filter));
442 ViETest::Log("You should see local preview from external capture\n"
443 "in window 1 and the remote video in window 2.\n");
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);
453 webrtc::VideoCaptureCapability capability;
454 capability.width = 176;
455 capability.height = 144;
456 capability.rawType = webrtc::kVideoI420;
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());
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.";
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;
482 video_frame[i] = 255;
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());
491 EXPECT_EQ(webrtc::Bright, observer.brightness_) <<
492 "Should be bright at this point since we are using a bright image.";
495 for (int i = 0; i < 176 * 144; ++i) {
496 video_frame[i] = video_frame[i] > 200 ? video_frame[i] - 200 : 0;
498 for (int frame = 0; frame < 30; ++frame) {
499 external_capture->IncomingFrame(
500 video_frame, video_frame_length, capability,
501 webrtc::TickTime::MillisecondTimestamp());
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.";
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.";
514 // Test no picture alarm
515 ViETest::Log("Testing NoPictureAlarm.");
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());
526 EXPECT_EQ(webrtc::AlarmCleared, observer.alarm_) <<
527 "Alarm should be cleared since ge just got some data.";
531 // Release the capture device
532 EXPECT_EQ(0, video_engine.capture->ReleaseCaptureDevice(capture_id));
534 // Release the capture device again
535 EXPECT_NE(0, video_engine.capture->ReleaseCaptureDevice(capture_id));
536 EXPECT_EQ(kViECaptureDeviceDoesNotExist, video_engine.LastError());
539 /// **************************************************************
540 // Testing finished. Tear down Video Engine
541 /// **************************************************************