added video support for cameraRoll and disk targets

This commit is contained in:
Matthieu Achard 2015-06-14 19:16:09 +02:00 committed by machard
parent 3dcd6b0a16
commit 5a151a808d
3 changed files with 136 additions and 2 deletions

View File

@ -182,6 +182,10 @@ var Camera = React.createClass({
}
NativeModules.CameraManager.capture(options, cb);
},
stopCapture() {
NativeModules.CameraManager.stopCapture();
}
});

View File

@ -45,6 +45,7 @@ typedef NS_ENUM(NSInteger, RCTCameraFlashMode) {
@property (nonatomic) AVCaptureSession *session;
@property (nonatomic) AVCaptureDeviceInput *captureDeviceInput;
@property (nonatomic) AVCaptureStillImageOutput *stillImageOutput;
@property (nonatomic) AVCaptureMovieFileOutput *movieFileOutput;
@property (nonatomic) AVCaptureMetadataOutput *metadataOutput;
@property (nonatomic) id runtimeErrorHandlingObserver;
@property (nonatomic) NSInteger presetCamera;
@ -56,5 +57,6 @@ typedef NS_ENUM(NSInteger, RCTCameraFlashMode) {
- (void)changeFlashMode:(NSInteger)flashMode;
- (AVCaptureDevice *)deviceWithMediaType:(NSString *)mediaType preferringPosition:(AVCaptureDevicePosition)position;
- (void)capture:(NSDictionary*)options callback:(RCTResponseSenderBlock)callback;
- (void)stopCapture;
@end

View File

@ -9,7 +9,10 @@
#import <AssetsLibrary/ALAssetsLibrary.h>
#import <AVFoundation/AVFoundation.h>
@implementation RCTCameraManager
@implementation RCTCameraManager {
NSInteger videoTarget;
RCTResponseSenderBlock videoCallback;
}
RCT_EXPORT_MODULE();
@ -93,6 +96,21 @@ RCT_EXPORT_VIEW_PROPERTY(flashMode, NSInteger);
self.captureDeviceInput = captureDeviceInput;
}
}
AVCaptureDevice *audioCaptureDevice = [self deviceWithMediaType:AVMediaTypeAudio preferringPosition:self.presetCamera];
if (audioCaptureDevice != nil) {
AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioCaptureDevice error:&error];
if (error)
{
NSLog(@"%@", error);
}
if ([self.session canAddInput:audioInput])
{
[self.session addInput:audioInput];
}
}
AVCaptureStillImageOutput *stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
if ([self.session canAddOutput:stillImageOutput])
@ -101,6 +119,13 @@ RCT_EXPORT_VIEW_PROPERTY(flashMode, NSInteger);
[self.session addOutput:stillImageOutput];
self.stillImageOutput = stillImageOutput;
}
AVCaptureMovieFileOutput *movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
if ([self.session canAddOutput:movieFileOutput])
{
[self.session addOutput:movieFileOutput];
self.movieFileOutput = movieFileOutput;
}
AVCaptureMetadataOutput *metadataOutput = [[AVCaptureMetadataOutput alloc] init];
if ([self.session canAddOutput:metadataOutput]) {
@ -193,7 +218,23 @@ RCT_EXPORT_METHOD(capture:(NSDictionary *)options callback:(RCTResponseSenderBlo
[self captureStill:captureTarget callback:callback];
}
else if (captureMode == RCTCameraCaptureModeVideo) {
// waiting for incoming PRs
if (self.movieFileOutput.recording) {
callback(@[RCTMakeError(@"Already Recording", nil, nil)]);
return;
}
Float64 totalSeconds = [[options valueForKey:@"totalSeconds"] floatValue];
int32_t preferredTimeScale = [[options valueForKey:@"preferredTimeScale"] intValue];
CMTime maxDuration = CMTimeMakeWithSeconds(totalSeconds || 60, preferredTimeScale | 30);
self.movieFileOutput.maxRecordedDuration = maxDuration;
[self captureVideo:captureTarget callback:callback];
}
}
RCT_EXPORT_METHOD(stopCapture) {
if (self.movieFileOutput.recording) {
[self.movieFileOutput stopRecording];
}
}
@ -234,6 +275,93 @@ RCT_EXPORT_METHOD(capture:(NSDictionary *)options callback:(RCTResponseSenderBlo
}];
}
-(void)captureVideo:(NSInteger)target callback:(RCTResponseSenderBlock)callback {
[[self.movieFileOutput connectionWithMediaType:AVMediaTypeVideo] setVideoOrientation:self.previewLayer.connection.videoOrientation];
//Create temporary URL to record to
NSString *outputPath = [[NSString alloc] initWithFormat:@"%@%@", NSTemporaryDirectory(), @"output.mov"];
NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:outputPath];
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:outputPath])
{
NSError *error;
if ([fileManager removeItemAtPath:outputPath error:&error] == NO)
{
callback(@[RCTMakeError(error.description, nil, nil)]);
return;
}
}
//Start recording
[self.movieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self];
videoCallback = callback;
videoTarget = target;
}
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput
didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL
fromConnections:(NSArray *)connections
error:(NSError *)error
{
NSLog(@"didFinishRecordingToOutputFileAtURL - enter");
BOOL RecordedSuccessfully = YES;
if ([error code] != noErr)
{
// A problem occurred: Find out if the recording was successful.
id value = [[error userInfo] objectForKey:AVErrorRecordingSuccessfullyFinishedKey];
if (value)
{
RecordedSuccessfully = [value boolValue];
}
}
if (RecordedSuccessfully)
{
//----- RECORDED SUCESSFULLY -----
NSLog(@"didFinishRecordingToOutputFileAtURL - success");
if (videoTarget == RCTCameraCaptureTargetCameraRoll) {
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:outputFileURL])
{
[library writeVideoAtPathToSavedPhotosAlbum:outputFileURL
completionBlock:^(NSURL *assetURL, NSError *error)
{
if (error)
{
videoCallback(@[RCTMakeError(error.description, nil, nil)]);
return;
}
videoCallback(@[[NSNull null], [assetURL absoluteString]]);
}];
}
}
else if (videoTarget == RCTCameraCaptureTargetDisk) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths firstObject];
NSString *fullPath = [[documentsDirectory stringByAppendingPathComponent:[[NSUUID UUID] UUIDString]] stringByAppendingPathExtension:@"mov"];
NSFileManager * fileManager = [ NSFileManager defaultManager];
NSError * error = nil;
//copying destination
if ( !( [ fileManager copyItemAtPath:[outputFileURL path] toPath:fullPath error:&error ]) )
{
videoCallback(@[RCTMakeError(error.description, nil, nil)]);
return;
}
videoCallback(@[[NSNull null], fullPath]);
}
else {
videoCallback(@[RCTMakeError(@"Target not supported", nil, nil)]);
}
} else {
videoCallback(@[RCTMakeError(@"Error while recording", nil, nil)]);
}
}
- (NSString *)saveImage:(UIImage *)image withName:(NSString *)name {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths firstObject];