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: 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 77 class 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 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 264 void ViEAutoTest::ViECaptureExtendedTest() { 265 ViECaptureExternalCaptureTest(); 266 } 267 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 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