@@ -345,6 +345,7 @@ @interface FLTCam : NSObject <FlutterTexture,
345345
346346@implementation FLTCam {
347347 dispatch_queue_t _dispatchQueue;
348+ UIDeviceOrientation _deviceOrientation;
348349}
349350// Format used for video and image streaming.
350351FourCharCode videoFormat = kCVPixelFormatType_32BGRA ;
@@ -353,6 +354,7 @@ @implementation FLTCam {
353354- (instancetype )initWithCameraName : (NSString *)cameraName
354355 resolutionPreset : (NSString *)resolutionPreset
355356 enableAudio : (BOOL )enableAudio
357+ orientation : (UIDeviceOrientation)orientation
356358 dispatchQueue : (dispatch_queue_t )dispatchQueue
357359 error : (NSError **)error {
358360 self = [super init ];
@@ -370,6 +372,7 @@ - (instancetype)initWithCameraName:(NSString *)cameraName
370372 _exposureMode = ExposureModeAuto;
371373 _focusMode = FocusModeAuto;
372374 _lockedCaptureOrientation = UIDeviceOrientationUnknown;
375+ _deviceOrientation = orientation;
373376
374377 NSError *localError = nil ;
375378 _captureVideoInput = [AVCaptureDeviceInput deviceInputWithDevice: _captureDevice
@@ -389,10 +392,11 @@ - (instancetype)initWithCameraName:(NSString *)cameraName
389392 AVCaptureConnection *connection =
390393 [AVCaptureConnection connectionWithInputPorts: _captureVideoInput.ports
391394 output: _captureVideoOutput];
395+
392396 if ([_captureDevice position ] == AVCaptureDevicePositionFront) {
393397 connection.videoMirrored = YES ;
394398 }
395- connection. videoOrientation = AVCaptureVideoOrientationLandscapeRight;
399+
396400 [_captureSession addInputWithNoConnections: _captureVideoInput];
397401 [_captureSession addOutputWithNoConnections: _captureVideoOutput];
398402 [_captureSession addConnection: connection];
@@ -406,6 +410,8 @@ - (instancetype)initWithCameraName:(NSString *)cameraName
406410 [_motionManager startAccelerometerUpdates ];
407411
408412 [self setCaptureSessionPreset: _resolutionPreset];
413+ [self updateOrientation ];
414+
409415 return self;
410416}
411417
@@ -417,6 +423,40 @@ - (void)stop {
417423 [_captureSession stopRunning ];
418424}
419425
426+ - (void )setDeviceOrientation : (UIDeviceOrientation)orientation {
427+ if (_deviceOrientation == orientation) {
428+ return ;
429+ }
430+
431+ _deviceOrientation = orientation;
432+ [self updateOrientation ];
433+ }
434+
435+ - (void )updateOrientation {
436+ if (_isRecording) {
437+ return ;
438+ }
439+
440+ UIDeviceOrientation orientation = (_lockedCaptureOrientation != UIDeviceOrientationUnknown)
441+ ? _lockedCaptureOrientation
442+ : _deviceOrientation;
443+
444+ [self updateOrientation: orientation forCaptureOutput: _capturePhotoOutput];
445+ [self updateOrientation: orientation forCaptureOutput: _captureVideoOutput];
446+ }
447+
448+ - (void )updateOrientation : (UIDeviceOrientation)orientation
449+ forCaptureOutput : (AVCaptureOutput *)captureOutput {
450+ if (!captureOutput) {
451+ return ;
452+ }
453+
454+ AVCaptureConnection *connection = [captureOutput connectionWithMediaType: AVMediaTypeVideo];
455+ if (connection && connection.isVideoOrientationSupported ) {
456+ connection.videoOrientation = [self getVideoOrientationForDeviceOrientation: orientation];
457+ }
458+ }
459+
420460- (void )captureToFile : (FlutterResult)result API_AVAILABLE(ios(10 )) {
421461 AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettings ];
422462 if (_resolutionPreset == max) {
@@ -437,18 +477,6 @@ - (void)captureToFile:(FlutterResult)result API_AVAILABLE(ios(10)) {
437477 return ;
438478 }
439479
440- AVCaptureConnection *connection = [_capturePhotoOutput connectionWithMediaType: AVMediaTypeVideo];
441-
442- if (connection) {
443- if (_lockedCaptureOrientation != UIDeviceOrientationUnknown) {
444- connection.videoOrientation =
445- [self getVideoOrientationForDeviceOrientation: _lockedCaptureOrientation];
446- } else {
447- connection.videoOrientation =
448- [self getVideoOrientationForDeviceOrientation: [[UIDevice currentDevice ] orientation ]];
449- }
450- }
451-
452480 [_capturePhotoOutput capturePhotoWithSettings: settings
453481 delegate: [[FLTSavePhotoDelegate alloc ] initWithPath: path
454482 result: result]];
@@ -812,9 +840,11 @@ - (void)startVideoRecordingWithResult:(FlutterResult)result {
812840- (void )stopVideoRecordingWithResult : (FlutterResult)result {
813841 if (_isRecording) {
814842 _isRecording = NO ;
843+
815844 if (_videoWriter.status != AVAssetWriterStatusUnknown) {
816845 [_videoWriter finishWritingWithCompletionHandler: ^{
817846 if (self->_videoWriter .status == AVAssetWriterStatusCompleted) {
847+ [self updateOrientation ];
818848 result (self->_videoRecordingPath );
819849 self->_videoRecordingPath = nil ;
820850 } else {
@@ -854,12 +884,18 @@ - (void)lockCaptureOrientationWithResult:(FlutterResult)result
854884 result (getFlutterError (e));
855885 return ;
856886 }
857- _lockedCaptureOrientation = orientation;
887+
888+ if (_lockedCaptureOrientation != orientation) {
889+ _lockedCaptureOrientation = orientation;
890+ [self updateOrientation ];
891+ }
892+
858893 result (nil );
859894}
860895
861896- (void )unlockCaptureOrientationWithResult : (FlutterResult)result {
862897 _lockedCaptureOrientation = UIDeviceOrientationUnknown;
898+ [self updateOrientation ];
863899 result (nil );
864900}
865901
@@ -1101,6 +1137,7 @@ - (BOOL)setupWriterForPath:(NSString *)path {
11011137 if (_enableAudio && !_isAudioSetup) {
11021138 [self setUpCaptureSessionForAudio ];
11031139 }
1140+
11041141 _videoWriter = [[AVAssetWriter alloc ] initWithURL: outputURL
11051142 fileType: AVFileTypeMPEG4
11061143 error: &error];
@@ -1109,11 +1146,9 @@ - (BOOL)setupWriterForPath:(NSString *)path {
11091146 [_methodChannel invokeMethod: errorMethod arguments: error.description];
11101147 return NO ;
11111148 }
1112- NSDictionary *videoSettings = [NSDictionary
1113- dictionaryWithObjectsAndKeys: AVVideoCodecH264, AVVideoCodecKey,
1114- [NSNumber numberWithInt: _previewSize.width], AVVideoWidthKey,
1115- [NSNumber numberWithInt: _previewSize.height], AVVideoHeightKey,
1116- nil ];
1149+
1150+ NSDictionary *videoSettings = [_captureVideoOutput
1151+ recommendedVideoSettingsForAssetWriterWithOutputFileType: AVFileTypeMPEG4];
11171152 _videoWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType: AVMediaTypeVideo
11181153 outputSettings: videoSettings];
11191154
@@ -1124,14 +1159,7 @@ - (BOOL)setupWriterForPath:(NSString *)path {
11241159 }];
11251160
11261161 NSParameterAssert (_videoWriterInput);
1127- CGFloat rotationDegrees;
1128- if (_lockedCaptureOrientation != UIDeviceOrientationUnknown) {
1129- rotationDegrees = [self getRotationFromDeviceOrientation: _lockedCaptureOrientation];
1130- } else {
1131- rotationDegrees = [self getRotationFromDeviceOrientation: [UIDevice currentDevice ].orientation];
1132- }
11331162
1134- _videoWriterInput.transform = CGAffineTransformMakeRotation (rotationDegrees * M_PI / 180 );
11351163 _videoWriterInput.expectsMediaDataInRealTime = YES ;
11361164
11371165 // Add the audio input
@@ -1194,21 +1222,6 @@ - (void)setUpCaptureSessionForAudio {
11941222 }
11951223 }
11961224}
1197-
1198- - (int )getRotationFromDeviceOrientation : (UIDeviceOrientation)orientation {
1199- switch (orientation) {
1200- case UIDeviceOrientationPortraitUpsideDown:
1201- return 270 ;
1202- case UIDeviceOrientationLandscapeRight:
1203- return 180 ;
1204- case UIDeviceOrientationLandscapeLeft:
1205- return 0 ;
1206- case UIDeviceOrientationPortrait:
1207- default :
1208- return 90 ;
1209- };
1210- }
1211-
12121225@end
12131226
12141227@interface CameraPlugin ()
@@ -1257,7 +1270,13 @@ - (void)startOrientationListener {
12571270
12581271- (void )orientationChanged : (NSNotification *)note {
12591272 UIDevice *device = note.object ;
1260- [self sendDeviceOrientation: device.orientation];
1273+ UIDeviceOrientation orientation = device.orientation ;
1274+
1275+ if (_camera) {
1276+ [_camera setDeviceOrientation: orientation];
1277+ }
1278+
1279+ [self sendDeviceOrientation: orientation];
12611280}
12621281
12631282- (void )sendDeviceOrientation : (UIDeviceOrientation)orientation {
@@ -1318,6 +1337,7 @@ - (void)handleMethodCallAsync:(FlutterMethodCall *)call result:(FlutterResult)re
13181337 FLTCam *cam = [[FLTCam alloc ] initWithCameraName: cameraName
13191338 resolutionPreset: resolutionPreset
13201339 enableAudio: [enableAudio boolValue ]
1340+ orientation: [[UIDevice currentDevice ] orientation ]
13211341 dispatchQueue: _dispatchQueue
13221342 error: &error];
13231343
0 commit comments