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);
});
}