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

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

Issue 2964703002: [iOS] Fix incorrectly oriented frames when rapidly switching between cameras. (Closed)
Patch Set: Refactored checking of image's source device. 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..fc5dfe36392649d06571d659fa59821405985f70 100644
--- a/webrtc/sdk/objc/Framework/UnitTests/RTCCameraVideoCapturerTests.mm
+++ b/webrtc/sdk/objc/Framework/UnitTests/RTCCameraVideoCapturerTests.mm
@@ -19,6 +19,7 @@
#import <WebRTC/RTCCameraVideoCapturer.h>
#import <WebRTC/RTCDispatcher.h>
#import <WebRTC/RTCVideoFrame.h>
+#import "AVCaptureSession+Device.h"
#if TARGET_OS_IPHONE
// Helper method.
@@ -218,6 +219,136 @@ 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)setExif:(CMSampleBufferRef)sampleBuffer {
+ 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);
+}
+
+- (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);
+
+ [self setExif:sampleBuffer];
+
+ [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)testImageExif {
+#if TARGET_OS_IPHONE
+ CMSampleBufferRef sampleBuffer = createTestSampleBufferRef();
+ [self setExif:sampleBuffer];
+
+ AVCaptureDevicePosition cameraPosition = [AVCaptureSession
+ devicePositionForSampleBuffer:sampleBuffer];
+ EXPECT_EQ(cameraPosition, AVCaptureDevicePositionBack);
+#endif
+}
+
@end
// TODO(kthelgason): Reenable these tests on simulator.
@@ -269,3 +400,49 @@ 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];
+}
+
+MAYBE_TEST(RTCCameraVideoCapturerTests, ImageExif) {
+ RTCCameraVideoCapturerTests *test = [[RTCCameraVideoCapturerTests alloc] init];
+ [test setup];
+ [test testImageExif];
+ [test tearDown];
+}

Powered by Google App Engine
This is Rietveld 408576698