예제 #1
0
        void UpdateDeviceFocus(AVCaptureFocusMode focusMode, AVCaptureExposureMode exposureMode, CGPoint point, bool monitorSubjectAreaChange)
        {
            SessionQueue.DispatchAsync(() => {
                if (VideoDeviceInput == null)
                {
                    return;
                }

                AVCaptureDevice device = VideoDeviceInput.Device;
                NSError error;
                if (device.LockForConfiguration(out error))
                {
                    // Setting (Focus/Exposure)PointOfInterest alone does not initiate a (focus/exposure) operation.
                    // Set (Focus/Exposure)Mode to apply the new point of interest.
                    if (device.FocusPointOfInterestSupported && device.IsFocusModeSupported(focusMode))
                    {
                        device.FocusPointOfInterest = point;
                        device.FocusMode            = focusMode;
                    }
                    if (device.ExposurePointOfInterestSupported && device.IsExposureModeSupported(exposureMode))
                    {
                        device.ExposurePointOfInterest = point;
                        device.ExposureMode            = exposureMode;
                    }
                    device.SubjectAreaChangeMonitoringEnabled = monitorSubjectAreaChange;
                    device.UnlockForConfiguration();
                }
                else
                {
                    Console.WriteLine("Could not lock device for configuration: {0}", error);
                }
            });
        }
예제 #2
0
        void ChangeCamera(CameraViewController sender)
        {
            CameraButton.Enabled = false;
            RecordButton.Enabled = false;
            StillButton.Enabled  = false;

            SessionQueue.DispatchAsync(() => {
                AVCaptureDevice currentVideoDevice        = VideoDeviceInput.Device;
                AVCaptureDevicePosition preferredPosition = AVCaptureDevicePosition.Unspecified;
                AVCaptureDevicePosition currentPosition   = currentVideoDevice.Position;

                switch (currentPosition)
                {
                case AVCaptureDevicePosition.Unspecified:
                case AVCaptureDevicePosition.Front:
                    preferredPosition = AVCaptureDevicePosition.Back;
                    break;

                case AVCaptureDevicePosition.Back:
                    preferredPosition = AVCaptureDevicePosition.Front;
                    break;
                }
                AVCaptureDevice videoDevice           = CreateDevice(AVMediaType.Video, preferredPosition);
                AVCaptureDeviceInput videoDeviceInput = AVCaptureDeviceInput.FromDevice(videoDevice);

                Session.BeginConfiguration();

                // Remove the existing device input first, since using the front and back camera simultaneously is not supported.
                Session.RemoveInput(VideoDeviceInput);

                if (Session.CanAddInput(videoDeviceInput))
                {
                    subjectSubscriber.Dispose();

                    SetFlashModeForDevice(AVCaptureFlashMode.Auto, videoDevice);
                    subjectSubscriber = NSNotificationCenter.DefaultCenter.AddObserver(AVCaptureDevice.SubjectAreaDidChangeNotification, SubjectAreaDidChange, videoDevice);

                    Session.AddInput(videoDeviceInput);
                    VideoDeviceInput = videoDeviceInput;
                }
                else
                {
                    Session.AddInput(VideoDeviceInput);
                }

                AVCaptureConnection connection = MovieFileOutput.ConnectionFromMediaType(AVMediaType.Video);
                if (connection.SupportsVideoStabilization)
                {
                    connection.PreferredVideoStabilizationMode = AVCaptureVideoStabilizationMode.Auto;
                }

                Session.CommitConfiguration();

                DispatchQueue.MainQueue.DispatchAsync(() => {
                    CameraButton.Enabled = true;
                    RecordButton.Enabled = true;
                    StillButton.Enabled  = true;
                });
            });
        }
예제 #3
0
        void ResumeInterruptedSession(CameraViewController sender)
        {
            SessionQueue.DispatchAsync(() => {
                // The session might fail to start running, e.g., if a phone or FaceTime call is still using audio or video.
                // A failure to start the session running will be communicated via a session runtime error notification.
                // To avoid repeatedly failing to start the session running, we only try to restart the session running in the
                // session runtime error handler if we aren't trying to resume the session running.

                Session.StartRunning();
                SessionRunning = Session.Running;
                if (!Session.Running)
                {
                    DispatchQueue.MainQueue.DispatchAsync(() => {
                        const string message = "Unable to resume";
                        UIAlertController alertController = UIAlertController.Create("AVCam", message, UIAlertControllerStyle.Alert);
                        UIAlertAction cancelAction        = UIAlertAction.Create("OK", UIAlertActionStyle.Cancel, null);
                        alertController.AddAction(cancelAction);
                        PresentViewController(alertController, true, null);
                    });
                }
                else
                {
                    DispatchQueue.MainQueue.DispatchAsync(() => {
                        ResumeButton.Hidden = true;
                    });
                }
            });
        }
예제 #4
0
        void SessionRuntimeError(NSNotification notification)
        {
            var error = (NSError)notification.UserInfo [AVCaptureSession.ErrorKey];

            Console.WriteLine("Capture session runtime error: {0}", error);

            // Automatically try to restart the session running if media services were reset and the last start running succeeded.
            // Otherwise, enable the user to try to resume the session running.
            if (error.Code == (int)AVError.MediaServicesWereReset)
            {
                SessionQueue.DispatchAsync(() => {
                    if (SessionRunning)
                    {
                        Session.StartRunning();
                        SessionRunning = Session.Running;
                    }
                    else
                    {
                        DispatchQueue.MainQueue.DispatchAsync(() => {
                            ResumeButton.Hidden = false;
                        });
                    }
                });
            }
            else
            {
                ResumeButton.Hidden = false;
            }
        }
예제 #5
0
 public override void ViewDidDisappear(bool animated)
 {
     SessionQueue.DispatchAsync(() => {
         if (SetupResult == AVCamSetupResult.Success)
         {
             Session.StopRunning();
             RemoveObservers();
         }
     });
     base.ViewDidDisappear(animated);
 }
예제 #6
0
        public override void ViewWillAppear(bool animated)
        {
            base.ViewWillAppear(animated);
            SessionQueue.DispatchAsync(() => {
                switch (SetupResult)
                {
                // Only setup observers and start the session running if setup succeeded.
                case AVCamSetupResult.Success:
                    AddObservers();
                    Session.StartRunning();
                    SessionRunning = Session.Running;
                    break;

                case AVCamSetupResult.CameraNotAuthorized:
                    DispatchQueue.MainQueue.DispatchAsync(() => {
                        string message = "AVCam doesn't have permission to use the camera, please change privacy settings";
                        UIAlertController alertController = UIAlertController.Create("AVCam", message, UIAlertControllerStyle.Alert);
                        UIAlertAction cancelAction        = UIAlertAction.Create("OK", UIAlertActionStyle.Cancel, null);
                        alertController.AddAction(cancelAction);
                        // Provide quick access to Settings.
                        UIAlertAction settingsAction = UIAlertAction.Create("Settings", UIAlertActionStyle.Default, action => {
                            UIApplication.SharedApplication.OpenUrl(new NSUrl(UIApplication.OpenSettingsUrlString));
                        });
                        alertController.AddAction(settingsAction);
                        PresentViewController(alertController, true, null);
                    });
                    break;

                case AVCamSetupResult.SessionConfigurationFailed:
                    DispatchQueue.MainQueue.DispatchAsync(() => {
                        string message = "Unable to capture media";
                        UIAlertController alertController = UIAlertController.Create("AVCam", message, UIAlertControllerStyle.Alert);
                        UIAlertAction cancelAction        = UIAlertAction.Create("OK", UIAlertActionStyle.Cancel, null);
                        alertController.AddAction(cancelAction);
                        PresentViewController(alertController, true, null);
                    });
                    break;
                }
            });
        }
예제 #7
0
        void ToggleMovieRecording(CameraViewController sender)
        {
            // Disable the Camera button until recording finishes, and disable the Record button until recording starts or finishes.
            CameraButton.Enabled = false;
            RecordButton.Enabled = false;

            SessionQueue.DispatchAsync(() => {
                if (!MovieFileOutput.Recording)
                {
                    if (UIDevice.CurrentDevice.IsMultitaskingSupported)
                    {
                        // Setup background task. This is needed because the IAVCaptureFileOutputRecordingDelegate.FinishedRecording
                        // callback is not received until AVCam returns to the foreground unless you request background execution time.
                        // This also ensures that there will be time to write the file to the photo library when AVCam is backgrounded.
                        // To conclude this background execution, UIApplication.SharedApplication.EndBackgroundTask is called in
                        // IAVCaptureFileOutputRecordingDelegate.FinishedRecording after the recorded file has been saved.
                        backgroundRecordingID = UIApplication.SharedApplication.BeginBackgroundTask(null);
                    }

                    // Update the orientation on the movie file output video connection before starting recording.
                    AVCaptureConnection connection = MovieFileOutput.ConnectionFromMediaType(AVMediaType.Video);
                    var previewLayer            = (AVCaptureVideoPreviewLayer)PreviewView.Layer;
                    connection.VideoOrientation = previewLayer.Connection.VideoOrientation;

                    // Turn OFF flash for video recording.
                    SetFlashModeForDevice(AVCaptureFlashMode.Off, VideoDeviceInput.Device);

                    // Start recording to a temporary file.
                    MovieFileOutput.StartRecordingToOutputFile(new NSUrl(GetTmpFilePath("mov"), false), this);
                }
                else
                {
                    MovieFileOutput.StopRecording();
                }
            });
        }
예제 #8
0
        void SnapStillImage(CameraViewController sender)
        {
            SessionQueue.DispatchAsync(async() => {
                AVCaptureConnection connection = StillImageOutput.ConnectionFromMediaType(AVMediaType.Video);
                var previewLayer = (AVCaptureVideoPreviewLayer)PreviewView.Layer;

                // Update the orientation on the still image output video connection before capturing.
                connection.VideoOrientation = previewLayer.Connection.VideoOrientation;

                // Flash set to Auto for Still Capture.
                SetFlashModeForDevice(AVCaptureFlashMode.Auto, VideoDeviceInput.Device);

                // Capture a still image.
                try {
                    var imageDataSampleBuffer = await StillImageOutput.CaptureStillImageTaskAsync(connection);

                    // The sample buffer is not retained. Create image data before saving the still image to the photo library asynchronously.
                    NSData imageData = AVCaptureStillImageOutput.JpegStillToNSData(imageDataSampleBuffer);

                    PHPhotoLibrary.RequestAuthorization(status => {
                        if (status == PHAuthorizationStatus.Authorized)
                        {
                            // To preserve the metadata, we create an asset from the JPEG NSData representation.
                            // Note that creating an asset from a UIImage discards the metadata.

                            // In iOS 9, we can use AddResource method on PHAssetCreationRequest class.
                            // In iOS 8, we save the image to a temporary file and use +[PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL:].

                            if (UIDevice.CurrentDevice.CheckSystemVersion(9, 0))
                            {
                                PHPhotoLibrary.SharedPhotoLibrary.PerformChanges(() => {
                                    var request = PHAssetCreationRequest.CreationRequestForAsset();
                                    request.AddResource(PHAssetResourceType.Photo, imageData, null);
                                }, (success, err) => {
                                    if (!success)
                                    {
                                        Console.WriteLine("Error occurred while saving image to photo library: {0}", err);
                                    }
                                });
                            }
                            else
                            {
                                var temporaryFileUrl = new NSUrl(GetTmpFilePath("jpg"), false);
                                PHPhotoLibrary.SharedPhotoLibrary.PerformChanges(() => {
                                    NSError error = null;
                                    if (imageData.Save(temporaryFileUrl, NSDataWritingOptions.Atomic, out error))
                                    {
                                        PHAssetChangeRequest.FromImage(temporaryFileUrl);
                                    }
                                    else
                                    {
                                        Console.WriteLine("Error occured while writing image data to a temporary file: {0}", error);
                                    }
                                }, (success, error) => {
                                    if (!success)
                                    {
                                        Console.WriteLine("Error occurred while saving image to photo library: {0}", error);
                                    }

                                    // Delete the temporary file.
                                    NSError deleteError;
                                    NSFileManager.DefaultManager.Remove(temporaryFileUrl, out deleteError);
                                });
                            }
                        }
                    });
                } catch (NSErrorException ex) {
                    Console.WriteLine("Could not capture still image: {0}", ex.Error);
                }
            });
        }