void CapturePhoto (UIButton photoButton) { // Retrieve the video preview layer's video orientation on the main queue before // entering the session queue. We do this to ensure UI elements are accessed on // the main thread and session configuration is done on the session queue. var videoPreviewLayerOrientation = PreviewView.VideoPreviewLayer.Connection.VideoOrientation; sessionQueue.DispatchAsync (() => { // Update the photo output's connection to match the video orientation of the video preview layer. var photoOutputConnection = photoOutput.ConnectionFromMediaType (AVMediaType.Video); if (photoOutputConnection != null) photoOutputConnection.VideoOrientation = videoPreviewLayerOrientation; // Capture a JPEG photo with flash set to auto and high resolution photo enabled. var photoSettings = AVCapturePhotoSettings.Create (); photoSettings.FlashMode = AVCaptureFlashMode.Auto; photoSettings.IsHighResolutionPhotoEnabled = true; // TODO: request strong typed API if (photoSettings.AvailablePreviewPhotoPixelFormatTypes.Length > 0) photoSettings.PreviewPhotoFormat = new NSDictionary<NSString, NSObject> (CVPixelBuffer.PixelFormatTypeKey, photoOutput.AvailablePhotoPixelFormatTypes [0]); // Live Photo capture is not supported in movie mode. if (livePhotoMode == LivePhotoMode.On && photoOutput.IsLivePhotoCaptureSupported) { var livePhotoMovieFileName = new NSUuid ().AsString (); var livePhotoMovieFilePath = Path.Combine (Path.GetTempPath (), Path.ChangeExtension (livePhotoMovieFileName, "mov")); photoSettings.LivePhotoMovieFileUrl = NSUrl.FromFilename (livePhotoMovieFilePath); } // Use a separate object for the photo capture delegate to isolate each capture life cycle. var photoCaptureDelegate = new PhotoCaptureDelegate (photoSettings, () => DispatchQueue.MainQueue.DispatchAsync (() => { PreviewView.VideoPreviewLayer.Opacity = 0; UIView.Animate (0.25, () => PreviewView.VideoPreviewLayer.Opacity = 1); }), capturing => { // Because Live Photo captures can overlap, we need to keep track of the // number of in progress Live Photo captures to ensure that the // Live Photo label stays visible during these captures. sessionQueue.DispatchAsync (() => { if (capturing) inProgressLivePhotoCapturesCount += 1; else inProgressLivePhotoCapturesCount -= 1; var count = inProgressLivePhotoCapturesCount; DispatchQueue.MainQueue.DispatchAsync (() => { if (count > 0) CapturingLivePhotoLabel.Hidden = false; else if (count == 0) CapturingLivePhotoLabel.Hidden = true; else Console.WriteLine ("Error: In progress live photo capture count is less than 0"); }); }); }, photoDelegate => { // When the capture is complete, remove a reference to the photo capture delegate so it can be deallocated. sessionQueue.DispatchAsync (() => inProgressPhotoCaptureDelegates.Remove (photoDelegate.RequestedPhotoSettings.UniqueID)); }); // The Photo Output keeps a weak reference to the photo capture delegate so // we store it in an array to maintain a strong reference to this object // until the capture is completed. inProgressPhotoCaptureDelegates [photoCaptureDelegate.RequestedPhotoSettings.UniqueID] = photoCaptureDelegate; photoOutput.CapturePhoto (photoSettings, photoCaptureDelegate); }); }
void CapturePhoto(UIButton photoButton) { // Retrieve the video preview layer's video orientation on the main queue before // entering the session queue. We do this to ensure UI elements are accessed on // the main thread and session configuration is done on the session queue. var videoPreviewLayerOrientation = PreviewView.VideoPreviewLayer.Connection.VideoOrientation; sessionQueue.DispatchAsync(() => { // Update the photo output's connection to match the video orientation of the video preview layer. var photoOutputConnection = photoOutput.ConnectionFromMediaType(AVMediaType.Video); if (photoOutputConnection != null) { photoOutputConnection.VideoOrientation = videoPreviewLayerOrientation; } // Capture a JPEG photo with flash set to auto and high resolution photo enabled. var photoSettings = AVCapturePhotoSettings.Create(); photoSettings.FlashMode = AVCaptureFlashMode.Auto; photoSettings.IsHighResolutionPhotoEnabled = true; // TODO: request strong typed API if (photoSettings.AvailablePreviewPhotoPixelFormatTypes.Length > 0) { photoSettings.PreviewPhotoFormat = new NSDictionary <NSString, NSObject> (CVPixelBuffer.PixelFormatTypeKey, photoOutput.AvailablePhotoPixelFormatTypes [0]); } // Live Photo capture is not supported in movie mode. if (livePhotoMode == LivePhotoMode.On && photoOutput.IsLivePhotoCaptureSupported) { var livePhotoMovieFileName = new NSUuid().AsString(); var livePhotoMovieFilePath = Path.Combine(Path.GetTempPath(), Path.ChangeExtension(livePhotoMovieFileName, "mov")); photoSettings.LivePhotoMovieFileUrl = NSUrl.FromFilename(livePhotoMovieFilePath); } // Use a separate object for the photo capture delegate to isolate each capture life cycle. var photoCaptureDelegate = new PhotoCaptureDelegate(photoSettings, () => DispatchQueue.MainQueue.DispatchAsync(() => { PreviewView.VideoPreviewLayer.Opacity = 0; UIView.Animate(0.25, () => PreviewView.VideoPreviewLayer.Opacity = 1); }), capturing => { // Because Live Photo captures can overlap, we need to keep track of the // number of in progress Live Photo captures to ensure that the // Live Photo label stays visible during these captures. sessionQueue.DispatchAsync(() => { if (capturing) { inProgressLivePhotoCapturesCount += 1; } else { inProgressLivePhotoCapturesCount -= 1; } var count = inProgressLivePhotoCapturesCount; DispatchQueue.MainQueue.DispatchAsync(() => { if (count > 0) { CapturingLivePhotoLabel.Hidden = false; } else if (count == 0) { CapturingLivePhotoLabel.Hidden = true; } else { Console.WriteLine("Error: In progress live photo capture count is less than 0"); } }); }); }, photoDelegate => { // When the capture is complete, remove a reference to the photo capture delegate so it can be deallocated. sessionQueue.DispatchAsync(() => inProgressPhotoCaptureDelegates.Remove(photoDelegate.RequestedPhotoSettings.UniqueID)); }); // The Photo Output keeps a weak reference to the photo capture delegate so // we store it in an array to maintain a strong reference to this object // until the capture is completed. inProgressPhotoCaptureDelegates [photoCaptureDelegate.RequestedPhotoSettings.UniqueID] = photoCaptureDelegate; photoOutput.CapturePhoto(photoSettings, photoCaptureDelegate); }); }