Skip to content

Commit 06c1fa4

Browse files
[camera_avfoundation] Set highest available resolution for ResolutionPreset.Max (#5245)
The current implementation of the camera plugin for iOS iterates though all other resolution presets when set to FLTResolutionPresetMax. This results in a resolution of 3840x2160 at most, while native camera is able to produce 4032x3024 This change should partially address these issues at least. - flutter/flutter#58163 - flutter/flutter#78247 - flutter/flutter#45906 P.S. I'm not really sure about tests - it seems that resolution presets are not covered by any. Any feedback is appreciated!
1 parent a9c68b8 commit 06c1fa4

File tree

9 files changed

+244
-6
lines changed

9 files changed

+244
-6
lines changed

packages/camera/camera_avfoundation/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.9.14+1
2+
3+
* Fixes bug where max resolution preset does not produce highest available resolution on iOS.
4+
15
## 0.9.14
26

37
* Adds support to HEIF format.

packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
2323
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
2424
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
25+
CEF6611A2B5E36A500D33FD4 /* CameraSessionPresetsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CEF661192B5E36A500D33FD4 /* CameraSessionPresetsTests.m */; };
2526
E01EE4A82799F3A5008C1950 /* QueueUtilsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E01EE4A72799F3A5008C1950 /* QueueUtilsTests.m */; };
2627
E032F250279F5E94009E9028 /* CameraCaptureSessionQueueRaceConditionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E032F24F279F5E94009E9028 /* CameraCaptureSessionQueueRaceConditionTests.m */; };
2728
E04F108627A87CA600573D0C /* FLTSavePhotoDelegateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E04F108527A87CA600573D0C /* FLTSavePhotoDelegateTests.m */; };
@@ -89,6 +90,7 @@
8990
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
9091
9C5CC6CAD53AD388B2694F3A /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
9192
A24F9E418BA48BCC7409B117 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
93+
CEF661192B5E36A500D33FD4 /* CameraSessionPresetsTests.m */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = CameraSessionPresetsTests.m; sourceTree = "<group>"; };
9294
E01EE4A72799F3A5008C1950 /* QueueUtilsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QueueUtilsTests.m; sourceTree = "<group>"; };
9395
E032F24F279F5E94009E9028 /* CameraCaptureSessionQueueRaceConditionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CameraCaptureSessionQueueRaceConditionTests.m; sourceTree = "<group>"; };
9496
E04F108527A87CA600573D0C /* FLTSavePhotoDelegateTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLTSavePhotoDelegateTests.m; sourceTree = "<group>"; };
@@ -151,6 +153,7 @@
151153
E0F95E3C27A32AB900699390 /* CameraPropertiesTests.m */,
152154
788A065927B0E02900533D74 /* StreamingTest.m */,
153155
43ED1536282570DE00EB00DE /* AvailableCamerasTest.m */,
156+
CEF661192B5E36A500D33FD4 /* CameraSessionPresetsTests.m */,
154157
);
155158
path = RunnerTests;
156159
sourceTree = "<group>";
@@ -451,6 +454,7 @@
451454
F6EE622F2710A6FC00905E4A /* MockFLTThreadSafeFlutterResult.m in Sources */,
452455
E0CDBAC227CD9729002561D9 /* CameraTestUtils.m in Sources */,
453456
334733EA2668111C00DCC49E /* CameraOrientationTests.m in Sources */,
457+
CEF6611A2B5E36A500D33FD4 /* CameraSessionPresetsTests.m in Sources */,
454458
E032F250279F5E94009E9028 /* CameraCaptureSessionQueueRaceConditionTests.m in Sources */,
455459
788A065A27B0E02900533D74 /* StreamingTest.m in Sources */,
456460
E0C6E2022770F01A00EA6AA3 /* ThreadSafeEventChannelTests.m in Sources */,
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
@import camera_avfoundation;
6+
@import camera_avfoundation.Test;
7+
8+
@import AVFoundation;
9+
@import XCTest;
10+
#import <OCMock/OCMock.h>
11+
#import "CameraTestUtils.h"
12+
13+
/// Includes test cases related to resolution presets setting operations for FLTCam class.
14+
@interface FLTCamSessionPresetsTest : XCTestCase
15+
@end
16+
17+
@implementation FLTCamSessionPresetsTest
18+
19+
- (void)testResolutionPresetWithBestFormat_mustUpdateCaptureSessionPreset {
20+
NSString *expectedPreset = AVCaptureSessionPresetInputPriority;
21+
22+
id videoSessionMock = OCMClassMock([AVCaptureSession class]);
23+
OCMStub([videoSessionMock addInputWithNoConnections:[OCMArg any]]);
24+
25+
id captureFormatMock = OCMClassMock([AVCaptureDeviceFormat class]);
26+
id captureDeviceMock = OCMClassMock([AVCaptureDevice class]);
27+
OCMStub([captureDeviceMock formats]).andReturn(@[ captureFormatMock ]);
28+
29+
OCMExpect([captureDeviceMock activeFormat]).andReturn(captureFormatMock);
30+
OCMExpect([captureDeviceMock lockForConfiguration:NULL]).andReturn(YES);
31+
OCMExpect([videoSessionMock setSessionPreset:expectedPreset]);
32+
33+
FLTCreateCamWithVideoDimensionsForFormat(videoSessionMock, @"max", captureDeviceMock,
34+
^CMVideoDimensions(AVCaptureDeviceFormat *format) {
35+
CMVideoDimensions videoDimensions;
36+
videoDimensions.width = 1;
37+
videoDimensions.height = 1;
38+
return videoDimensions;
39+
});
40+
41+
OCMVerifyAll(captureDeviceMock);
42+
OCMVerifyAll(videoSessionMock);
43+
}
44+
45+
- (void)testResolutionPresetWithCanSetSessionPresetMax_mustUpdateCaptureSessionPreset {
46+
NSString *expectedPreset = AVCaptureSessionPreset3840x2160;
47+
48+
id videoSessionMock = OCMClassMock([AVCaptureSession class]);
49+
OCMStub([videoSessionMock addInputWithNoConnections:[OCMArg any]]);
50+
51+
// Make sure that setting resolution preset for session always succeeds.
52+
OCMStub([videoSessionMock canSetSessionPreset:[OCMArg any]]).andReturn(YES);
53+
54+
OCMExpect([videoSessionMock setSessionPreset:expectedPreset]);
55+
56+
FLTCreateCamWithVideoCaptureSession(videoSessionMock, @"max");
57+
58+
OCMVerifyAll(videoSessionMock);
59+
}
60+
61+
- (void)testResolutionPresetWithCanSetSessionPresetUltraHigh_mustUpdateCaptureSessionPreset {
62+
NSString *expectedPreset = AVCaptureSessionPreset3840x2160;
63+
64+
id videoSessionMock = OCMClassMock([AVCaptureSession class]);
65+
OCMStub([videoSessionMock addInputWithNoConnections:[OCMArg any]]);
66+
67+
// Make sure that setting resolution preset for session always succeeds.
68+
OCMStub([videoSessionMock canSetSessionPreset:[OCMArg any]]).andReturn(YES);
69+
70+
// Expect that setting "ultraHigh" resolutionPreset correctly updates videoCaptureSession.
71+
OCMExpect([videoSessionMock setSessionPreset:expectedPreset]);
72+
73+
FLTCreateCamWithVideoCaptureSession(videoSessionMock, @"ultraHigh");
74+
75+
OCMVerifyAll(videoSessionMock);
76+
}
77+
78+
@end

packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraTestUtils.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,24 @@ NS_ASSUME_NONNULL_BEGIN
1111
/// @return an FLTCam object.
1212
extern FLTCam *FLTCreateCamWithCaptureSessionQueue(dispatch_queue_t captureSessionQueue);
1313

14+
/// Creates an `FLTCam` with a given captureSession and resolutionPreset
15+
/// @param captureSession AVCaptureSession for video
16+
/// @param resolutionPreset preset for camera's captureSession resolution
17+
/// @return an FLTCam object.
18+
extern FLTCam *FLTCreateCamWithVideoCaptureSession(AVCaptureSession *captureSession,
19+
NSString *resolutionPreset);
20+
21+
/// Creates an `FLTCam` with a given captureSession and resolutionPreset.
22+
/// Allows to inject a capture device and a block to compute the video dimensions.
23+
/// @param captureSession AVCaptureSession for video
24+
/// @param resolutionPreset preset for camera's captureSession resolution
25+
/// @param captureDevice AVCaptureDevice to be used
26+
/// @param videoDimensionsForFormat custom code to determine video dimensions
27+
/// @return an FLTCam object.
28+
extern FLTCam *FLTCreateCamWithVideoDimensionsForFormat(
29+
AVCaptureSession *captureSession, NSString *resolutionPreset, AVCaptureDevice *captureDevice,
30+
VideoDimensionsForFormat videoDimensionsForFormat);
31+
1432
/// Creates a test sample buffer.
1533
/// @return a test sample buffer.
1634
extern CMSampleBufferRef FLTCreateTestSampleBuffer(void);

packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraTestUtils.m

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212
.andReturn(inputMock);
1313

1414
id videoSessionMock = OCMClassMock([AVCaptureSession class]);
15-
OCMStub([videoSessionMock addInputWithNoConnections:[OCMArg any]]); // no-op
15+
OCMStub([videoSessionMock addInputWithNoConnections:[OCMArg any]]);
1616
OCMStub([videoSessionMock canSetSessionPreset:[OCMArg any]]).andReturn(YES);
1717

1818
id audioSessionMock = OCMClassMock([AVCaptureSession class]);
19-
OCMStub([audioSessionMock addInputWithNoConnections:[OCMArg any]]); // no-op
19+
OCMStub([audioSessionMock addInputWithNoConnections:[OCMArg any]]);
2020
OCMStub([audioSessionMock canSetSessionPreset:[OCMArg any]]).andReturn(YES);
2121

2222
return [[FLTCam alloc] initWithCameraName:@"camera"
@@ -29,6 +29,51 @@
2929
error:nil];
3030
}
3131

32+
FLTCam *FLTCreateCamWithVideoCaptureSession(AVCaptureSession *captureSession,
33+
NSString *resolutionPreset) {
34+
id inputMock = OCMClassMock([AVCaptureDeviceInput class]);
35+
OCMStub([inputMock deviceInputWithDevice:[OCMArg any] error:[OCMArg setTo:nil]])
36+
.andReturn(inputMock);
37+
38+
id audioSessionMock = OCMClassMock([AVCaptureSession class]);
39+
OCMStub([audioSessionMock addInputWithNoConnections:[OCMArg any]]);
40+
OCMStub([audioSessionMock canSetSessionPreset:[OCMArg any]]).andReturn(YES);
41+
42+
return [[FLTCam alloc] initWithCameraName:@"camera"
43+
resolutionPreset:resolutionPreset
44+
enableAudio:true
45+
orientation:UIDeviceOrientationPortrait
46+
videoCaptureSession:captureSession
47+
audioCaptureSession:audioSessionMock
48+
captureSessionQueue:dispatch_queue_create("capture_session_queue", NULL)
49+
error:nil];
50+
}
51+
52+
FLTCam *FLTCreateCamWithVideoDimensionsForFormat(
53+
AVCaptureSession *captureSession, NSString *resolutionPreset, AVCaptureDevice *captureDevice,
54+
VideoDimensionsForFormat videoDimensionsForFormat) {
55+
id inputMock = OCMClassMock([AVCaptureDeviceInput class]);
56+
OCMStub([inputMock deviceInputWithDevice:[OCMArg any] error:[OCMArg setTo:nil]])
57+
.andReturn(inputMock);
58+
59+
id audioSessionMock = OCMClassMock([AVCaptureSession class]);
60+
OCMStub([audioSessionMock addInputWithNoConnections:[OCMArg any]]);
61+
OCMStub([audioSessionMock canSetSessionPreset:[OCMArg any]]).andReturn(YES);
62+
63+
return
64+
[[FLTCam alloc] initWithResolutionPreset:resolutionPreset
65+
enableAudio:true
66+
orientation:UIDeviceOrientationPortrait
67+
videoCaptureSession:captureSession
68+
audioCaptureSession:audioSessionMock
69+
captureSessionQueue:dispatch_queue_create("capture_session_queue", NULL)
70+
captureDeviceFactory:^AVCaptureDevice *(void) {
71+
return captureDevice;
72+
}
73+
videoDimensionsForFormat:videoDimensionsForFormat
74+
error:nil];
75+
}
76+
3277
CMSampleBufferRef FLTCreateTestSampleBuffer(void) {
3378
CVPixelBufferRef pixelBuffer;
3479
CVPixelBufferCreate(kCFAllocatorDefault, 100, 100, kCVPixelFormatType_32BGRA, NULL, &pixelBuffer);

packages/camera/camera_avfoundation/ios/Classes/FLTCam.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ NS_ASSUME_NONNULL_BEGIN
4343
orientation:(UIDeviceOrientation)orientation
4444
captureSessionQueue:(dispatch_queue_t)captureSessionQueue
4545
error:(NSError **)error;
46+
4647
- (void)start;
4748
- (void)stop;
4849
- (void)setDeviceOrientation:(UIDeviceOrientation)orientation;

packages/camera/camera_avfoundation/ios/Classes/FLTCam.m

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ @interface FLTCam () <AVCaptureVideoDataOutputSampleBufferDelegate,
8686
/// Videos are written to disk by `videoAdaptor` on an internal queue managed by AVFoundation.
8787
@property(strong, nonatomic) dispatch_queue_t photoIOQueue;
8888
@property(assign, nonatomic) UIDeviceOrientation deviceOrientation;
89+
/// A wrapper for CMVideoFormatDescriptionGetDimensions.
90+
/// Allows for alternate implementations in tests.
91+
@property(nonatomic, copy) VideoDimensionsForFormat videoDimensionsForFormat;
92+
/// A wrapper for AVCaptureDevice creation to allow for dependency injection in tests.
93+
@property(nonatomic, copy) CaptureDeviceFactory captureDeviceFactory;
8994
@end
9095

9196
@implementation FLTCam
@@ -116,6 +121,30 @@ - (instancetype)initWithCameraName:(NSString *)cameraName
116121
audioCaptureSession:(AVCaptureSession *)audioCaptureSession
117122
captureSessionQueue:(dispatch_queue_t)captureSessionQueue
118123
error:(NSError **)error {
124+
return [self initWithResolutionPreset:resolutionPreset
125+
enableAudio:enableAudio
126+
orientation:orientation
127+
videoCaptureSession:videoCaptureSession
128+
audioCaptureSession:videoCaptureSession
129+
captureSessionQueue:captureSessionQueue
130+
captureDeviceFactory:^AVCaptureDevice *(void) {
131+
return [AVCaptureDevice deviceWithUniqueID:cameraName];
132+
}
133+
videoDimensionsForFormat:^CMVideoDimensions(AVCaptureDeviceFormat *format) {
134+
return CMVideoFormatDescriptionGetDimensions(format.formatDescription);
135+
}
136+
error:error];
137+
}
138+
139+
- (instancetype)initWithResolutionPreset:(NSString *)resolutionPreset
140+
enableAudio:(BOOL)enableAudio
141+
orientation:(UIDeviceOrientation)orientation
142+
videoCaptureSession:(AVCaptureSession *)videoCaptureSession
143+
audioCaptureSession:(AVCaptureSession *)audioCaptureSession
144+
captureSessionQueue:(dispatch_queue_t)captureSessionQueue
145+
captureDeviceFactory:(CaptureDeviceFactory)captureDeviceFactory
146+
videoDimensionsForFormat:(VideoDimensionsForFormat)videoDimensionsForFormat
147+
error:(NSError **)error {
119148
self = [super init];
120149
NSAssert(self, @"super init cannot be nil");
121150
_resolutionPreset = FLTGetFLTResolutionPresetForString(resolutionPreset);
@@ -136,7 +165,9 @@ - (instancetype)initWithCameraName:(NSString *)cameraName
136165
_photoIOQueue = dispatch_queue_create("io.flutter.camera.photoIOQueue", NULL);
137166
_videoCaptureSession = videoCaptureSession;
138167
_audioCaptureSession = audioCaptureSession;
139-
_captureDevice = [AVCaptureDevice deviceWithUniqueID:cameraName];
168+
_captureDeviceFactory = captureDeviceFactory;
169+
_captureDevice = captureDeviceFactory();
170+
_videoDimensionsForFormat = videoDimensionsForFormat;
140171
_flashMode = _captureDevice.hasFlash ? FLTFlashModeAuto : FLTFlashModeOff;
141172
_exposureMode = FLTExposureModeAuto;
142173
_focusMode = FLTFocusModeAuto;
@@ -366,7 +397,24 @@ - (NSString *)getTemporaryFilePathWithExtension:(NSString *)extension
366397

367398
- (BOOL)setCaptureSessionPreset:(FLTResolutionPreset)resolutionPreset withError:(NSError **)error {
368399
switch (resolutionPreset) {
369-
case FLTResolutionPresetMax:
400+
case FLTResolutionPresetMax: {
401+
AVCaptureDeviceFormat *bestFormat =
402+
[self highestResolutionFormatForCaptureDevice:_captureDevice];
403+
if (bestFormat) {
404+
_videoCaptureSession.sessionPreset = AVCaptureSessionPresetInputPriority;
405+
if ([_captureDevice lockForConfiguration:NULL]) {
406+
// Set the best device format found and finish the device configuration.
407+
_captureDevice.activeFormat = bestFormat;
408+
[_captureDevice unlockForConfiguration];
409+
410+
// Set the preview size based on values from the current capture device.
411+
_previewSize =
412+
CGSizeMake(_captureDevice.activeFormat.highResolutionStillImageDimensions.width,
413+
_captureDevice.activeFormat.highResolutionStillImageDimensions.height);
414+
break;
415+
}
416+
}
417+
}
370418
case FLTResolutionPresetUltraHigh:
371419
if ([_videoCaptureSession canSetSessionPreset:AVCaptureSessionPreset3840x2160]) {
372420
_videoCaptureSession.sessionPreset = AVCaptureSessionPreset3840x2160;
@@ -422,6 +470,24 @@ - (BOOL)setCaptureSessionPreset:(FLTResolutionPreset)resolutionPreset withError:
422470
return YES;
423471
}
424472

473+
/// Finds the highest available resolution in terms of pixel count for the given device.
474+
- (AVCaptureDeviceFormat *)highestResolutionFormatForCaptureDevice:
475+
(AVCaptureDevice *)captureDevice {
476+
AVCaptureDeviceFormat *bestFormat = nil;
477+
NSUInteger maxPixelCount = 0;
478+
for (AVCaptureDeviceFormat *format in _captureDevice.formats) {
479+
CMVideoDimensions res = self.videoDimensionsForFormat(format);
480+
NSUInteger height = res.height;
481+
NSUInteger width = res.width;
482+
NSUInteger pixelCount = height * width;
483+
if (pixelCount > maxPixelCount) {
484+
maxPixelCount = pixelCount;
485+
bestFormat = format;
486+
}
487+
}
488+
return bestFormat;
489+
}
490+
425491
- (void)captureOutput:(AVCaptureOutput *)output
426492
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
427493
fromConnection:(AVCaptureConnection *)connection {
@@ -935,7 +1001,7 @@ - (void)setDescriptionWhileRecording:(NSString *)cameraName
9351001
return;
9361002
}
9371003

938-
_captureDevice = [AVCaptureDevice deviceWithUniqueID:cameraName];
1004+
_captureDevice = self.captureDeviceFactory();
9391005

9401006
AVCaptureConnection *oldConnection =
9411007
[_captureVideoOutput connectionWithMediaType:AVMediaTypeVideo];

packages/camera/camera_avfoundation/ios/Classes/FLTCam_Test.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@
55
#import "FLTCam.h"
66
#import "FLTSavePhotoDelegate.h"
77

8+
/// Determines the video dimensions (width and height) for a given capture device format.
9+
/// Used in tests to mock CMVideoFormatDescriptionGetDimensions.
10+
typedef CMVideoDimensions (^VideoDimensionsForFormat)(AVCaptureDeviceFormat *);
11+
12+
/// Factory block returning an AVCaptureDevice.
13+
/// Used in tests to inject a device into FLTCam.
14+
typedef AVCaptureDevice * (^CaptureDeviceFactory)(void);
15+
816
@interface FLTImageStreamHandler : NSObject <FlutterStreamHandler>
917

1018
/// The queue on which `eventSink` property should be accessed.
@@ -55,6 +63,19 @@
5563
captureSessionQueue:(dispatch_queue_t)captureSessionQueue
5664
error:(NSError **)error;
5765

66+
/// Initializes a camera instance.
67+
/// Allows for testing with specified resolution, audio preference, orientation,
68+
/// and direct access to capture sessions and blocks.
69+
- (instancetype)initWithResolutionPreset:(NSString *)resolutionPreset
70+
enableAudio:(BOOL)enableAudio
71+
orientation:(UIDeviceOrientation)orientation
72+
videoCaptureSession:(AVCaptureSession *)videoCaptureSession
73+
audioCaptureSession:(AVCaptureSession *)audioCaptureSession
74+
captureSessionQueue:(dispatch_queue_t)captureSessionQueue
75+
captureDeviceFactory:(CaptureDeviceFactory)captureDeviceFactory
76+
videoDimensionsForFormat:(VideoDimensionsForFormat)videoDimensionsForFormat
77+
error:(NSError **)error;
78+
5879
/// Start streaming images.
5980
- (void)startImageStreamWithMessenger:(NSObject<FlutterBinaryMessenger> *)messenger
6081
imageStreamHandler:(FLTImageStreamHandler *)imageStreamHandler;

packages/camera/camera_avfoundation/pubspec.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ name: camera_avfoundation
22
description: iOS implementation of the camera plugin.
33
repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_avfoundation
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
5-
version: 0.9.14
5+
6+
version: 0.9.14+1
67

78
environment:
89
sdk: ^3.2.3

0 commit comments

Comments
 (0)