public override void FinishedRecording (AVCaptureFileOutput captureOutput, NSUrl outputFileUrl, NSObject[] connections, NSError error) { try { FinishedRecordingInternal (captureOutput, outputFileUrl, connections, error); } catch (Exception ex) { string errorMessage = string.Format ("Exception during movie recording finish handler: {0}", ErrorHandling.GetExceptionDetailedText (ex) ); OnCaptureError (errorMessage); } }
void FinishedRecordingInternal (AVCaptureFileOutput captureOutput, NSUrl outputFileUrl, NSObject[] connections, NSError nsError) { if ( nsError != null ) { // we are hoping for an 'error' object that contains three items // this error is expected because we have specified a file size limit and the streaming // session has filled it up so we need to let the world know by raising an event. // note that a correctly recorded file calls the delegate with an error code even // though this is not (always) an actual error. We have to check the code to know for sure. var userInfo = nsError.UserInfo; // handle recording stoppage due to file size limit if ((userInfo.Keys.Length == 3) && (nsError.Code == -11811)) { var k0 = userInfo.Keys[0]; var v0 = userInfo.Values[0]; int segmentLength; if (k0.ToString () != "AVErrorFileSizeKey" || (int.TryParse (v0.ToString (), out segmentLength) == false ) || segmentLength == 0) { OnMovieSegmentRecordingComplete (null, 0, true); } else { string path = outputFileUrl.Path; OnMovieSegmentRecordingComplete (path, segmentLength, false); } } else if (userInfo.Keys.Length == 3 && nsError.Code == -11810) { var k0 = userInfo.Keys[0]; if (k0.ToString () != "AVErrorTimeKey") { OnMovieSegmentRecordingComplete (null, 0, true); } else { string path = outputFileUrl.Path; OnMovieSegmentRecordingComplete (path, 0, false); } } else { // unexpected error code indicates a real error OnCaptureError ($"\"Error during movie recording finish handler: {ErrorHandling.GetNSErrorString (nsError)}"); } } else { string path = outputFileUrl.Path; if ( File.Exists(path) == true ) { OnMovieSegmentRecordingComplete( path, 0, false ); } else { OnCaptureError ($"file not written: {path}"); } } }
public override void DidStartRecording ( AVCaptureFileOutput captureOutput, NSUrl outputFileUrl, NSObject[] connections ) { string path = outputFileUrl.Path; onMovieSegmentRecordingStarted( path ); }
public void FinishedRecording (AVCaptureFileOutput captureOutput, NSUrl outputFileUrl, NSObject [] connections, NSError error) { // Note that currentBackgroundRecordingID is used to end the background task associated with this recording. // This allows a new recording to be started, associated with a new UIBackgroundTaskIdentifier, once the movie file output's isRecording property // is back to false — which happens sometime after this method returns. // Note: Since we use a unique file path for each recording, a new recording will not overwrite a recording currently being saved. Action cleanup = () => { var path = outputFileUrl.Path; if (NSFileManager.DefaultManager.FileExists (path)) { NSError err; if (!NSFileManager.DefaultManager.Remove (path, out err)) Console.WriteLine ($"Could not remove file at url: {outputFileUrl}"); } var currentBackgroundRecordingID = backgroundRecordingID; if (currentBackgroundRecordingID != -1) { backgroundRecordingID = -1; UIApplication.SharedApplication.EndBackgroundTask (currentBackgroundRecordingID); } }; bool success = true; if (error != null) { Console.WriteLine ($"Movie file finishing error: {error.LocalizedDescription}"); success = ((NSNumber)error.UserInfo [AVErrorKeys.RecordingSuccessfullyFinished]).BoolValue; } if (success) { // Check authorization status. PHPhotoLibrary.RequestAuthorization (status => { if (status == PHAuthorizationStatus.Authorized) { // Save the movie file to the photo library and cleanup. PHPhotoLibrary.SharedPhotoLibrary.PerformChanges (() => { var options = new PHAssetResourceCreationOptions { ShouldMoveFile = true }; var creationRequest = PHAssetCreationRequest.CreationRequestForAsset (); creationRequest.AddResource (PHAssetResourceType.Video, outputFileUrl, options); }, (success2, error2) => { if (!success2) Console.WriteLine ($"Could not save movie to photo library: {error2}"); cleanup (); }); } else { cleanup (); } }); } else { cleanup (); } // Enable the Camera and Record buttons to let the user switch camera and start another recording. DispatchQueue.MainQueue.DispatchAsync (() => { // Only enable the ability to change camera if the device has more than one camera. CameraButton.Enabled = UniqueDevicePositionsCount (videoDeviceDiscoverySession) > 1; RecordButton.Enabled = true; CaptureModeControl.Enabled = true; RecordButton.SetTitle ("Record", UIControlState.Normal); }); }
public void DidStartRecording (AVCaptureFileOutput captureOutput, NSUrl outputFileUrl, NSObject [] connections) { // Enable the Record button to let the user stop the recording. DispatchQueue.MainQueue.DispatchAsync (() => { RecordButton.Enabled = true; RecordButton.SetTitle ("Stop", UIControlState.Normal); }); }
void FinishedRecordingInternal(AVCaptureFileOutput captureOutput, NSUrl outputFileUrl, NSObject[] connections, NSError nsError) { if (nsError != null) { // we are hoping for an 'error' object that contains three items // this error is expected because we have specified a file size limit and the streaming // session has filled it up so we need to let the world know by raising an event. // note that a correctly recorded file calls the delegate with an error code even // though this is not (always) an actual error. We have to check the code to know for sure. var userInfo = nsError.UserInfo; // handle recording stoppage due to file size limit if ((userInfo.Keys.Length == 3) && (nsError.Code == -11811)) { var k0 = userInfo.Keys[0]; var v0 = userInfo.Values[0]; int segmentLength; if (k0.ToString() != "AVErrorFileSizeKey" || (int.TryParse(v0.ToString(), out segmentLength) == false) || segmentLength == 0) { OnMovieSegmentRecordingComplete(null, 0, true); } else { string path = outputFileUrl.Path; OnMovieSegmentRecordingComplete(path, segmentLength, false); } } else if (userInfo.Keys.Length == 3 && nsError.Code == -11810) { var k0 = userInfo.Keys[0]; if (k0.ToString() != "AVErrorTimeKey") { OnMovieSegmentRecordingComplete(null, 0, true); } else { string path = outputFileUrl.Path; OnMovieSegmentRecordingComplete(path, 0, false); } } else { // unexpected error code indicates a real error OnCaptureError($"\"Error during movie recording finish handler: {ErrorHandling.GetNSErrorString (nsError)}"); } } else { string path = outputFileUrl.Path; if (File.Exists(path) == true) { OnMovieSegmentRecordingComplete(path, 0, false); } else { OnCaptureError($"file not written: {path}"); } } }
public override void DidStartRecording(AVCaptureFileOutput captureOutput, NSUrl outputFileUrl, NSObject[] connections) { string path = outputFileUrl.Path; OnMovieSegmentRecordingStarted(path); }
public void FinishedRecording(AVCaptureFileOutput captureOutput, NSUrl outputFileUrl, NSObject [] connections, NSError error) { // Note that currentBackgroundRecordingID is used to end the background task associated with this recording. // This allows a new recording to be started, associated with a new UIBackgroundTaskIdentifier, once the movie file output's isRecording property // is back to false — which happens sometime after this method returns. // Note: Since we use a unique file path for each recording, a new recording will not overwrite a recording currently being saved. Action cleanup = () => { var path = outputFileUrl.Path; if (NSFileManager.DefaultManager.FileExists(path)) { NSError err; if (!NSFileManager.DefaultManager.Remove(path, out err)) { Console.WriteLine($"Could not remove file at url: {outputFileUrl}"); } } var currentBackgroundRecordingID = backgroundRecordingID; if (currentBackgroundRecordingID != -1) { backgroundRecordingID = -1; UIApplication.SharedApplication.EndBackgroundTask(currentBackgroundRecordingID); } }; bool success = true; if (error != null) { Console.WriteLine($"Movie file finishing error: {error.LocalizedDescription}"); success = ((NSNumber)error.UserInfo [AVErrorKeys.RecordingSuccessfullyFinished]).BoolValue; } if (success) { // Check authorization status. PHPhotoLibrary.RequestAuthorization(status => { if (status == PHAuthorizationStatus.Authorized) { // Save the movie file to the photo library and cleanup. PHPhotoLibrary.SharedPhotoLibrary.PerformChanges(() => { var options = new PHAssetResourceCreationOptions { ShouldMoveFile = true }; var creationRequest = PHAssetCreationRequest.CreationRequestForAsset(); creationRequest.AddResource(PHAssetResourceType.Video, outputFileUrl, options); }, (success2, error2) => { if (!success2) { Console.WriteLine($"Could not save movie to photo library: {error2}"); } cleanup(); }); } else { cleanup(); } }); } else { cleanup(); } // Enable the Camera and Record buttons to let the user switch camera and start another recording. DispatchQueue.MainQueue.DispatchAsync(() => { // Only enable the ability to change camera if the device has more than one camera. CameraButton.Enabled = UniqueDevicePositionsCount(videoDeviceDiscoverySession) > 1; RecordButton.Enabled = true; CaptureModeControl.Enabled = true; RecordButton.SetTitle("Record", UIControlState.Normal); }); }
public void FinishedRecording (AVCaptureFileOutput captureOutput, NSUrl outputFileUrl, NSObject [] connections, NSError error) { // Note that currentBackgroundRecordingID is used to end the background task associated with this recording. // This allows a new recording to be started, associated with a new UIBackgroundTaskIdentifier, once the movie file output's Recording property // is back to false — which happens sometime after this method returns. // Note: Since we use a unique file path for each recording, a new recording will not overwrite a recording currently being saved. var currentBackgroundRecordingID = backgroundRecordingID; backgroundRecordingID = -1; Action cleanup = () => { NSError err; if (NSFileManager.DefaultManager.FileExists (outputFileUrl.Path)) NSFileManager.DefaultManager.Remove (outputFileUrl, out err); if (currentBackgroundRecordingID != -1) UIApplication.SharedApplication.EndBackgroundTask (currentBackgroundRecordingID); }; var success = true; if (error != null) { Console.WriteLine ($"Error occurred while capturing movie: {error}"); success = error.UserInfo [AVErrorKeys.RecordingSuccessfullyFinished].AsBool (); } if (success) { PHPhotoLibrary.RequestAuthorization (status => { if (status == PHAuthorizationStatus.Authorized) { // Save the movie file to the photo library and cleanup PHPhotoLibrary.SharedPhotoLibrary.PerformChanges (() => { // In iOS 9 and later, it's possible to move the file into the photo library without duplicating the file data. // This avoids using double the disk space during save, which can make a difference on devices with limited free disk space. var options = new PHAssetResourceCreationOptions { ShouldMoveFile = true }; PHAssetCreationRequest changeRequest = PHAssetCreationRequest.CreationRequestForAsset (); changeRequest.AddResource (PHAssetResourceType.Video, outputFileUrl, options); }, (result, err) => { if (!result) Console.WriteLine ($"Could not save movie to photo library: {err}"); cleanup (); }); } else { cleanup (); } }); } else { cleanup (); } // Enable the Camera and Record buttons to let the user switch camera and start another recording DispatchQueue.MainQueue.DispatchAsync (() => { // Only enable the ability to change camera if the device has more than one camera CameraButton.Enabled = (AVCaptureDevice.DevicesWithMediaType (AVMediaType.Video).Length > 1); RecordButton.Enabled = CaptureModeControl.SelectedSegment == (int)CaptureMode.Movie; RecordButton.SetTitle ("Record", UIControlState.Normal); CaptureModeControl.Enabled = true; }); }
public override void DidStartRecording(AVCaptureFileOutput captureOutput, NSUrl outputFileUrl, NSObject[] connections) { _didStart?.Invoke(); }
public void FinishedRecording(AVCaptureFileOutput captureOutput, NSUrl outputFileUrl, NSObject[] connections, NSError error) { }
public void FinishedRecording (AVCaptureFileOutput captureOutput, NSUrl outputFileUrl, NSObject[] connections, NSError error) { // Note that currentBackgroundRecordingID is used to end the background task associated with this recording. // This allows a new recording to be started, associated with a new UIBackgroundTaskIdentifier, once the movie file output's isRecording property // is back to NO — which happens sometime after this method returns. // Note: Since we use a unique file path for each recording, a new recording will not overwrite a recording currently being saved. var currentBackgroundRecordingID = backgroundRecordingID; backgroundRecordingID = -1; Action cleanup = () => { NSError err; NSFileManager.DefaultManager.Remove (outputFileUrl, out err); if (currentBackgroundRecordingID != -1) UIApplication.SharedApplication.EndBackgroundTask (currentBackgroundRecordingID); }; bool success = true; if (error != null) { Console.WriteLine ("Movie file finishing error: {0}", error); success = ((NSNumber)error.UserInfo [AVErrorKeys.RecordingSuccessfullyFinished]).BoolValue; } if (!success) { cleanup (); return; } // Check authorization status. PHPhotoLibrary.RequestAuthorization (status => { if (status == PHAuthorizationStatus.Authorized) { // Save the movie file to the photo library and cleanup. PHPhotoLibrary.SharedPhotoLibrary.PerformChanges (() => { // In iOS 9 and later, it's possible to move the file into the photo library without duplicating the file data. // This avoids using double the disk space during save, which can make a difference on devices with limited free disk space. if (UIDevice.CurrentDevice.CheckSystemVersion (9, 0)) { var options = new PHAssetResourceCreationOptions { ShouldMoveFile = true }; var changeRequest = PHAssetCreationRequest.CreationRequestForAsset (); changeRequest.AddResource (PHAssetResourceType.Video, outputFileUrl, options); } else { PHAssetChangeRequest.FromVideo (outputFileUrl); } }, (success2, error2) => { if (!success2) Console.WriteLine ("Could not save movie to photo library: {0}", error2); cleanup (); }); } else { cleanup (); } }); }
public void FinishedRecording(AVCaptureFileOutput captureOutput, NSUrl outputFileUrl, NSObject[] connections, NSError error) { // Note that currentBackgroundRecordingID is used to end the background task associated with this recording. // This allows a new recording to be started, associated with a new UIBackgroundTaskIdentifier, once the movie file output's isRecording property // is back to NO — which happens sometime after this method returns. // Note: Since we use a unique file path for each recording, a new recording will not overwrite a recording currently being saved. var currentBackgroundRecordingID = backgroundRecordingID; backgroundRecordingID = -1; Action cleanup = () => { NSError err; NSFileManager.DefaultManager.Remove(outputFileUrl, out err); if (currentBackgroundRecordingID != -1) { UIApplication.SharedApplication.EndBackgroundTask(currentBackgroundRecordingID); } }; bool success = true; if (error != null) { Console.WriteLine("Movie file finishing error: {0}", error); success = ((NSNumber)error.UserInfo [AVErrorKeys.RecordingSuccessfullyFinished]).BoolValue; } if (!success) { cleanup(); return; } // Check authorization status. PHPhotoLibrary.RequestAuthorization(status => { if (status == PHAuthorizationStatus.Authorized) { // Save the movie file to the photo library and cleanup. PHPhotoLibrary.SharedPhotoLibrary.PerformChanges(() => { // In iOS 9 and later, it's possible to move the file into the photo library without duplicating the file data. // This avoids using double the disk space during save, which can make a difference on devices with limited free disk space. if (UIDevice.CurrentDevice.CheckSystemVersion(9, 0)) { var options = new PHAssetResourceCreationOptions { ShouldMoveFile = true }; var changeRequest = PHAssetCreationRequest.CreationRequestForAsset(); changeRequest.AddResource(PHAssetResourceType.Video, outputFileUrl, options); } else { PHAssetChangeRequest.FromVideo(outputFileUrl); } }, (success2, error2) => { if (!success2) { Console.WriteLine("Could not save movie to photo library: {0}", error2); } cleanup(); }); } else { cleanup(); } }); }