1/* 2 * Copyright 2017 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#import <OCMock/OCMock.h> 12 13#if TARGET_OS_IPHONE 14#import <UIKit/UIKit.h> 15#endif 16 17#include "rtc_base/gunit.h" 18 19#import "base/RTCVideoFrame.h" 20#import "components/capturer/RTCCameraVideoCapturer.h" 21#import "helpers/AVCaptureSession+DevicePosition.h" 22#import "helpers/RTCDispatcher.h" 23 24#if TARGET_OS_IPHONE 25// Helper method. 26CMSampleBufferRef createTestSampleBufferRef() { 27 28 // This image is already in the testing bundle. 29 UIImage *image = [UIImage imageNamed:@"Default.png"]; 30 CGSize size = image.size; 31 CGImageRef imageRef = [image CGImage]; 32 33 CVPixelBufferRef pixelBuffer = nullptr; 34 CVPixelBufferCreate(kCFAllocatorDefault, size.width, size.height, kCVPixelFormatType_32ARGB, nil, 35 &pixelBuffer); 36 37 CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); 38 // We don't care about bitsPerComponent and bytesPerRow so arbitrary value of 8 for both. 39 CGContextRef context = CGBitmapContextCreate(nil, size.width, size.height, 8, 8 * size.width, 40 rgbColorSpace, kCGImageAlphaPremultipliedFirst); 41 42 CGContextDrawImage( 43 context, CGRectMake(0, 0, CGImageGetWidth(imageRef), CGImageGetHeight(imageRef)), imageRef); 44 45 CGColorSpaceRelease(rgbColorSpace); 46 CGContextRelease(context); 47 48 // We don't really care about the timing. 49 CMSampleTimingInfo timing = {kCMTimeInvalid, kCMTimeInvalid, kCMTimeInvalid}; 50 CMVideoFormatDescriptionRef description = nullptr; 51 CMVideoFormatDescriptionCreateForImageBuffer(NULL, pixelBuffer, &description); 52 53 CMSampleBufferRef sampleBuffer = nullptr; 54 CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, pixelBuffer, YES, NULL, NULL, description, 55 &timing, &sampleBuffer); 56 CFRelease(pixelBuffer); 57 58 return sampleBuffer; 59 60} 61#endif 62@interface RTC_OBJC_TYPE (RTCCameraVideoCapturer) 63(Tests)<AVCaptureVideoDataOutputSampleBufferDelegate> - 64 (instancetype)initWithDelegate 65 : (__weak id<RTC_OBJC_TYPE(RTCVideoCapturerDelegate)>)delegate captureSession 66 : (AVCaptureSession *)captureSession; 67@end 68 69@interface RTCCameraVideoCapturerTests : NSObject 70@property(nonatomic, strong) id delegateMock; 71@property(nonatomic, strong) id deviceMock; 72@property(nonatomic, strong) id captureConnectionMock; 73@property(nonatomic, strong) id captureSessionMock; 74@property(nonatomic, strong) RTC_OBJC_TYPE(RTCCameraVideoCapturer) * capturer; 75@end 76 77@implementation RTCCameraVideoCapturerTests 78@synthesize delegateMock = _delegateMock; 79@synthesize deviceMock = _deviceMock; 80@synthesize captureConnectionMock = _captureConnectionMock; 81@synthesize captureSessionMock = _captureSessionMock; 82@synthesize capturer = _capturer; 83 84- (void)setup { 85 self.delegateMock = OCMProtocolMock(@protocol(RTC_OBJC_TYPE(RTCVideoCapturerDelegate))); 86 self.captureConnectionMock = OCMClassMock([AVCaptureConnection class]); 87 self.capturer = 88 [[RTC_OBJC_TYPE(RTCCameraVideoCapturer) alloc] initWithDelegate:self.delegateMock]; 89 self.deviceMock = [self createDeviceMock]; 90} 91 92- (void)setupWithMockedCaptureSession { 93 self.captureSessionMock = OCMStrictClassMock([AVCaptureSession class]); 94 OCMStub([self.captureSessionMock setSessionPreset:[OCMArg any]]); 95 OCMStub([self.captureSessionMock setUsesApplicationAudioSession:NO]); 96 OCMStub([self.captureSessionMock canAddOutput:[OCMArg any]]).andReturn(YES); 97 OCMStub([self.captureSessionMock addOutput:[OCMArg any]]); 98 OCMStub([self.captureSessionMock beginConfiguration]); 99 OCMStub([self.captureSessionMock commitConfiguration]); 100 self.delegateMock = OCMProtocolMock(@protocol(RTC_OBJC_TYPE(RTCVideoCapturerDelegate))); 101 self.captureConnectionMock = OCMClassMock([AVCaptureConnection class]); 102 self.capturer = 103 [[RTC_OBJC_TYPE(RTCCameraVideoCapturer) alloc] initWithDelegate:self.delegateMock 104 captureSession:self.captureSessionMock]; 105 self.deviceMock = [self createDeviceMock]; 106} 107 108- (void)tearDown { 109 [self.delegateMock stopMocking]; 110 [self.deviceMock stopMocking]; 111 self.delegateMock = nil; 112 self.deviceMock = nil; 113 self.capturer = nil; 114} 115 116#pragma mark - utils 117 118- (id)createDeviceMock { 119 return OCMClassMock([AVCaptureDevice class]); 120} 121 122#pragma mark - test cases 123 124- (void)testSetupSession { 125 AVCaptureSession *session = self.capturer.captureSession; 126 EXPECT_TRUE(session != nil); 127 128#if TARGET_OS_IPHONE 129 EXPECT_EQ(session.sessionPreset, AVCaptureSessionPresetInputPriority); 130 EXPECT_EQ(session.usesApplicationAudioSession, NO); 131#endif 132 EXPECT_EQ(session.outputs.count, 1u); 133} 134 135- (void)testSetupSessionOutput { 136 AVCaptureVideoDataOutput *videoOutput = self.capturer.captureSession.outputs[0]; 137 EXPECT_EQ(videoOutput.alwaysDiscardsLateVideoFrames, NO); 138 EXPECT_EQ(videoOutput.sampleBufferDelegate, self.capturer); 139} 140 141- (void)testSupportedFormatsForDevice { 142 // given 143 id validFormat1 = OCMClassMock([AVCaptureDeviceFormat class]); 144 CMVideoFormatDescriptionRef format; 145 146 // We don't care about width and heigth so arbitrary 123 and 456 values. 147 int width = 123; 148 int height = 456; 149 CMVideoFormatDescriptionCreate(nil, kCVPixelFormatType_420YpCbCr8PlanarFullRange, width, height, 150 nil, &format); 151 OCMStub([validFormat1 formatDescription]).andReturn(format); 152 153 id validFormat2 = OCMClassMock([AVCaptureDeviceFormat class]); 154 CMVideoFormatDescriptionCreate(nil, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, width, 155 height, nil, &format); 156 OCMStub([validFormat2 formatDescription]).andReturn(format); 157 158 id invalidFormat = OCMClassMock([AVCaptureDeviceFormat class]); 159 CMVideoFormatDescriptionCreate(nil, kCVPixelFormatType_422YpCbCr8_yuvs, width, height, nil, 160 &format); 161 OCMStub([invalidFormat formatDescription]).andReturn(format); 162 163 NSArray *formats = @[ validFormat1, validFormat2, invalidFormat ]; 164 OCMStub([self.deviceMock formats]).andReturn(formats); 165 166 // when 167 NSArray *supportedFormats = 168 [RTC_OBJC_TYPE(RTCCameraVideoCapturer) supportedFormatsForDevice:self.deviceMock]; 169 170 // then 171 EXPECT_EQ(supportedFormats.count, 3u); 172 EXPECT_TRUE([supportedFormats containsObject:validFormat1]); 173 EXPECT_TRUE([supportedFormats containsObject:validFormat2]); 174 EXPECT_TRUE([supportedFormats containsObject:invalidFormat]); 175 176 // cleanup 177 [validFormat1 stopMocking]; 178 [validFormat2 stopMocking]; 179 [invalidFormat stopMocking]; 180 validFormat1 = nil; 181 validFormat2 = nil; 182 invalidFormat = nil; 183} 184 185- (void)testDelegateCallbackNotCalledWhenInvalidBuffer { 186 // given 187 CMSampleBufferRef sampleBuffer = nullptr; 188 [[self.delegateMock reject] capturer:[OCMArg any] didCaptureVideoFrame:[OCMArg any]]; 189 190 // when 191 [self.capturer captureOutput:self.capturer.captureSession.outputs[0] 192 didOutputSampleBuffer:sampleBuffer 193 fromConnection:self.captureConnectionMock]; 194 195 // then 196 [self.delegateMock verify]; 197} 198 199 200- (void)testDelegateCallbackWithValidBufferAndOrientationUpdate { 201#if TARGET_OS_IPHONE 202 [UIDevice.currentDevice setValue:@(UIDeviceOrientationPortraitUpsideDown) forKey:@"orientation"]; 203 CMSampleBufferRef sampleBuffer = createTestSampleBufferRef(); 204 205 // then 206 [[self.delegateMock expect] capturer:self.capturer 207 didCaptureVideoFrame:[OCMArg checkWithBlock:^BOOL(RTC_OBJC_TYPE(RTCVideoFrame) * 208 expectedFrame) { 209 EXPECT_EQ(expectedFrame.rotation, RTCVideoRotation_270); 210 return YES; 211 }]]; 212 213 // when 214 NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; 215 [center postNotificationName:UIDeviceOrientationDidChangeNotification object:nil]; 216 217 // We need to wait for the dispatch to finish. 218 WAIT(0, 1000); 219 220 [self.capturer captureOutput:self.capturer.captureSession.outputs[0] 221 didOutputSampleBuffer:sampleBuffer 222 fromConnection:self.captureConnectionMock]; 223 224 [self.delegateMock verify]; 225 CFRelease(sampleBuffer); 226#endif 227} 228 229- (void)testRotationCamera:(AVCaptureDevicePosition)camera 230 withOrientation:(UIDeviceOrientation)deviceOrientation { 231#if TARGET_OS_IPHONE 232 // Mock the AVCaptureConnection as we will get the camera position from the connection's 233 // input ports. 234 AVCaptureDeviceInput *inputPortMock = OCMClassMock([AVCaptureDeviceInput class]); 235 AVCaptureInputPort *captureInputPort = OCMClassMock([AVCaptureInputPort class]); 236 NSArray *inputPortsArrayMock = @[captureInputPort]; 237 AVCaptureDevice *captureDeviceMock = OCMClassMock([AVCaptureDevice class]); 238 OCMStub(((AVCaptureConnection *)self.captureConnectionMock).inputPorts). 239 andReturn(inputPortsArrayMock); 240 OCMStub(captureInputPort.input).andReturn(inputPortMock); 241 OCMStub(inputPortMock.device).andReturn(captureDeviceMock); 242 OCMStub(captureDeviceMock.position).andReturn(camera); 243 244 [UIDevice.currentDevice setValue:@(deviceOrientation) forKey:@"orientation"]; 245 246 CMSampleBufferRef sampleBuffer = createTestSampleBufferRef(); 247 248 [[self.delegateMock expect] capturer:self.capturer 249 didCaptureVideoFrame:[OCMArg checkWithBlock:^BOOL(RTC_OBJC_TYPE(RTCVideoFrame) * 250 expectedFrame) { 251 if (camera == AVCaptureDevicePositionFront) { 252 if (deviceOrientation == UIDeviceOrientationLandscapeLeft) { 253 EXPECT_EQ(expectedFrame.rotation, RTCVideoRotation_180); 254 } else if (deviceOrientation == UIDeviceOrientationLandscapeRight) { 255 EXPECT_EQ(expectedFrame.rotation, RTCVideoRotation_0); 256 } 257 } else if (camera == AVCaptureDevicePositionBack) { 258 if (deviceOrientation == UIDeviceOrientationLandscapeLeft) { 259 EXPECT_EQ(expectedFrame.rotation, RTCVideoRotation_0); 260 } else if (deviceOrientation == UIDeviceOrientationLandscapeRight) { 261 EXPECT_EQ(expectedFrame.rotation, RTCVideoRotation_180); 262 } 263 } 264 return YES; 265 }]]; 266 267 NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; 268 [center postNotificationName:UIDeviceOrientationDidChangeNotification object:nil]; 269 270 // We need to wait for the dispatch to finish. 271 WAIT(0, 1000); 272 273 [self.capturer captureOutput:self.capturer.captureSession.outputs[0] 274 didOutputSampleBuffer:sampleBuffer 275 fromConnection:self.captureConnectionMock]; 276 277 [self.delegateMock verify]; 278 279 CFRelease(sampleBuffer); 280#endif 281} 282 283- (void)setExif:(CMSampleBufferRef)sampleBuffer { 284 CFMutableDictionaryRef exif = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL); 285 CFDictionarySetValue(exif, CFSTR("LensModel"), CFSTR("iPhone SE back camera 4.15mm f/2.2")); 286 CMSetAttachment(sampleBuffer, CFSTR("{Exif}"), exif, kCMAttachmentMode_ShouldPropagate); 287} 288 289- (void)testRotationFrame { 290#if TARGET_OS_IPHONE 291 // Mock the AVCaptureConnection as we will get the camera position from the connection's 292 // input ports. 293 AVCaptureDeviceInput *inputPortMock = OCMClassMock([AVCaptureDeviceInput class]); 294 AVCaptureInputPort *captureInputPort = OCMClassMock([AVCaptureInputPort class]); 295 NSArray *inputPortsArrayMock = @[captureInputPort]; 296 AVCaptureDevice *captureDeviceMock = OCMClassMock([AVCaptureDevice class]); 297 OCMStub(((AVCaptureConnection *)self.captureConnectionMock).inputPorts). 298 andReturn(inputPortsArrayMock); 299 OCMStub(captureInputPort.input).andReturn(inputPortMock); 300 OCMStub(inputPortMock.device).andReturn(captureDeviceMock); 301 OCMStub(captureDeviceMock.position).andReturn(AVCaptureDevicePositionFront); 302 303 [UIDevice.currentDevice setValue:@(UIDeviceOrientationLandscapeLeft) forKey:@"orientation"]; 304 305 CMSampleBufferRef sampleBuffer = createTestSampleBufferRef(); 306 307 [[self.delegateMock expect] capturer:self.capturer 308 didCaptureVideoFrame:[OCMArg checkWithBlock:^BOOL(RTC_OBJC_TYPE(RTCVideoFrame) * 309 expectedFrame) { 310 // Front camera and landscape left should return 180. But the frame says its 311 // from the back camera, so rotation should be 0. 312 EXPECT_EQ(expectedFrame.rotation, RTCVideoRotation_0); 313 return YES; 314 }]]; 315 316 NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; 317 [center postNotificationName:UIDeviceOrientationDidChangeNotification object:nil]; 318 319 // We need to wait for the dispatch to finish. 320 WAIT(0, 1000); 321 322 [self setExif:sampleBuffer]; 323 324 [self.capturer captureOutput:self.capturer.captureSession.outputs[0] 325 didOutputSampleBuffer:sampleBuffer 326 fromConnection:self.captureConnectionMock]; 327 328 [self.delegateMock verify]; 329 CFRelease(sampleBuffer); 330#endif 331} 332 333- (void)testImageExif { 334#if TARGET_OS_IPHONE 335 CMSampleBufferRef sampleBuffer = createTestSampleBufferRef(); 336 [self setExif:sampleBuffer]; 337 338 AVCaptureDevicePosition cameraPosition = [AVCaptureSession 339 devicePositionForSampleBuffer:sampleBuffer]; 340 EXPECT_EQ(cameraPosition, AVCaptureDevicePositionBack); 341#endif 342} 343 344- (void)testStartingAndStoppingCapture { 345 id expectedDeviceInputMock = OCMClassMock([AVCaptureDeviceInput class]); 346 id captureDeviceInputMock = OCMClassMock([AVCaptureDeviceInput class]); 347 OCMStub([captureDeviceInputMock deviceInputWithDevice:self.deviceMock error:[OCMArg setTo:nil]]) 348 .andReturn(expectedDeviceInputMock); 349 350 OCMStub([self.deviceMock lockForConfiguration:[OCMArg setTo:nil]]).andReturn(YES); 351 OCMStub([self.deviceMock unlockForConfiguration]); 352 OCMStub([_captureSessionMock canAddInput:expectedDeviceInputMock]).andReturn(YES); 353 OCMStub([_captureSessionMock inputs]).andReturn(@[ expectedDeviceInputMock ]); 354 OCMStub([_captureSessionMock removeInput:expectedDeviceInputMock]); 355 356 // Set expectation that the capture session should be started with correct device. 357 OCMExpect([_captureSessionMock addInput:expectedDeviceInputMock]); 358 OCMExpect([_captureSessionMock startRunning]); 359 OCMExpect([_captureSessionMock stopRunning]); 360 361 id format = OCMClassMock([AVCaptureDeviceFormat class]); 362 [self.capturer startCaptureWithDevice:self.deviceMock format:format fps:30]; 363 [self.capturer stopCapture]; 364 365 // Start capture code is dispatched async. 366 OCMVerifyAllWithDelay(_captureSessionMock, 15); 367} 368 369- (void)testStartCaptureFailingToLockForConfiguration { 370 // The captureSessionMock is a strict mock, so this test will crash if the startCapture 371 // method does not return when failing to lock for configuration. 372 OCMExpect([self.deviceMock lockForConfiguration:[OCMArg setTo:nil]]).andReturn(NO); 373 374 id format = OCMClassMock([AVCaptureDeviceFormat class]); 375 [self.capturer startCaptureWithDevice:self.deviceMock format:format fps:30]; 376 377 // Start capture code is dispatched async. 378 OCMVerifyAllWithDelay(self.deviceMock, 15); 379} 380 381- (void)testStartingAndStoppingCaptureWithCallbacks { 382 id expectedDeviceInputMock = OCMClassMock([AVCaptureDeviceInput class]); 383 id captureDeviceInputMock = OCMClassMock([AVCaptureDeviceInput class]); 384 OCMStub([captureDeviceInputMock deviceInputWithDevice:self.deviceMock error:[OCMArg setTo:nil]]) 385 .andReturn(expectedDeviceInputMock); 386 387 OCMStub([self.deviceMock lockForConfiguration:[OCMArg setTo:nil]]).andReturn(YES); 388 OCMStub([self.deviceMock unlockForConfiguration]); 389 OCMStub([_captureSessionMock canAddInput:expectedDeviceInputMock]).andReturn(YES); 390 OCMStub([_captureSessionMock inputs]).andReturn(@[ expectedDeviceInputMock ]); 391 OCMStub([_captureSessionMock removeInput:expectedDeviceInputMock]); 392 393 // Set expectation that the capture session should be started with correct device. 394 OCMExpect([_captureSessionMock addInput:expectedDeviceInputMock]); 395 OCMExpect([_captureSessionMock startRunning]); 396 OCMExpect([_captureSessionMock stopRunning]); 397 398 dispatch_semaphore_t completedStopSemaphore = dispatch_semaphore_create(0); 399 400 __block BOOL completedStart = NO; 401 id format = OCMClassMock([AVCaptureDeviceFormat class]); 402 [self.capturer startCaptureWithDevice:self.deviceMock 403 format:format 404 fps:30 405 completionHandler:^(NSError *error) { 406 EXPECT_EQ(error, nil); 407 completedStart = YES; 408 }]; 409 410 __block BOOL completedStop = NO; 411 [self.capturer stopCaptureWithCompletionHandler:^{ 412 completedStop = YES; 413 dispatch_semaphore_signal(completedStopSemaphore); 414 }]; 415 416 dispatch_semaphore_wait(completedStopSemaphore, 417 dispatch_time(DISPATCH_TIME_NOW, 15.0 * NSEC_PER_SEC)); 418 OCMVerifyAllWithDelay(_captureSessionMock, 15); 419 EXPECT_TRUE(completedStart); 420 EXPECT_TRUE(completedStop); 421} 422 423- (void)testStartCaptureFailingToLockForConfigurationWithCallback { 424 id expectedDeviceInputMock = OCMClassMock([AVCaptureDeviceInput class]); 425 id captureDeviceInputMock = OCMClassMock([AVCaptureDeviceInput class]); 426 OCMStub([captureDeviceInputMock deviceInputWithDevice:self.deviceMock error:[OCMArg setTo:nil]]) 427 .andReturn(expectedDeviceInputMock); 428 429 id errorMock = OCMClassMock([NSError class]); 430 431 OCMStub([self.deviceMock lockForConfiguration:[OCMArg setTo:errorMock]]).andReturn(NO); 432 OCMStub([_captureSessionMock canAddInput:expectedDeviceInputMock]).andReturn(YES); 433 OCMStub([self.deviceMock unlockForConfiguration]); 434 435 OCMExpect([_captureSessionMock addInput:expectedDeviceInputMock]); 436 437 dispatch_semaphore_t completedStartSemaphore = dispatch_semaphore_create(0); 438 __block NSError *callbackError = nil; 439 440 id format = OCMClassMock([AVCaptureDeviceFormat class]); 441 [self.capturer startCaptureWithDevice:self.deviceMock 442 format:format 443 fps:30 444 completionHandler:^(NSError *error) { 445 callbackError = error; 446 dispatch_semaphore_signal(completedStartSemaphore); 447 }]; 448 449 long ret = dispatch_semaphore_wait(completedStartSemaphore, 450 dispatch_time(DISPATCH_TIME_NOW, 15.0 * NSEC_PER_SEC)); 451 EXPECT_EQ(ret, 0); 452 EXPECT_EQ(callbackError, errorMock); 453} 454 455@end 456 457TEST(RTCCameraVideoCapturerTests, SetupSession) { 458 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init]; 459 [test setup]; 460 [test testSetupSession]; 461 [test tearDown]; 462} 463 464TEST(RTCCameraVideoCapturerTests, SetupSessionOutput) { 465 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init]; 466 [test setup]; 467 [test testSetupSessionOutput]; 468 [test tearDown]; 469} 470 471TEST(RTCCameraVideoCapturerTests, SupportedFormatsForDevice) { 472 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init]; 473 [test setup]; 474 [test testSupportedFormatsForDevice]; 475 [test tearDown]; 476} 477 478TEST(RTCCameraVideoCapturerTests, DelegateCallbackNotCalledWhenInvalidBuffer) { 479 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init]; 480 [test setup]; 481 [test testDelegateCallbackNotCalledWhenInvalidBuffer]; 482 [test tearDown]; 483} 484 485TEST(RTCCameraVideoCapturerTests, DelegateCallbackWithValidBufferAndOrientationUpdate) { 486 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init]; 487 [test setup]; 488 [test testDelegateCallbackWithValidBufferAndOrientationUpdate]; 489 [test tearDown]; 490} 491 492TEST(RTCCameraVideoCapturerTests, RotationCameraBackLandscapeLeft) { 493 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init]; 494 [test setup]; 495 [test testRotationCamera:AVCaptureDevicePositionBack 496 withOrientation:UIDeviceOrientationLandscapeLeft]; 497 [test tearDown]; 498} 499 500TEST(RTCCameraVideoCapturerTests, RotationCameraFrontLandscapeLeft) { 501 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init]; 502 [test setup]; 503 [test testRotationCamera:AVCaptureDevicePositionFront 504 withOrientation:UIDeviceOrientationLandscapeLeft]; 505 [test tearDown]; 506} 507 508TEST(RTCCameraVideoCapturerTests, RotationCameraBackLandscapeRight) { 509 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init]; 510 [test setup]; 511 [test testRotationCamera:AVCaptureDevicePositionBack 512 withOrientation:UIDeviceOrientationLandscapeRight]; 513 [test tearDown]; 514} 515 516TEST(RTCCameraVideoCapturerTests, RotationCameraFrontLandscapeRight) { 517 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init]; 518 [test setup]; 519 [test testRotationCamera:AVCaptureDevicePositionFront 520 withOrientation:UIDeviceOrientationLandscapeRight]; 521 [test tearDown]; 522} 523 524TEST(RTCCameraVideoCapturerTests, RotationCameraFrame) { 525 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init]; 526 [test setup]; 527 [test testRotationFrame]; 528 [test tearDown]; 529} 530 531TEST(RTCCameraVideoCapturerTests, ImageExif) { 532 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init]; 533 [test setup]; 534 [test testImageExif]; 535 [test tearDown]; 536} 537 538TEST(RTCCameraVideoCapturerTests, StartAndStopCapture) { 539 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init]; 540 [test setupWithMockedCaptureSession]; 541 [test testStartingAndStoppingCapture]; 542 [test tearDown]; 543} 544 545TEST(RTCCameraVideoCapturerTests, StartCaptureFailingToLockForConfiguration) { 546 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init]; 547 [test setupWithMockedCaptureSession]; 548 [test testStartCaptureFailingToLockForConfiguration]; 549 [test tearDown]; 550} 551 552TEST(RTCCameraVideoCapturerTests, StartAndStopCaptureWithCallbacks) { 553 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init]; 554 [test setupWithMockedCaptureSession]; 555 [test testStartingAndStoppingCaptureWithCallbacks]; 556 [test tearDown]; 557} 558 559TEST(RTCCameraVideoCapturerTests, StartCaptureFailingToLockForConfigurationWithCallback) { 560 RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init]; 561 [test setupWithMockedCaptureSession]; 562 [test testStartCaptureFailingToLockForConfigurationWithCallback]; 563 [test tearDown]; 564} 565