Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(219)

Unified Diff: webrtc/sdk/objc/Framework/UnitTests/RTCCameraVideoCapturerTests.mm

Issue 2964703002: [iOS] Fix incorrectly oriented frames when rapidly switching between cameras. (Closed)
Patch Set: Moved common code to new class. Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/sdk/objc/Framework/UnitTests/RTCCameraVideoCapturerTests.mm
diff --git a/webrtc/sdk/objc/Framework/UnitTests/RTCCameraVideoCapturerTests.mm b/webrtc/sdk/objc/Framework/UnitTests/RTCCameraVideoCapturerTests.mm
index 3c171761ebb35f20dff2d21e5994448f5f259bbc..ba7e58e48622b517d64e82cc1f0e3ae273389166 100644
--- a/webrtc/sdk/objc/Framework/UnitTests/RTCCameraVideoCapturerTests.mm
+++ b/webrtc/sdk/objc/Framework/UnitTests/RTCCameraVideoCapturerTests.mm
@@ -218,6 +218,134 @@ CMSampleBufferRef createTestSampleBufferRef() {
#endif
}
+- (void)testRotationCamera:(AVCaptureDevicePosition)camera
+ withOrientation:(UIDeviceOrientation)deviceOrientation {
+#if TARGET_OS_IPHONE
+ // Mock the AVCaptureConnection as we will get the camera position from the connection's
+ // input ports.
+ AVCaptureDeviceInput *inputPortMock = OCMClassMock([AVCaptureDeviceInput class]);
+ AVCaptureInputPort *captureInputPort = OCMClassMock([AVCaptureInputPort class]);
+ NSArray *inputPortsArrayMock = @[captureInputPort];
+ AVCaptureDevice *captureDeviceMock = OCMClassMock([AVCaptureDevice class]);
+ OCMStub(((AVCaptureConnection *)self.captureConnectionMock).inputPorts).
+ andReturn(inputPortsArrayMock);
+ OCMStub(captureInputPort.input).andReturn(inputPortMock);
+ OCMStub(inputPortMock.device).andReturn(captureDeviceMock);
+ OCMStub(captureDeviceMock.position).andReturn(camera);
+
+ // UpsideDown -> RTCVideoRotation_0.
+ UIDevice *currentDeviceMock = OCMClassMock([UIDevice class]);
+ OCMStub(currentDeviceMock.orientation).andReturn(deviceOrientation);
+ id classMock = OCMClassMock([UIDevice class]);
+ OCMStub([classMock currentDevice]).andReturn(currentDeviceMock);
+
+ CMSampleBufferRef sampleBuffer = createTestSampleBufferRef();
+
+ [[self.delegateMock expect] capturer:self.capturer
+ didCaptureVideoFrame:[OCMArg checkWithBlock:^BOOL(RTCVideoFrame *expectedFrame) {
+ if (camera == AVCaptureDevicePositionFront) {
+ if (deviceOrientation == UIDeviceOrientationLandscapeLeft) {
+ EXPECT_EQ(expectedFrame.rotation, RTCVideoRotation_180);
+ } else if (deviceOrientation == UIDeviceOrientationLandscapeRight) {
+ EXPECT_EQ(expectedFrame.rotation, RTCVideoRotation_0);
+ }
+ } else if (camera == AVCaptureDevicePositionBack) {
+ if (deviceOrientation == UIDeviceOrientationLandscapeLeft) {
+ EXPECT_EQ(expectedFrame.rotation, RTCVideoRotation_0);
+ } else if (deviceOrientation == UIDeviceOrientationLandscapeRight) {
+ EXPECT_EQ(expectedFrame.rotation, RTCVideoRotation_180);
+ }
+ }
+ return YES;
+ }]];
+
+ NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+ [center postNotificationName:UIDeviceOrientationDidChangeNotification object:nil];
+
+ // We need to wait for the dispatch to finish.
+ WAIT(0, 1000);
+
+ [self.capturer captureOutput:self.capturer.captureSession.outputs[0]
+ didOutputSampleBuffer:sampleBuffer
+ fromConnection:self.captureConnectionMock];
+
+ [self.delegateMock verify];
+
+ [(id)currentDeviceMock stopMocking];
+ currentDeviceMock = nil;
+ [classMock stopMocking];
+ classMock = nil;
+ CFRelease(sampleBuffer);
+#endif
+}
+
+- (void)testRotationFrame {
+#if TARGET_OS_IPHONE
+ // Mock the AVCaptureConnection as we will get the camera position from the connection's
+ // input ports.
+ AVCaptureDeviceInput *inputPortMock = OCMClassMock([AVCaptureDeviceInput class]);
+ AVCaptureInputPort *captureInputPort = OCMClassMock([AVCaptureInputPort class]);
+ NSArray *inputPortsArrayMock = @[captureInputPort];
+ AVCaptureDevice *captureDeviceMock = OCMClassMock([AVCaptureDevice class]);
+ OCMStub(((AVCaptureConnection *)self.captureConnectionMock).inputPorts).
+ andReturn(inputPortsArrayMock);
+ OCMStub(captureInputPort.input).andReturn(inputPortMock);
+ OCMStub(inputPortMock.device).andReturn(captureDeviceMock);
+ OCMStub(captureDeviceMock.position).andReturn(AVCaptureDevicePositionFront);
+
+ // UpsideDown -> RTCVideoRotation_0.
+ UIDevice *currentDeviceMock = OCMClassMock([UIDevice class]);
+ OCMStub(currentDeviceMock.orientation).andReturn(UIDeviceOrientationLandscapeLeft);
+ id classMock = OCMClassMock([UIDevice class]);
+ OCMStub([classMock currentDevice]).andReturn(currentDeviceMock);
+
+ CMSampleBufferRef sampleBuffer = createTestSampleBufferRef();
+
+ [[self.delegateMock expect] capturer:self.capturer
+ didCaptureVideoFrame:[OCMArg checkWithBlock:^BOOL(RTCVideoFrame *expectedFrame) {
+ // Front camera and landscape left should return 180. But the frame says its from the back
+ // camera, so rotation should be 0.
+ EXPECT_EQ(expectedFrame.rotation, RTCVideoRotation_0);
+ return YES;
+ }]];
+
+ NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+ [center postNotificationName:UIDeviceOrientationDidChangeNotification object:nil];
+
+ // We need to wait for the dispatch to finish.
+ WAIT(0, 1000);
+
+ CFMutableDictionaryRef exif = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL);
+ CFDictionarySetValue(exif, CFSTR("LensModel"), CFSTR("iPhone SE back camera 4.15mm f/2.2"));
+ CMSetAttachment(sampleBuffer, CFSTR("{Exif}"), exif, kCMAttachmentMode_ShouldPropagate);
+
+ // switchingCameras is not public, so use invocation to set it.
+ SEL selector = NSSelectorFromString(@"setSwitchingCameras:");
+ if ([self.capturer respondsToSelector:selector]) {
magjed_webrtc 2017/07/24 10:12:51 I don't like white-box testing. I would rather you
jtt_webrtc 2017/07/24 16:40:36 Added test to test just [RTCImageHelper isFrontCam
+ NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:
+ [[self.capturer class]
+ instanceMethodSignatureForSelector:selector]];
+ [invocation setSelector:selector];
+ [invocation setTarget:self.capturer];
+ BOOL arg = true;
+ [invocation setArgument:(void *)&arg atIndex:2];
+ [invocation invoke];
+ }
+
+ [self.capturer captureOutput:self.capturer.captureSession.outputs[0]
+ didOutputSampleBuffer:sampleBuffer
+ fromConnection:self.captureConnectionMock];
+
+ [self.delegateMock verify];
+
+ [(id)currentDeviceMock stopMocking];
+ currentDeviceMock = nil;
+ [classMock stopMocking];
+ classMock = nil;
+ CFRelease(sampleBuffer);
+#endif
+}
+
@end
// TODO(kthelgason): Reenable these tests on simulator.
@@ -269,3 +397,43 @@ MAYBE_TEST(RTCCameraVideoCapturerTests, DelegateCallbackWithValidBufferAndOrient
[test testDelegateCallbackWithValidBufferAndOrientationUpdate];
[test tearDown];
}
+
+MAYBE_TEST(RTCCameraVideoCapturerTests, RotationCameraBackLandscapeLeft) {
+ RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init];
+ [test setup];
+ [test testRotationCamera:AVCaptureDevicePositionBack
+ withOrientation:UIDeviceOrientationLandscapeLeft];
+ [test tearDown];
+}
+
+MAYBE_TEST(RTCCameraVideoCapturerTests, RotationCameraFrontLandscapeLeft) {
+ RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init];
+ [test setup];
+ [test testRotationCamera:AVCaptureDevicePositionFront
+ withOrientation:UIDeviceOrientationLandscapeLeft];
+ [test tearDown];
+}
+
+MAYBE_TEST(RTCCameraVideoCapturerTests, RotationCameraBackLandscapeRight) {
+ RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init];
+ [test setup];
+ [test testRotationCamera:AVCaptureDevicePositionBack
+ withOrientation:UIDeviceOrientationLandscapeRight];
+ [test tearDown];
+}
+
+MAYBE_TEST(RTCCameraVideoCapturerTests, RotationCameraFrontLandscapeRight) {
+ RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init];
+ [test setup];
+ [test testRotationCamera:AVCaptureDevicePositionFront
+ withOrientation:UIDeviceOrientationLandscapeRight];
+ [test tearDown];
+}
+
+MAYBE_TEST(RTCCameraVideoCapturerTests, RotationCameraFrame) {
+ RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init];
+ [test setup];
+ [test testRotationFrame];
+ [test tearDown];
+}
+

Powered by Google App Engine
This is Rietveld 408576698