From 0417103a7dda753735278cafee72331f8f5f8bfc Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Mon, 22 Feb 2021 16:48:24 +0100 Subject: [PATCH 1/7] Fix iOS rotation issue --- packages/camera/camera/CHANGELOG.md | 4 ++++ .../camera/camera/ios/Classes/CameraPlugin.m | 2 +- .../camera/camera/lib/src/camera_preview.dart | 18 ++++++++---------- packages/camera/camera/pubspec.yaml | 2 +- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index 29774748a32b..3e3f1807dacf 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.8.0-nullsafety.3 + +* Solved a rotation issue on iOS which caused the default preview to be displayed as landscape right instead of portrait. + ## 0.8.0-nullsafety.2 * Solved delay when using the zoom feature on iOS. diff --git a/packages/camera/camera/ios/Classes/CameraPlugin.m b/packages/camera/camera/ios/Classes/CameraPlugin.m index c1770ff6d40b..514c8bcb448a 100644 --- a/packages/camera/camera/ios/Classes/CameraPlugin.m +++ b/packages/camera/camera/ios/Classes/CameraPlugin.m @@ -392,7 +392,7 @@ - (instancetype)initWithCameraName:(NSString *)cameraName if ([_captureDevice position] == AVCaptureDevicePositionFront) { connection.videoMirrored = YES; } - connection.videoOrientation = AVCaptureVideoOrientationLandscapeRight; + connection.videoOrientation = AVCaptureVideoOrientationPortrait; [_captureSession addInputWithNoConnections:_captureVideoInput]; [_captureSession addOutputWithNoConnections:_captureVideoOutput]; [_captureSession addConnection:connection]; diff --git a/packages/camera/camera/lib/src/camera_preview.dart b/packages/camera/camera/lib/src/camera_preview.dart index f6d357b41b77..ba7cb39f6477 100644 --- a/packages/camera/camera/lib/src/camera_preview.dart +++ b/packages/camera/camera/lib/src/camera_preview.dart @@ -4,7 +4,6 @@ import 'package:camera/camera.dart'; import 'package:camera_platform_interface/camera_platform_interface.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -41,26 +40,25 @@ class CameraPreview extends StatelessWidget { : Container(); } - DeviceOrientation _getApplicableOrientation() { - return controller.value.isRecordingVideo - ? controller.value.recordingOrientation! - : (controller.value.lockedCaptureOrientation ?? - controller.value.deviceOrientation); - } - bool _isLandscape() { return [DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight] .contains(_getApplicableOrientation()); } int _getQuarterTurns() { - int platformOffset = defaultTargetPlatform == TargetPlatform.iOS ? 1 : 0; Map turns = { DeviceOrientation.portraitUp: 0, DeviceOrientation.landscapeLeft: 1, DeviceOrientation.portraitDown: 2, DeviceOrientation.landscapeRight: 3, }; - return turns[_getApplicableOrientation()]! + platformOffset; + return turns[_getApplicableOrientation()]!; + } + + DeviceOrientation _getApplicableOrientation() { + return controller.value.isRecordingVideo + ? controller.value.recordingOrientation! + : (controller.value.lockedCaptureOrientation ?? + controller.value.deviceOrientation); } } diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml index 4b820b8b64cf..2d620505def2 100644 --- a/packages/camera/camera/pubspec.yaml +++ b/packages/camera/camera/pubspec.yaml @@ -2,7 +2,7 @@ name: camera description: A Flutter plugin for getting information about and controlling the camera on Android and iOS. Supports previewing the camera feed, capturing images, capturing video, and streaming image buffers to dart. -version: 0.8.0-nullsafety.2 +version: 0.8.0-nullsafety.3 homepage: https://github.com/flutter/plugins/tree/master/packages/camera/camera dependencies: From c2489490065dddc6a464d15dd49873dd90be0812 Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Fri, 26 Feb 2021 15:08:07 +0100 Subject: [PATCH 2/7] Fix orientation issues on iOS --- .../camera/camera/ios/Classes/CameraPlugin.m | 104 +++++++++++------- .../camera/camera/lib/src/camera_preview.dart | 10 +- 2 files changed, 67 insertions(+), 47 deletions(-) diff --git a/packages/camera/camera/ios/Classes/CameraPlugin.m b/packages/camera/camera/ios/Classes/CameraPlugin.m index 514c8bcb448a..9fb72571fb6c 100644 --- a/packages/camera/camera/ios/Classes/CameraPlugin.m +++ b/packages/camera/camera/ios/Classes/CameraPlugin.m @@ -345,6 +345,7 @@ @interface FLTCam : NSObject _videoWriter.status == AVAssetWriterStatusCompleted) { + [self updateOrientation]; result(self->_videoRecordingPath); self->_videoRecordingPath = nil; } else { @@ -854,12 +885,18 @@ - (void)lockCaptureOrientationWithResult:(FlutterResult)result result(getFlutterError(e)); return; } - _lockedCaptureOrientation = orientation; + + if (_lockedCaptureOrientation != orientation) { + _lockedCaptureOrientation = orientation; + [self updateOrientation]; + } + result(nil); } - (void)unlockCaptureOrientationWithResult:(FlutterResult)result { _lockedCaptureOrientation = UIDeviceOrientationUnknown; + [self updateOrientation]; result(nil); } @@ -1101,6 +1138,7 @@ - (BOOL)setupWriterForPath:(NSString *)path { if (_enableAudio && !_isAudioSetup) { [self setUpCaptureSessionForAudio]; } + _videoWriter = [[AVAssetWriter alloc] initWithURL:outputURL fileType:AVFileTypeMPEG4 error:&error]; @@ -1109,11 +1147,8 @@ - (BOOL)setupWriterForPath:(NSString *)path { [_methodChannel invokeMethod:errorMethod arguments:error.description]; return NO; } - NSDictionary *videoSettings = [NSDictionary - dictionaryWithObjectsAndKeys:AVVideoCodecH264, AVVideoCodecKey, - [NSNumber numberWithInt:_previewSize.width], AVVideoWidthKey, - [NSNumber numberWithInt:_previewSize.height], AVVideoHeightKey, - nil]; + + NSDictionary *videoSettings = [_captureVideoOutput recommendedVideoSettingsForAssetWriterWithOutputFileType:AVFileTypeMPEG4]; _videoWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings]; @@ -1124,14 +1159,7 @@ - (BOOL)setupWriterForPath:(NSString *)path { }]; NSParameterAssert(_videoWriterInput); - CGFloat rotationDegrees; - if (_lockedCaptureOrientation != UIDeviceOrientationUnknown) { - rotationDegrees = [self getRotationFromDeviceOrientation:_lockedCaptureOrientation]; - } else { - rotationDegrees = [self getRotationFromDeviceOrientation:[UIDevice currentDevice].orientation]; - } - _videoWriterInput.transform = CGAffineTransformMakeRotation(rotationDegrees * M_PI / 180); _videoWriterInput.expectsMediaDataInRealTime = YES; // Add the audio input @@ -1194,21 +1222,6 @@ - (void)setUpCaptureSessionForAudio { } } } - -- (int)getRotationFromDeviceOrientation:(UIDeviceOrientation)orientation { - switch (orientation) { - case UIDeviceOrientationPortraitUpsideDown: - return 270; - case UIDeviceOrientationLandscapeRight: - return 180; - case UIDeviceOrientationLandscapeLeft: - return 0; - case UIDeviceOrientationPortrait: - default: - return 90; - }; -} - @end @interface CameraPlugin () @@ -1257,7 +1270,13 @@ - (void)startOrientationListener { - (void)orientationChanged:(NSNotification *)note { UIDevice *device = note.object; - [self sendDeviceOrientation:device.orientation]; + UIDeviceOrientation orientation = device.orientation; + + if (_camera) { + [_camera setDeviceOrientation:orientation]; + } + + [self sendDeviceOrientation:orientation]; } - (void)sendDeviceOrientation:(UIDeviceOrientation)orientation { @@ -1318,6 +1337,7 @@ - (void)handleMethodCallAsync:(FlutterMethodCall *)call result:(FlutterResult)re FLTCam *cam = [[FLTCam alloc] initWithCameraName:cameraName resolutionPreset:resolutionPreset enableAudio:[enableAudio boolValue] + orientation: [[UIDevice currentDevice] orientation] dispatchQueue:_dispatchQueue error:&error]; diff --git a/packages/camera/camera/lib/src/camera_preview.dart b/packages/camera/camera/lib/src/camera_preview.dart index ba7cb39f6477..0363cbf9eb0c 100644 --- a/packages/camera/camera/lib/src/camera_preview.dart +++ b/packages/camera/camera/lib/src/camera_preview.dart @@ -28,11 +28,11 @@ class CameraPreview extends StatelessWidget { child: Stack( fit: StackFit.expand, children: [ - RotatedBox( - quarterTurns: _getQuarterTurns(), - child: - CameraPlatform.instance.buildPreview(controller.cameraId), - ), + //RotatedBox( + // quarterTurns: _getQuarterTurns(), + // child: + CameraPlatform.instance.buildPreview(controller.cameraId), + //), child ?? Container(), ], ), From 73fe7f7041e2ff3624f74170514aab2b4468776d Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Tue, 16 Mar 2021 12:30:01 +0100 Subject: [PATCH 3/7] Merged with master and added test --- .../camera/test/camera_preview_test.dart | 202 ++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100644 packages/camera/camera/test/camera_preview_test.dart diff --git a/packages/camera/camera/test/camera_preview_test.dart b/packages/camera/camera/test/camera_preview_test.dart new file mode 100644 index 000000000000..460374722d4f --- /dev/null +++ b/packages/camera/camera/test/camera_preview_test.dart @@ -0,0 +1,202 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:camera/camera.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:quiver/core.dart'; + +class FakeController extends ValueNotifier + implements CameraController { + FakeController() : super(const CameraValue.uninitialized()); + + @override + Future dispose() async { + super.dispose(); + } + + @override + Widget buildPreview() { + return Texture(textureId: CameraController.kUninitializedCameraId); + } + + @override + int get cameraId => CameraController.kUninitializedCameraId; + + @override + void debugCheckIsDisposed() {} + + @override + CameraDescription get description => CameraDescription( + name: '', lensDirection: CameraLensDirection.back, sensorOrientation: 0); + + @override + bool get enableAudio => false; + + @override + Future getExposureOffsetStepSize() async => 1.0; + + @override + Future getMaxExposureOffset() async => 1.0; + + @override + Future getMaxZoomLevel() async => 1.0; + + @override + Future getMinExposureOffset() async => 1.0; + + @override + Future getMinZoomLevel() async => 1.0; + + @override + ImageFormatGroup? get imageFormatGroup => null; + + @override + Future initialize() async {} + + @override + Future lockCaptureOrientation([DeviceOrientation? orientation]) async {} + + @override + Future pauseVideoRecording() async {} + + @override + Future prepareForVideoRecording() async {} + + @override + ResolutionPreset get resolutionPreset => ResolutionPreset.low; + + @override + Future resumeVideoRecording() async {} + + @override + Future setExposureMode(ExposureMode mode) async {} + + @override + Future setExposureOffset(double offset) async => offset; + + @override + Future setExposurePoint(Offset? point) async {} + + @override + Future setFlashMode(FlashMode mode) async {} + + @override + Future setFocusMode(FocusMode mode) async {} + + @override + Future setFocusPoint(Offset? point) async {} + + @override + Future setZoomLevel(double zoom) async {} + + @override + Future startImageStream(onAvailable) async {} + + @override + Future startVideoRecording() async {} + + @override + Future stopImageStream() async {} + + @override + Future stopVideoRecording() async => XFile(''); + + @override + Future takePicture() async => XFile(''); + + @override + Future unlockCaptureOrientation() async {} +} + +void main() { + testWidgets( + 'when recording rotatedBox should turn according to recording orientation', + ( + WidgetTester tester, + ) async { + final FakeController controller = FakeController(); + controller.value = controller.value.copyWith( + isInitialized: true, + isRecordingVideo: true, + deviceOrientation: DeviceOrientation.portraitUp, + lockedCaptureOrientation: + Optional.fromNullable(DeviceOrientation.landscapeRight), + recordingOrientation: + Optional.fromNullable(DeviceOrientation.landscapeLeft), + previewSize: Size(480, 640), + ); + + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: CameraPreview(controller), + ), + ); + expect(find.byType(RotatedBox), findsOneWidget); + + RotatedBox rotatedBox = tester.widget(find.byType(RotatedBox)); + expect(rotatedBox.quarterTurns, 1); + }); + + testWidgets( + 'when orientation locked rotatedBox should turn according to locked orientation', + ( + WidgetTester tester, + ) async { + final FakeController controller = FakeController(); + controller.value = controller.value.copyWith( + isInitialized: true, + deviceOrientation: DeviceOrientation.portraitUp, + lockedCaptureOrientation: + Optional.fromNullable(DeviceOrientation.landscapeRight), + recordingOrientation: + Optional.fromNullable(DeviceOrientation.landscapeLeft), + previewSize: Size(480, 640), + ); + + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: CameraPreview(controller), + ), + ); + expect(find.byType(RotatedBox), findsOneWidget); + + RotatedBox rotatedBox = tester.widget(find.byType(RotatedBox)); + expect(rotatedBox.quarterTurns, 3); + }); + + testWidgets( + 'when not locked and not recording rotatedBox should turn according to device orientation', + ( + WidgetTester tester, + ) async { + final FakeController controller = FakeController(); + controller.value = controller.value.copyWith( + isInitialized: true, + deviceOrientation: DeviceOrientation.portraitUp, + lockedCaptureOrientation: null, + recordingOrientation: + Optional.fromNullable(DeviceOrientation.landscapeLeft), + previewSize: Size(480, 640), + ); + + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: CameraPreview(controller), + ), + ); + expect(find.byType(RotatedBox), findsOneWidget); + + RotatedBox rotatedBox = tester.widget(find.byType(RotatedBox)); + expect(rotatedBox.quarterTurns, 0); + }); +} From fea49f8a95e41de52086bcd7286affa82a5608dd Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Tue, 16 Mar 2021 13:00:18 +0100 Subject: [PATCH 4/7] Test RotationBox turns according to device orientation --- .../camera/test/camera_preview_test.dart | 207 ++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 packages/camera/camera/test/camera_preview_test.dart diff --git a/packages/camera/camera/test/camera_preview_test.dart b/packages/camera/camera/test/camera_preview_test.dart new file mode 100644 index 000000000000..8d0e97e9fc21 --- /dev/null +++ b/packages/camera/camera/test/camera_preview_test.dart @@ -0,0 +1,207 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'dart:async'; + +import 'package:camera/camera.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:quiver/core.dart'; + +class FakeController extends ValueNotifier + implements CameraController { + FakeController() : super(const CameraValue.uninitialized()); + + @override + Future dispose() async { + super.dispose(); + } + + @override + Widget buildPreview() { + return Texture(textureId: CameraController.kUninitializedCameraId); + } + + @override + int get cameraId => CameraController.kUninitializedCameraId; + + @override + void debugCheckIsDisposed() {} + + @override + CameraDescription get description => CameraDescription( + name: '', lensDirection: CameraLensDirection.back, sensorOrientation: 0); + + @override + bool get enableAudio => false; + + @override + Future getExposureOffsetStepSize() async => 1.0; + + @override + Future getMaxExposureOffset() async => 1.0; + + @override + Future getMaxZoomLevel() async => 1.0; + + @override + Future getMinExposureOffset() async => 1.0; + + @override + Future getMinZoomLevel() async => 1.0; + + @override + ImageFormatGroup? get imageFormatGroup => null; + + @override + Future initialize() async {} + + @override + Future lockCaptureOrientation([DeviceOrientation? orientation]) async {} + + @override + Future pauseVideoRecording() async {} + + @override + Future prepareForVideoRecording() async {} + + @override + ResolutionPreset get resolutionPreset => ResolutionPreset.low; + + @override + Future resumeVideoRecording() async {} + + @override + Future setExposureMode(ExposureMode mode) async {} + + @override + Future setExposureOffset(double offset) async => offset; + + @override + Future setExposurePoint(Offset? point) async {} + + @override + Future setFlashMode(FlashMode mode) async {} + + @override + Future setFocusMode(FocusMode mode) async {} + + @override + Future setFocusPoint(Offset? point) async {} + + @override + Future setZoomLevel(double zoom) async {} + + @override + Future startImageStream(onAvailable) async {} + + @override + Future startVideoRecording() async {} + + @override + Future stopImageStream() async {} + + @override + Future stopVideoRecording() async => XFile(''); + + @override + Future takePicture() async => XFile(''); + + @override + Future unlockCaptureOrientation() async {} +} + +void main() { + group('rotated box', () { + testWidgets( + 'when recording rotatedBox should turn according to recording orientation', + ( + WidgetTester tester, + ) async { + final FakeController controller = FakeController(); + controller.value = controller.value.copyWith( + isInitialized: true, + isRecordingVideo: true, + deviceOrientation: DeviceOrientation.portraitUp, + lockedCaptureOrientation: + Optional.fromNullable(DeviceOrientation.landscapeRight), + recordingOrientation: + Optional.fromNullable(DeviceOrientation.landscapeLeft), + previewSize: Size(480, 640), + ); + + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: CameraPreview(controller), + ), + ); + expect(find.byType(RotatedBox), findsOneWidget); + + RotatedBox rotatedBox = + tester.widget(find.byType(RotatedBox)); + expect(rotatedBox.quarterTurns, 1); + }); + + testWidgets( + 'when orientation locked rotatedBox should turn according to locked orientation', + ( + WidgetTester tester, + ) async { + final FakeController controller = FakeController(); + controller.value = controller.value.copyWith( + isInitialized: true, + deviceOrientation: DeviceOrientation.portraitUp, + lockedCaptureOrientation: + Optional.fromNullable(DeviceOrientation.landscapeRight), + recordingOrientation: + Optional.fromNullable(DeviceOrientation.landscapeLeft), + previewSize: Size(480, 640), + ); + + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: CameraPreview(controller), + ), + ); + expect(find.byType(RotatedBox), findsOneWidget); + + RotatedBox rotatedBox = + tester.widget(find.byType(RotatedBox)); + expect(rotatedBox.quarterTurns, 3); + }); + + testWidgets( + 'when not locked and not recording rotatedBox should turn according to device orientation', + ( + WidgetTester tester, + ) async { + final FakeController controller = FakeController(); + controller.value = controller.value.copyWith( + isInitialized: true, + deviceOrientation: DeviceOrientation.portraitUp, + lockedCaptureOrientation: null, + recordingOrientation: + Optional.fromNullable(DeviceOrientation.landscapeLeft), + previewSize: Size(480, 640), + ); + + await tester.pumpWidget( + Directionality( + textDirection: TextDirection.ltr, + child: CameraPreview(controller), + ), + ); + expect(find.byType(RotatedBox), findsOneWidget); + + RotatedBox rotatedBox = + tester.widget(find.byType(RotatedBox)); + expect(rotatedBox.quarterTurns, 0); + }); + }); +} From b174c60dc737e87a0d1299486bab1fcc959a8749 Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Tue, 16 Mar 2021 14:50:12 +0100 Subject: [PATCH 5/7] Fix formatting --- .../camera/camera/ios/Classes/CameraPlugin.m | 94 +++++++++---------- .../camera/camera/lib/src/camera_preview.dart | 1 - 2 files changed, 47 insertions(+), 48 deletions(-) diff --git a/packages/camera/camera/ios/Classes/CameraPlugin.m b/packages/camera/camera/ios/Classes/CameraPlugin.m index 9fb72571fb6c..6199f52588e3 100644 --- a/packages/camera/camera/ios/Classes/CameraPlugin.m +++ b/packages/camera/camera/ios/Classes/CameraPlugin.m @@ -392,11 +392,11 @@ - (instancetype)initWithCameraName:(NSString *)cameraName AVCaptureConnection *connection = [AVCaptureConnection connectionWithInputPorts:_captureVideoInput.ports output:_captureVideoOutput]; - + if ([_captureDevice position] == AVCaptureDevicePositionFront) { connection.videoMirrored = YES; } - + [_captureSession addInputWithNoConnections:_captureVideoInput]; [_captureSession addOutputWithNoConnections:_captureVideoOutput]; [_captureSession addConnection:connection]; @@ -411,7 +411,7 @@ - (instancetype)initWithCameraName:(NSString *)cameraName [self setCaptureSessionPreset:_resolutionPreset]; [self updateOrientation]; - + return self; } @@ -424,39 +424,38 @@ - (void)stop { } - (void)setDeviceOrientation:(UIDeviceOrientation)orientation { - if (_deviceOrientation == orientation) { - return; - } - - _deviceOrientation = orientation; - [self updateOrientation]; + if (_deviceOrientation == orientation) { + return; + } + + _deviceOrientation = orientation; + [self updateOrientation]; } - (void)updateOrientation { - if (_isRecording) { - return; - } - - UIDeviceOrientation orientation = (_lockedCaptureOrientation != UIDeviceOrientationUnknown) - ? _lockedCaptureOrientation - : _deviceOrientation; - - [self updateOrientation:orientation forCaptureOutput:_capturePhotoOutput]; - [self updateOrientation:orientation forCaptureOutput:_captureVideoOutput]; -} - -- (void)updateOrientation:(UIDeviceOrientation) orientation - forCaptureOutput:(AVCaptureOutput*) captureOutput { - if (!captureOutput) { - return; - } - - AVCaptureConnection *connection = [captureOutput connectionWithMediaType:AVMediaTypeVideo]; - if(connection && connection.isVideoOrientationSupported) { - connection.videoOrientation = [self getVideoOrientationForDeviceOrientation:orientation]; - } + if (_isRecording) { + return; + } + + UIDeviceOrientation orientation = (_lockedCaptureOrientation != UIDeviceOrientationUnknown) + ? _lockedCaptureOrientation + : _deviceOrientation; + + [self updateOrientation:orientation forCaptureOutput:_capturePhotoOutput]; + [self updateOrientation:orientation forCaptureOutput:_captureVideoOutput]; } +- (void)updateOrientation:(UIDeviceOrientation)orientation + forCaptureOutput:(AVCaptureOutput *)captureOutput { + if (!captureOutput) { + return; + } + + AVCaptureConnection *connection = [captureOutput connectionWithMediaType:AVMediaTypeVideo]; + if (connection && connection.isVideoOrientationSupported) { + connection.videoOrientation = [self getVideoOrientationForDeviceOrientation:orientation]; + } +} - (void)captureToFile:(FlutterResult)result API_AVAILABLE(ios(10)) { AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettings]; @@ -841,7 +840,7 @@ - (void)startVideoRecordingWithResult:(FlutterResult)result { - (void)stopVideoRecordingWithResult:(FlutterResult)result { if (_isRecording) { _isRecording = NO; - + if (_videoWriter.status != AVAssetWriterStatusUnknown) { [_videoWriter finishWritingWithCompletionHandler:^{ if (self->_videoWriter.status == AVAssetWriterStatusCompleted) { @@ -885,12 +884,12 @@ - (void)lockCaptureOrientationWithResult:(FlutterResult)result result(getFlutterError(e)); return; } - - if (_lockedCaptureOrientation != orientation) { - _lockedCaptureOrientation = orientation; - [self updateOrientation]; - } - + + if (_lockedCaptureOrientation != orientation) { + _lockedCaptureOrientation = orientation; + [self updateOrientation]; + } + result(nil); } @@ -1138,7 +1137,7 @@ - (BOOL)setupWriterForPath:(NSString *)path { if (_enableAudio && !_isAudioSetup) { [self setUpCaptureSessionForAudio]; } - + _videoWriter = [[AVAssetWriter alloc] initWithURL:outputURL fileType:AVFileTypeMPEG4 error:&error]; @@ -1147,8 +1146,9 @@ - (BOOL)setupWriterForPath:(NSString *)path { [_methodChannel invokeMethod:errorMethod arguments:error.description]; return NO; } - - NSDictionary *videoSettings = [_captureVideoOutput recommendedVideoSettingsForAssetWriterWithOutputFileType:AVFileTypeMPEG4]; + + NSDictionary *videoSettings = [_captureVideoOutput + recommendedVideoSettingsForAssetWriterWithOutputFileType:AVFileTypeMPEG4]; _videoWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:videoSettings]; @@ -1271,11 +1271,11 @@ - (void)startOrientationListener { - (void)orientationChanged:(NSNotification *)note { UIDevice *device = note.object; UIDeviceOrientation orientation = device.orientation; - - if (_camera) { - [_camera setDeviceOrientation:orientation]; - } - + + if (_camera) { + [_camera setDeviceOrientation:orientation]; + } + [self sendDeviceOrientation:orientation]; } @@ -1337,7 +1337,7 @@ - (void)handleMethodCallAsync:(FlutterMethodCall *)call result:(FlutterResult)re FLTCam *cam = [[FLTCam alloc] initWithCameraName:cameraName resolutionPreset:resolutionPreset enableAudio:[enableAudio boolValue] - orientation: [[UIDevice currentDevice] orientation] + orientation:[[UIDevice currentDevice] orientation] dispatchQueue:_dispatchQueue error:&error]; diff --git a/packages/camera/camera/lib/src/camera_preview.dart b/packages/camera/camera/lib/src/camera_preview.dart index a1c6da74bdde..689a1d9df814 100644 --- a/packages/camera/camera/lib/src/camera_preview.dart +++ b/packages/camera/camera/lib/src/camera_preview.dart @@ -3,7 +3,6 @@ // found in the LICENSE file. import 'package:camera/camera.dart'; -import 'package:camera_platform_interface/camera_platform_interface.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; From ed367fea62a76b53c223ba6c7aecb761ec6f059e Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Fri, 19 Mar 2021 09:17:09 +0100 Subject: [PATCH 6/7] Removed merge conflict tags from CHANGELOG --- packages/camera/camera/CHANGELOG.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index 2f2be7f7fcca..eb88683bee8f 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -3,12 +3,6 @@ * Solved a rotation issue on iOS which caused the default preview to be displayed as landscape right instead of portrait. ## 0.8.0 -<<<<<<< HEAD - -||||||| merged common ancestors ->>>>>>>>> Temporary merge branch 2 -======= ->>>>>>> ios_orientation_issue * Stable null safety release. * Solved delay when using the zoom feature on iOS. From 2b2f0990fd15e43ef539522160b9b6e40b26a128 Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Wed, 24 Mar 2021 08:40:55 +0100 Subject: [PATCH 7/7] Fix license header in test --- packages/camera/camera/test/camera_preview_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera/test/camera_preview_test.dart b/packages/camera/camera/test/camera_preview_test.dart index 8e0787196594..d579341c0e58 100644 --- a/packages/camera/camera/test/camera_preview_test.dart +++ b/packages/camera/camera/test/camera_preview_test.dart @@ -1,4 +1,4 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. +// Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file.