diff --git a/ios/RN/RNCamera.h b/ios/RN/RNCamera.h index 5c27af8f5..83efe6d3d 100644 --- a/ios/RN/RNCamera.h +++ b/ios/RN/RNCamera.h @@ -30,6 +30,7 @@ @property (assign, nonatomic) float focusDepth; @property (assign, nonatomic) NSInteger whiteBalance; @property (nonatomic, assign, getter=isReadingBarCodes) BOOL barCodeReading; +@property(assign, nonatomic) AVVideoCodecType videoCodecType; - (id)initWithBridge:(RCTBridge *)bridge; - (void)updateType; diff --git a/ios/RN/RNCamera.m b/ios/RN/RNCamera.m index e81d252aa..be792e3ac 100644 --- a/ios/RN/RNCamera.m +++ b/ios/RN/RNCamera.m @@ -404,7 +404,21 @@ - (void)record:(NSDictionary *)options resolve:(RCTPromiseResolveBlock)resolve r AVCaptureConnection *connection = [self.movieFileOutput connectionWithMediaType:AVMediaTypeVideo]; [connection setVideoOrientation:[RNCameraUtils videoOrientationForInterfaceOrientation:[[UIApplication sharedApplication] statusBarOrientation]]]; - + + if (options[@"codec"]) { + AVVideoCodecType videoCodecType = options[@"codec"]; + if (@available(iOS 10, *)) { + if ([self.movieFileOutput.availableVideoCodecTypes containsObject:videoCodecType]) { + [self.movieFileOutput setOutputSettings:@{AVVideoCodecKey:videoCodecType} forConnection:connection]; + self.videoCodecType = videoCodecType; + } else { + RCTLogWarn(@"%s: Video Codec '%@' is not supported on this device.", __func__, videoCodecType); + } + } else { + RCTLogWarn(@"%s: Setting videoCodec is only supported above iOS version 10.", __func__); + } + } + dispatch_async(self.sessionQueue, ^{ NSString *path = [RNFileSystem generatePathInDirectory:[[RNFileSystem cacheDirectoryPath] stringByAppendingString:@"Camera"] withExtension:@".mov"]; NSURL *outputURL = [[NSURL alloc] initFileURLWithPath:path]; @@ -714,12 +728,18 @@ - (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToO } } if (success && self.videoRecordedResolve != nil) { - self.videoRecordedResolve(@{ @"uri": outputFileURL.absoluteString }); + AVVideoCodecType videoCodec = self.videoCodecType; + if (videoCodec == nil) { + videoCodec = [self.movieFileOutput.availableVideoCodecTypes firstObject]; + } + + self.videoRecordedResolve(@{ @"uri": outputFileURL.absoluteString, @"codec":videoCodec }); } else if (self.videoRecordedReject != nil) { self.videoRecordedReject(@"E_RECORDING_FAILED", @"An error occurred while recording a video.", error); } self.videoRecordedResolve = nil; self.videoRecordedReject = nil; + self.videoCodecType = nil; [self cleanupMovieFileCapture]; // If face detection has been running prior to recording to file diff --git a/ios/RN/RNCameraManager.h b/ios/RN/RNCameraManager.h index 91a6b13ba..52bc556f2 100644 --- a/ios/RN/RNCameraManager.h +++ b/ios/RN/RNCameraManager.h @@ -49,6 +49,7 @@ typedef NS_ENUM(NSInteger, RNCameraVideoResolution) { @interface RNCameraManager : RCTViewManager + (NSDictionary *)validBarCodeTypes; ++ (NSDictionary *)validCodecTypes; @end diff --git a/ios/RN/RNCameraManager.m b/ios/RN/RNCameraManager.m index 3ff8f41b2..ec4adcd81 100644 --- a/ios/RN/RNCameraManager.m +++ b/ios/RN/RNCameraManager.m @@ -55,6 +55,7 @@ - (NSDictionary *)constantsToExport @"480p": @(RNCameraVideo4x3), @"4:3": @(RNCameraVideo4x3), }, + @"VideoCodec": [[self class] validCodecTypes], @"BarCodeType" : [[self class] validBarCodeTypes], @"FaceDetection" : [[self class] faceDetectorConstants] }; @@ -65,6 +66,24 @@ - (NSDictionary *)constantsToExport return @[@"onCameraReady", @"onMountError", @"onBarCodeRead", @"onFacesDetected"]; } ++ (NSDictionary *)validCodecTypes +{ + if (@available(iOS 11, *)) { + return @{ + @"H264": AVVideoCodecTypeH264, + @"HVEC": AVVideoCodecTypeHEVC, + @"JPEG": AVVideoCodecTypeJPEG, + @"AppleProRes422": AVVideoCodecTypeAppleProRes422, + @"AppleProRes4444": AVVideoCodecTypeAppleProRes4444 + }; + } else { + return @{ + @"H264": AVVideoCodecH264, + @"JPEG": AVVideoCodecJPEG + }; + } +} + + (NSDictionary *)validBarCodeTypes { return @{ diff --git a/src/RNCamera.js b/src/RNCamera.js index 829e47f5b..a7aafb3fc 100644 --- a/src/RNCamera.js +++ b/src/RNCamera.js @@ -35,6 +35,7 @@ type RecordingOptions = { maxDuration?: number, maxFileSize?: number, quality?: number | string, + codec?: string, mute?: boolean, }; @@ -96,6 +97,7 @@ export default class Camera extends React.Component { AutoFocus: CameraManager.AutoFocus, WhiteBalance: CameraManager.WhiteBalance, VideoQuality: CameraManager.VideoQuality, + VideoCodec: CameraManager.VideoCodec, BarCodeType: CameraManager.BarCodeType, FaceDetection: CameraManager.FaceDetection, };