diff --git a/packages/camera/ios/Classes/CameraPlugin.m b/packages/camera/ios/Classes/CameraPlugin.m index 6af25fc2a659..712d946b2a03 100644 --- a/packages/camera/ios/Classes/CameraPlugin.m +++ b/packages/camera/ios/Classes/CameraPlugin.m @@ -86,8 +86,8 @@ - (instancetype)initWithCameraName:(NSString *)cameraName error:(NSError **)error; - (void)start; - (void)stop; -- (void)startRecordingVideoAtPath:(NSString *)path result:(FlutterResult)result; -- (void)stopRecordingVideoWithResult:(FlutterResult)result; +- (void)startVideoRecordingAtPath:(NSString *)path result:(FlutterResult)result; +- (void)stopVideoRecordingWithResult:(FlutterResult)result; - (void)captureToFile:(NSString *)filename result:(FlutterResult)result; @end @@ -211,12 +211,14 @@ - (void)newVideoSample:(CMSampleBufferRef)sampleBuffer { }); return; } - if (![_videoWriterInput appendSampleBuffer:sampleBuffer]) { - _eventSink(@{ - @"event" : @"error", - @"errorDescription" : [NSString stringWithFormat:@"%@", @"Unable to write to video input"] - }); - } + if (_videoWriterInput.readyForMoreMediaData) { + if (![_videoWriterInput appendSampleBuffer:sampleBuffer]) { + _eventSink(@{ + @"event" : @"error", + @"errorDescription" : [NSString stringWithFormat:@"%@", @"Unable to write to video input"] + }); + } + } } - (void)newAudioSample:(CMSampleBufferRef)sampleBuffer { @@ -228,12 +230,14 @@ - (void)newAudioSample:(CMSampleBufferRef)sampleBuffer { }); return; } - if (![_audioWriterInput appendSampleBuffer:sampleBuffer]) { - _eventSink(@{ - @"event" : @"error", - @"errorDescription" : [NSString stringWithFormat:@"%@", @"Unable to write to audio input"] - }); - } + if (_audioWriterInput.readyForMoreMediaData) { + if (![_audioWriterInput appendSampleBuffer:sampleBuffer]) { + _eventSink(@{ + @"event" : @"error", + @"errorDescription" : [NSString stringWithFormat:@"%@", @"Unable to write to audio input"] + }); + } + } } - (void)close { @@ -270,7 +274,7 @@ - (FlutterError *_Nullable)onListenWithArguments:(id _Nullable)arguments _eventSink = events; return nil; } -- (void)startRecordingVideoAtPath:(NSString *)path result:(FlutterResult)result { +- (void)startVideoRecordingAtPath:(NSString *)path result:(FlutterResult)result { if (!_isRecording) { if (![self setupWriterForPath:path]) { _eventSink(@{@"event" : @"error", @"errorDescription" : @"Setup Writer Failed"}); @@ -284,16 +288,26 @@ - (void)startRecordingVideoAtPath:(NSString *)path result:(FlutterResult)result } } -- (void)stopRecordingVideoWithResult:(FlutterResult)result { +- (void)stopVideoRecordingWithResult:(FlutterResult)result { if (_isRecording) { _isRecording = NO; - __block NSString *path = _videoWriter.outputURL.absoluteString; - if (_videoWriter.status != 0) { + if (_videoWriter.status != AVAssetWriterStatusUnknown) { [_videoWriter finishWritingWithCompletionHandler:^{ - result(@{@"outputURL" : path}); + if (self->_videoWriter.status == AVAssetWriterStatusCompleted) { + result(nil); + } + else + { + self->_eventSink(@{@"event" : @"error", @"errorDescription" : @"AVAssetWriter could not finish writing!"}); + } }]; } } + else + { + NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSURLErrorResourceUnavailable userInfo:@{NSLocalizedDescriptionKey:@"Video is not recording!"}]; + result([error flutterError]); + } } - (BOOL)setupWriterForPath:(NSString *)path { @@ -355,6 +369,12 @@ - (void)setUpCaptureSessionForAudio { AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio]; AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:&error]; + if (error) { + _eventSink(@{ + @"event" : @"error", + @"errorDescription" : error.description + }); + } // Setup the audio output. _audioOutput = [[AVCaptureAudioDataOutput alloc] init]; @@ -378,7 +398,7 @@ - (void)setUpCaptureSessionForAudio { @interface CameraPlugin () @property(readonly, nonatomic) NSObject *registry; @property(readonly, nonatomic) NSObject *messenger; -@property(readonly, nonatomic) NSMutableDictionary *cams; +@property(readonly, nonatomic) FLTCam *camera; @end @implementation CameraPlugin @@ -397,17 +417,11 @@ - (instancetype)initWithRegistry:(NSObject *)registry NSAssert(self, @"super init cannot be nil"); _registry = registry; _messenger = messenger; - _cams = [NSMutableDictionary dictionaryWithCapacity:1]; return self; } - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { if ([@"init" isEqualToString:call.method]) { - for (NSNumber *textureId in _cams) { - [_registry unregisterTexture:[textureId longLongValue]]; - [[_cams objectForKey:textureId] close]; - } - [_cams removeAllObjects]; result(nil); } else if ([@"availableCameras" isEqualToString:call.method]) { AVCaptureDeviceDiscoverySession *discoverySession = [AVCaptureDeviceDiscoverySession @@ -447,7 +461,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result result([error flutterError]); } else { int64_t textureId = [_registry registerTexture:cam]; - _cams[@(textureId)] = cam; + _camera = cam; cam.onFrameAvailable = ^{ [_registry textureFrameAvailable:textureId]; }; @@ -470,21 +484,18 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result } else { NSDictionary *argsMap = call.arguments; NSUInteger textureId = ((NSNumber *)argsMap[@"textureId"]).unsignedIntegerValue; - FLTCam *cam = _cams[@(textureId)]; + if ([@"takePicture" isEqualToString:call.method]) { - [cam captureToFile:call.arguments[@"path"] result:result]; + [_camera captureToFile:call.arguments[@"path"] result:result]; } else if ([@"dispose" isEqualToString:call.method]) { [_registry unregisterTexture:textureId]; - [cam close]; - [_cams removeObjectForKey:@(textureId)]; + [_camera close]; result(nil); } else if ([@"startVideoRecording" isEqualToString:call.method]) { - [cam startRecordingVideoAtPath:call.arguments[@"filePath"] result:result]; - + [_camera startVideoRecordingAtPath:call.arguments[@"filePath"] result:result]; } else if ([@"stopVideoRecording" isEqualToString:call.method]) { - [cam stopRecordingVideoWithResult:result]; - result(nil); + [_camera stopVideoRecordingWithResult:result]; } else { result(FlutterMethodNotImplemented); }