Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/camera/camera/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.9.4+8

* Fixes a bug where ImageFormatGroup was ignored in `startImageStream` on iOS.

## 0.9.4+7

* Fixes a crash in iOS when passing null queue pointer into AVFoundation API due to race condition.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,4 +240,56 @@ void main() {
},
skip: !Platform.isAndroid,
);

/// Start streaming with specifying the ImageFormatGroup.
Future<CameraImage> startStreaming(List<CameraDescription> cameras,
ImageFormatGroup? imageFormatGroup) async {
final CameraController controller = CameraController(
cameras.first,
ResolutionPreset.low,
enableAudio: false,
imageFormatGroup: imageFormatGroup,
);

await controller.initialize();
final _completer = Completer<CameraImage>();

await controller.startImageStream((CameraImage image) {
if (!_completer.isCompleted) {
Future(() async {
await controller.stopImageStream();
await controller.dispose();
}).then((value) {
_completer.complete(image);
});
}
});
return _completer.future;
}

testWidgets(
'iOS image streaming with imageFormatGroup',
(WidgetTester tester) async {
final List<CameraDescription> cameras = await availableCameras();
if (cameras.isEmpty) {
return;
}

var _image = await startStreaming(cameras, null);
expect(_image, isNotNull);
expect(_image.format.group, ImageFormatGroup.bgra8888);
expect(_image.planes.length, 1);

_image = await startStreaming(cameras, ImageFormatGroup.yuv420);
expect(_image, isNotNull);
expect(_image.format.group, ImageFormatGroup.yuv420);
expect(_image.planes.length, 2);

_image = await startStreaming(cameras, ImageFormatGroup.bgra8888);
expect(_image, isNotNull);
expect(_image.format.group, ImageFormatGroup.bgra8888);
expect(_image.planes.length, 1);
},
skip: !Platform.isIOS,
);
}
19 changes: 13 additions & 6 deletions packages/camera/camera/ios/Classes/CameraPlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,8 @@ @interface FLTCam : NSObject <FlutterTexture,
@property(assign, nonatomic) CMTime lastAudioSampleTime;
@property(assign, nonatomic) CMTime videoTimeOffset;
@property(assign, nonatomic) CMTime audioTimeOffset;
// Format used for video and image streaming.
@property(assign, nonatomic) FourCharCode videoFormat;
@property(nonatomic) CMMotionManager *motionManager;
@property AVAssetWriterInputPixelBufferAdaptor *videoAdaptor;
@end
Expand All @@ -365,8 +367,6 @@ @implementation FLTCam {
dispatch_queue_t _captureSessionQueue;
UIDeviceOrientation _deviceOrientation;
}
// Format used for video and image streaming.
FourCharCode videoFormat = kCVPixelFormatType_32BGRA;
NSString *const errorMethod = @"error";

- (instancetype)initWithCameraName:(NSString *)cameraName
Expand All @@ -391,6 +391,7 @@ - (instancetype)initWithCameraName:(NSString *)cameraName
_focusMode = FocusModeAuto;
_lockedCaptureOrientation = UIDeviceOrientationUnknown;
_deviceOrientation = orientation;
_videoFormat = kCVPixelFormatType_32BGRA;

NSError *localError = nil;
_captureVideoInput = [AVCaptureDeviceInput deviceInputWithDevice:_captureDevice
Expand All @@ -403,7 +404,7 @@ - (instancetype)initWithCameraName:(NSString *)cameraName

_captureVideoOutput = [AVCaptureVideoDataOutput new];
_captureVideoOutput.videoSettings =
@{(NSString *)kCVPixelBufferPixelFormatTypeKey : @(videoFormat)};
@{(NSString *)kCVPixelBufferPixelFormatTypeKey : @(_videoFormat)};
[_captureVideoOutput setAlwaysDiscardsLateVideoFrames:YES];
[_captureVideoOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];

Expand Down Expand Up @@ -441,6 +442,12 @@ - (void)stop {
[_captureSession stopRunning];
}

- (void)setVideoFormat:(OSType)videoFormat {
_videoFormat = videoFormat;
_captureVideoOutput.videoSettings =
@{(NSString *)kCVPixelBufferPixelFormatTypeKey : @(videoFormat)};
}

- (void)setDeviceOrientation:(UIDeviceOrientation)orientation {
if (_deviceOrientation == orientation) {
return;
Expand Down Expand Up @@ -680,7 +687,7 @@ - (void)captureOutput:(AVCaptureOutput *)output
NSMutableDictionary *imageBuffer = [NSMutableDictionary dictionary];
imageBuffer[@"width"] = [NSNumber numberWithUnsignedLong:imageWidth];
imageBuffer[@"height"] = [NSNumber numberWithUnsignedLong:imageHeight];
imageBuffer[@"format"] = @(videoFormat);
imageBuffer[@"format"] = @(_videoFormat);
imageBuffer[@"planes"] = planes;
imageBuffer[@"lensAperture"] = [NSNumber numberWithFloat:[_captureDevice lensAperture]];
Float64 exposureDuration = CMTimeGetSeconds([_captureDevice exposureDuration]);
Expand Down Expand Up @@ -1246,7 +1253,7 @@ - (BOOL)setupWriterForPath:(NSString *)path {
_videoAdaptor = [AVAssetWriterInputPixelBufferAdaptor
assetWriterInputPixelBufferAdaptorWithAssetWriterInput:_videoWriterInput
sourcePixelBufferAttributes:@{
(NSString *)kCVPixelBufferPixelFormatTypeKey : @(videoFormat)
(NSString *)kCVPixelBufferPixelFormatTypeKey : @(_videoFormat)
}];

NSParameterAssert(_videoWriterInput);
Expand Down Expand Up @@ -1464,7 +1471,7 @@ - (void)handleMethodCallAsync:(FlutterMethodCall *)call
NSUInteger cameraId = ((NSNumber *)argsMap[@"cameraId"]).unsignedIntegerValue;
if ([@"initialize" isEqualToString:call.method]) {
NSString *videoFormatValue = ((NSString *)argsMap[@"imageFormatGroup"]);
videoFormat = getVideoFormatFromString(videoFormatValue);
[_camera setVideoFormat:getVideoFormatFromString(videoFormatValue)];

__weak CameraPlugin *weakSelf = self;
_camera.onFrameAvailable = ^{
Expand Down
2 changes: 1 addition & 1 deletion packages/camera/camera/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: A Flutter plugin for controlling the camera. Supports previewing
Dart.
repository: https://github.com/flutter/plugins/tree/main/packages/camera/camera
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
version: 0.9.4+7
version: 0.9.4+8

environment:
sdk: ">=2.14.0 <3.0.0"
Expand Down