2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using System.Collections.Generic;
19 using System.Diagnostics;
21 using System.Runtime.InteropServices;
22 using System.Threading;
24 using Native = Interop.Camera;
26 namespace Tizen.Multimedia
28 static internal class CameraLog
30 internal const string Tag = "Tizen.Multimedia.Camera";
31 internal const string Enter = "[Enter]";
32 internal const string Leave = "[Leave]";
36 /// The camera class provides methods to capture photos and support setting up notifications
37 /// for state changes of capturing, previewing, focusing, information about resolution and binary format
38 /// and functions for picture manipulations like sepia negative and many more.
39 /// It also notifies you when a significant picture parameter changes e.g. focus.
41 public class Camera : IDisposable, IDisplayable<CameraError>
43 private IntPtr _handle = IntPtr.Zero;
44 private bool _disposed = false;
45 private CameraState _state = CameraState.None;
48 /// Initializes a new instance of the <see cref="Camera"/> Class.
50 /// <since_tizen> 3 </since_tizen>
51 /// <param name="device">The camera device to access</param>
52 public Camera(CameraDevice device)
54 CameraErrorFactory.ThrowIfError(Native.Create(device, out _handle),
55 "Failed to create camera instance");
57 Capabilities = new CameraCapabilities(this);
58 Settings = new CameraSettings(this);
59 DisplaySettings = new CameraDisplaySettings(this);
63 SetState(CameraState.Created);
67 /// Destructor of the camera class.
74 public IntPtr Handle => GetHandle();
76 internal IntPtr GetHandle()
78 ValidateNotDisposed();
82 #region Dispose support
84 /// Releases the unmanaged resources used by the Camera.
86 /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
87 protected virtual void Dispose(bool disposing)
93 // to be used if there are any other disposable objects
96 if (_handle != IntPtr.Zero)
98 Native.Destroy(_handle);
99 _handle = IntPtr.Zero;
107 /// Releases all resources used by the Camera.
109 /// <since_tizen> 3 </since_tizen>
110 public void Dispose()
112 ReplaceDisplay(null);
114 GC.SuppressFinalize(this);
117 internal void ValidateNotDisposed()
121 Log.Error(CameraLog.Tag, "Camera handle is disposed.");
122 throw new ObjectDisposedException(nameof(Camera));
125 #endregion Dispose support
127 #region Check camera state
128 internal void ValidateState(params CameraState[] required)
130 ValidateNotDisposed();
132 Debug.Assert(required.Length > 0);
134 var curState = _state;
135 if (!required.Contains(curState))
137 throw new InvalidOperationException($"The camera is not in a valid state. " +
138 $"Current State : { curState }, Valid State : { string.Join(", ", required) }.");
142 internal void SetState(CameraState state)
146 #endregion Check camera state
148 #region EventHandlers
150 /// Event that occurs when the camera interrupt is started by policy.
152 public event EventHandler<CameraInterruptStartedEventArgs> InterruptStarted;
153 private Native.InterruptStartedCallback _interruptStartedCallback;
156 /// Event that occurs when an camera is interrupted by policy.
158 /// <since_tizen> 3 </since_tizen>
159 public event EventHandler<CameraInterruptedEventArgs> Interrupted;
160 private Native.InterruptedCallback _interruptedCallback;
163 /// Event that occurs when there is an asynchronous error.
165 /// <since_tizen> 3 </since_tizen>
166 public event EventHandler<CameraErrorOccurredEventArgs> ErrorOccurred;
167 private Native.ErrorCallback _errorCallback;
170 /// Event that occurs when the auto focus state is changed.
172 /// <since_tizen> 3 </since_tizen>
173 public event EventHandler<CameraFocusStateChangedEventArgs> FocusStateChanged;
174 private Native.FocusStateChangedCallback _focusStateChangedCallback;
177 /// Event that occurs when a face is detected in preview frame.
179 /// <since_tizen> 3 </since_tizen>
180 public event EventHandler<FaceDetectedEventArgs> FaceDetected;
181 private Native.FaceDetectedCallback _faceDetectedCallback;
184 /// Event that occurs during capture of image.
186 /// <since_tizen> 3 </since_tizen>
187 public event EventHandler<CameraCapturingEventArgs> Capturing;
188 private Native.CapturingCallback _capturingCallback;
191 /// Event that occurs after the capture of the image.
193 /// <since_tizen> 3 </since_tizen>
194 public event EventHandler<EventArgs> CaptureCompleted;
195 private Native.CaptureCompletedCallback _captureCompletedCallback;
197 private Native.HdrCaptureProgressCallback _hdrCaptureProgressCallback;
198 private event EventHandler<HdrCaptureProgressEventArgs> _hdrCaptureProgress;
199 private object _hdrCaptureProgressEventLock = new object();
202 /// Event that occurs when there is change in HDR capture progress.
203 /// Check whether <see cref="CameraCapabilities.IsHdrCaptureSupported"/> is supported or not before add this EventHandler.
205 /// <since_tizen> 3 </since_tizen>
206 /// <exception cref="NotSupportedException">In case of HDR feature is not supported.</exception>
207 public event EventHandler<HdrCaptureProgressEventArgs> HdrCaptureProgress
211 lock (_hdrCaptureProgressEventLock)
213 if (_hdrCaptureProgress == null)
215 RegisterHdrCaptureProgress();
218 _hdrCaptureProgress += value;
224 lock (_hdrCaptureProgressEventLock)
226 _hdrCaptureProgress -= value;
228 if (_hdrCaptureProgress == null)
230 UnregisterHdrCaptureProgress();
237 /// Event that occurs when camera state is changed.
239 /// <since_tizen> 3 </since_tizen>
240 public event EventHandler<CameraStateChangedEventArgs> StateChanged;
241 private Native.StateChangedCallback _stateChangedCallback;
243 private static Native.DeviceStateChangedCallback _deviceStateChangedCallback;
244 private static event EventHandler<CameraDeviceStateChangedEventArgs> _deviceStateChanged;
245 private static object _deviceStateChangedEventLock = new object();
246 private static int _deviceStateCallbackId;
249 /// Event that occurs after the <see cref="CameraDeviceState"/> is changed.
251 /// <since_tizen> 3 </since_tizen>
252 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
253 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
254 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
255 public static event EventHandler<CameraDeviceStateChangedEventArgs> DeviceStateChanged
259 lock (_deviceStateChangedEventLock)
261 if (_deviceStateChanged == null)
263 RegisterDeviceStateChangedCallback();
266 _deviceStateChanged += value;
272 lock (_deviceStateChangedEventLock)
274 _deviceStateChanged -= value;
276 if (_deviceStateChanged == null)
278 UnregisterDeviceStateChangedCallback();
284 private Native.PreviewCallback _previewCallback;
285 private event EventHandler<PreviewEventArgs> _preview;
286 private object _previewEventLock = new object();
288 /// Event that occurs once per frame when previewing.
289 /// Preview callback is registered when user add callback explicitly to avoid useless P/Invoke.
291 /// <since_tizen> 3 </since_tizen>
292 public event EventHandler<PreviewEventArgs> Preview
296 lock (_previewEventLock)
298 if (_preview == null)
300 RegisterPreviewCallback();
309 lock (_previewEventLock)
313 if (_preview == null)
315 UnregisterPreviewCallback();
321 private Native.MediaPacketPreviewCallback _mediaPacketPreviewCallback;
322 private EventHandler<MediaPacketPreviewEventArgs> _mediaPacketPreview;
323 private object _mediaPacketPreviewEventLock = new object();
326 /// Event that occurs once per frame when previewing.
327 /// Preview callback is registered when user add callback explicitly to avoid useless P/Invoke.
329 /// <since_tizen> 3 </since_tizen>
330 public event EventHandler<MediaPacketPreviewEventArgs> MediaPacketPreview
334 lock (_mediaPacketPreviewEventLock)
336 if (_mediaPacketPreview == null)
338 RegisterMediaPacketPreviewCallback();
341 _mediaPacketPreview += value;
347 lock (_mediaPacketPreviewEventLock)
349 _mediaPacketPreview -= value;
351 if (_mediaPacketPreview == null)
353 UnregisterMediaPacketPreviewCallback();
358 #endregion EventHandlers
362 /// Get/Set the various camera settings.
364 /// <since_tizen> 3 </since_tizen>
365 public CameraSettings Settings { get; }
368 /// Gets the various camera capabilities.
370 /// <since_tizen> 3 </since_tizen>
371 public CameraCapabilities Capabilities { get; }
374 /// Get/set various camera display properties.
376 /// <since_tizen> 3 </since_tizen>
377 public CameraDisplaySettings DisplaySettings{ get; }
379 private Display _display;
381 private CameraError SetDisplay(Display display)
385 return CameraDisplay.SetTarget(GetHandle(), DisplayType.None, IntPtr.Zero);
388 return display.ApplyTo(this);
391 private void ReplaceDisplay(Display newDisplay)
393 _display?.SetOwner(null);
394 _display = newDisplay;
395 _display?.SetOwner(this);
399 /// Sets or gets the display type and handle to show preview images.
400 /// The camera must be in the <see cref="CameraState.Created"/> state.
402 /// <since_tizen> 3 </since_tizen>
404 /// This must be set before StartPreview() method.
405 /// In Custom ROI display mode, DisplayRoiArea property must be set before calling this method.
407 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
408 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
409 /// <exception cref="ObjectDisposedException" > The camera already has been disposed.</exception>
410 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
411 public Display Display
420 ValidateState(CameraState.Created);
422 if (value?.Owner != null)
424 if (ReferenceEquals(this, value.Owner))
429 throw new ArgumentException("The display has already been assigned to another.");
432 CameraErrorFactory.ThrowIfError(SetDisplay(value), "Failed to set the camera display");
434 ReplaceDisplay(value);
438 CameraError IDisplayable<CameraError>.ApplyEvasDisplay(DisplayType type, ElmSharp.EvasObject evasObject)
440 Debug.Assert(_disposed == false);
441 ValidationUtil.ValidateEnum(typeof(DisplayType), type, nameof(type));
443 return CameraDisplay.SetTarget(GetHandle(), type, evasObject);
447 /// Gets the state of the camera.
449 /// <since_tizen> 3 </since_tizen>
450 /// <value> None, Created, Preview, Capturing, Captured </value>
451 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
452 public CameraState State
456 ValidateNotDisposed();
458 CameraState val = CameraState.None;
459 CameraErrorFactory.ThrowIfError(Native.GetState(_handle, out val),
460 "Failed to get camera state");
467 /// The hint for display reuse.
468 /// If the hint is set to true, the display will be reused when the camera device is changed with
469 /// ChangeDevice method.
471 /// <since_tizen> 3 </since_tizen>
472 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
473 /// <exception cref="InvalidOperationException">Invalid state.</exception>
474 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
475 public bool DisplayReuseHint
479 ValidateNotDisposed();
481 CameraErrorFactory.ThrowIfError(Native.GetDisplayReuseHint(_handle, out bool val),
482 "Failed to get camera display reuse hint");
489 ValidateState(CameraState.Preview);
491 CameraErrorFactory.ThrowIfError(Native.SetDisplayReuseHint(_handle, value),
492 "Failed to set display reuse hint.");
497 /// Gets the facing direction of camera module.
499 /// <since_tizen> 3 </since_tizen>
500 /// <value>A <see cref="CameraFacingDirection"/> that specifies the facing direction of camera device.</value>
501 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
502 public CameraFacingDirection Direction
506 ValidateNotDisposed();
508 CameraErrorFactory.ThrowIfError(Native.GetFacingDirection(_handle, out var val),
509 "Failed to get camera direction");
516 /// Gets the camera device count.
518 /// <since_tizen> 3 </since_tizen>
519 /// <value>This returns 2, if the device supports primary and secondary cameras.
520 /// Otherwise 1, if the device only supports primary camera.</value>
521 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
522 public int CameraCount
526 ValidateNotDisposed();
528 CameraErrorFactory.ThrowIfError(Native.GetDeviceCount(_handle, out int val),
529 "Failed to get camera device count");
534 #endregion Properties
538 /// Changes the camera device.
540 /// <since_tizen> 3 </since_tizen>
541 /// <param name="device">The hardware camera to access.</param>
543 /// If display reuse is set using <see cref="DisplayReuseHint"/>
544 /// before stopping the preview, the display will be reused and last frame on the display
545 /// can be kept even though camera device is changed.
546 /// The camera must be in the <see cref="CameraState.Created"/>.
548 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
549 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
550 /// <exception cref="NotSupportedException">In case of ChangeDevice feature is not supported.</exception>
551 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
552 public void ChangeDevice(CameraDevice device)
554 ValidateState(CameraState.Created);
555 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
557 CameraErrorFactory.ThrowIfError(Native.ChangeDevice(_handle, device),
558 "Failed to change the camera device");
562 /// Gets the device state.
564 /// <since_tizen> 3 </since_tizen>
565 /// <param name="device">The device to get state.</param>
566 /// <returns>Returns the state of camera device</returns>
567 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
568 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
569 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
570 public static CameraDeviceState GetDeviceState(CameraDevice device)
572 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
574 CameraErrorFactory.ThrowIfError(Native.GetDeviceState(device, out var val),
575 "Failed to get the camera device state.");
581 /// Gets the flash state.
583 /// <since_tizen> 3 </since_tizen>
584 /// <param name="device">The device to get state.</param>
585 /// <returns>Returns the flash state of camera device</returns>
586 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
587 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
588 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
589 public static CameraFlashState GetFlashState(CameraDevice device)
591 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
593 CameraErrorFactory.ThrowIfError(Native.GetFlashState(device, out var val),
594 "Failed to get camera flash state");
600 /// Starts capturing and drawing preview frames on the screen.
601 /// The display property must be set using <see cref="Display"/> before using this method.
602 /// If needed set fps <see cref="CameraSettings.PreviewFps"/>, preview resolution
603 /// <see cref="CameraSettings.PreviewResolution"/>, or preview format <see cref="CameraSettings.PreviewPixelFormat"/>
604 /// before using this method.
605 /// The camera must be in the <see cref="CameraState.Created"/> or <see cref="CameraState.Captured"/> state.
607 /// <since_tizen> 3 </since_tizen>
609 /// http://tizen.org/privilege/camera
611 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
612 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
613 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
614 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
615 public void StartPreview()
617 ValidateState(CameraState.Created, CameraState.Captured);
619 CameraErrorFactory.ThrowIfError(Native.StartPreview(_handle),
620 "Failed to start the camera preview.");
622 // Update by StateChangedCallback can be delayed for dozens of milliseconds.
623 SetState(CameraState.Preview);
627 /// Stops capturing and drawing preview frames on the screen.
628 /// The camera must be in the <see cref="CameraState.Preview"/> state.
630 /// <since_tizen> 3 </since_tizen>
632 /// http://tizen.org/privilege/camera
634 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
635 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
636 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
637 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
638 public void StopPreview()
640 ValidateState(CameraState.Preview);
642 CameraErrorFactory.ThrowIfError(Native.StopPreview(_handle),
643 "Failed to stop the camera preview.");
645 SetState(CameraState.Created);
649 /// Starts capturing of still images.
650 /// EventHandler must be set for capturing using <see cref="Capturing"/>
651 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
652 /// The camera must be in the <see cref="CameraState.Preview"/> state.
654 /// <since_tizen> 3 </since_tizen>
656 /// http://tizen.org/privilege/camera
659 /// This function causes the transition of the camera state from Capturing to Captured
660 /// automatically and the corresponding EventHandlers will be invoked.
661 /// The preview should be restarted by calling <see cref="StartPreview"/> method after capture is completed.
663 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
664 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
665 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
666 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
667 public void StartCapture()
669 ValidateState(CameraState.Preview);
671 CameraErrorFactory.ThrowIfError(Native.StartCapture(_handle, _capturingCallback, _captureCompletedCallback, IntPtr.Zero),
672 "Failed to start the camera capture.");
674 SetState(CameraState.Capturing);
678 /// Starts continuously capturing still images.
679 /// EventHandler must be set for capturing using <see cref="Capturing"/>
680 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
681 /// The camera must be in the <see cref="CameraState.Preview"/> state.
683 /// <since_tizen> 3 </since_tizen>
685 /// http://tizen.org/privilege/camera
687 /// <param name="count">The number of still images.</param>
688 /// <param name="interval">The interval of the capture(milliseconds).</param>
689 /// <param name="cancellationToken">The cancellation token to cancel capturing.</param>
690 /// <seealso cref="CancellationToken"/>
692 /// If this is not supported zero shutter lag occurs. The capture resolution could be
693 /// changed to the preview resolution. This function causes the transition of the camera state
694 /// from Capturing to Captured automatically and the corresponding Eventhandlers will be invoked.
695 /// Each captured image will be delivered through Eventhandler set using <see cref="Capturing"/> event.
696 /// The preview should be restarted by calling <see cref="StartPreview"/> method after capture is completed.
698 /// <exception cref="ArgumentOutOfRangeException">In case of invalid parameters.</exception>
699 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
700 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
701 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
702 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
703 public void StartCapture(int count, int interval, CancellationToken cancellationToken)
705 ValidateState(CameraState.Preview);
709 throw new ArgumentOutOfRangeException(nameof(count), count, $"{nameof(count)} should be greater than one.");
714 throw new ArgumentOutOfRangeException(nameof(interval), interval, $"{nameof(interval)} should be greater than or equal to zero.");
717 //Handle CancellationToken
718 if (cancellationToken != CancellationToken.None)
720 cancellationToken.Register(() =>
722 CameraErrorFactory.ThrowIfError(Native.StopContinuousCapture(_handle),
723 "Failed to cancel the continuous capture");
724 SetState(CameraState.Captured);
728 CameraErrorFactory.ThrowIfError(Native.StartContinuousCapture(_handle, count, interval,
729 _capturingCallback, _captureCompletedCallback, IntPtr.Zero), "Failed to start the continuous capture.");
731 SetState(CameraState.Capturing);
735 /// Starts camera auto-focusing, asynchronously.
736 /// The camera must be in the <see cref="CameraState.Preview"/> or <see cref="CameraState.Captured"/> state.
738 /// <since_tizen> 3 </since_tizen>
739 /// <param name="continuous">Continuous auto focus</param>
741 /// http://tizen.org/privilege/camera
744 /// If continuous status is true, the camera continuously tries to focus.
746 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
747 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
748 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
749 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
750 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
751 public void StartFocusing(bool continuous)
753 ValidateState(CameraState.Preview, CameraState.Captured);
755 CameraErrorFactory.ThrowIfError(Native.StartFocusing(_handle, continuous),
756 "Failed to cancel the camera focus.");
760 /// Stops camera auto focusing.
761 /// The camera must be in the <see cref="CameraState.Preview"/> or <see cref="CameraState.Captured"/> state.
763 /// <since_tizen> 3 </since_tizen>
765 /// http://tizen.org/privilege/camera
767 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
768 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
769 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
770 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
771 public void StopFocusing()
773 ValidateState(CameraState.Preview, CameraState.Captured);
775 CameraErrorFactory.ThrowIfError(Native.CancelFocusing(_handle),
776 "Failed to cancel the camera focus.");
780 /// Starts face detection.
781 /// The camera must be in the <see cref="CameraState.Preview"/> state.
783 /// <since_tizen> 3 </since_tizen>
785 /// http://tizen.org/privilege/camera
788 /// This should be called after <see cref="StartPreview"/> is started.
789 /// The Eventhandler set using <see cref="FaceDetected"/> invoked when the face is detected in preview frame.
790 /// Internally it starts continuous focus and focusing on the detected face.
792 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
793 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
794 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
795 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
796 public void StartFaceDetection()
798 ValidateState(CameraState.Preview);
800 _faceDetectedCallback = (IntPtr faces, int count, IntPtr userData) =>
802 var result = new List<FaceDetectionData>();
803 IntPtr current = faces;
805 for (int i = 0; i < count; i++)
807 result.Add(new FaceDetectionData(current));
808 current = IntPtr.Add(current, Marshal.SizeOf<Native.DetectedFaceStruct>());
811 FaceDetected?.Invoke(this, new FaceDetectedEventArgs(result));
813 CameraErrorFactory.ThrowIfError(Native.StartFaceDetection(_handle, _faceDetectedCallback, IntPtr.Zero),
814 "Failed to start face detection");
818 /// Stops face detection.
820 /// <since_tizen> 3 </since_tizen>
822 /// http://tizen.org/privilege/camera
824 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
825 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
826 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
827 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
828 public void StopFaceDetection()
830 if (_faceDetectedCallback == null)
832 throw new InvalidOperationException("The face detection is not started.");
835 CameraErrorFactory.ThrowIfError(Native.StopFaceDetection(_handle),
836 "Failed to stop the face detection.");
838 _faceDetectedCallback = null;
842 #region Callback registrations
843 private void RegisterCallbacks()
845 RegisterErrorCallback();
846 RegisterFocusStateChanged();
847 RegisterInterruptStartedCallback();
848 RegisterInterruptedCallback();
849 RegisterStateChangedCallback();
851 //Define capturing callback
852 _capturingCallback = (IntPtr main, IntPtr postview, IntPtr thumbnail, IntPtr userData) =>
854 Capturing?.Invoke(this, new CameraCapturingEventArgs(new StillImage(main),
855 postview == IntPtr.Zero ? null : new StillImage(postview),
856 thumbnail == IntPtr.Zero ? null : new StillImage(thumbnail)));
859 //Define captureCompleted callback
860 _captureCompletedCallback = _ =>
862 SetState(CameraState.Captured);
863 CaptureCompleted?.Invoke(this, EventArgs.Empty);
867 private void RegisterInterruptStartedCallback()
869 _interruptStartedCallback = (CameraPolicy policy, CameraState state, IntPtr userData) =>
871 InterruptStarted?.Invoke(this, new CameraInterruptStartedEventArgs(policy, state));
873 CameraErrorFactory.ThrowIfError(Native.SetInterruptStartedCallback(_handle, _interruptStartedCallback, IntPtr.Zero),
874 "Failed to set interrupt callback");
877 private void RegisterInterruptedCallback()
879 _interruptedCallback = (CameraPolicy policy, CameraState previous, CameraState current, IntPtr userData) =>
881 Interrupted?.Invoke(this, new CameraInterruptedEventArgs(policy, previous, current));
883 CameraErrorFactory.ThrowIfError(Native.SetInterruptedCallback(_handle, _interruptedCallback, IntPtr.Zero),
884 "Failed to set interrupt callback");
887 private void RegisterErrorCallback()
889 _errorCallback = (CameraErrorCode error, CameraState current, IntPtr userData) =>
891 ErrorOccurred?.Invoke(this, new CameraErrorOccurredEventArgs(error, current));
893 CameraErrorFactory.ThrowIfError(Native.SetErrorCallback(_handle, _errorCallback, IntPtr.Zero),
894 "Setting error callback failed");
897 private void RegisterStateChangedCallback()
899 _stateChangedCallback = (CameraState previous, CameraState current, bool byPolicy, IntPtr _) =>
902 Log.Info(CameraLog.Tag, "Camera state changed " + previous.ToString() + " -> " + current.ToString());
903 StateChanged?.Invoke(this, new CameraStateChangedEventArgs(previous, current, byPolicy));
905 CameraErrorFactory.ThrowIfError(Native.SetStateChangedCallback(_handle, _stateChangedCallback, IntPtr.Zero),
906 "Setting state changed callback failed");
909 private static void RegisterDeviceStateChangedCallback()
911 _deviceStateChangedCallback = (CameraDevice device, CameraDeviceState state, IntPtr userData) =>
913 _deviceStateChanged?.Invoke(null, new CameraDeviceStateChangedEventArgs(device, state));
916 CameraErrorFactory.ThrowIfError(Native.SetDeviceStateChangedCallback(_deviceStateChangedCallback, IntPtr.Zero, out _deviceStateCallbackId),
917 "Failed to set device state changed callback");
919 Log.Info(CameraLog.Tag, "add callbackId " + _deviceStateCallbackId.ToString());
922 private static void UnregisterDeviceStateChangedCallback()
924 CameraErrorFactory.ThrowIfError(Native.UnsetDeviceStateChangedCallback(_deviceStateCallbackId),
925 "Unsetting device state changed callback failed");
926 _deviceStateChangedCallback = null;
927 _deviceStateCallbackId = 0;
930 private void RegisterFocusStateChanged()
932 _focusStateChangedCallback = (CameraFocusState state, IntPtr userData) =>
934 FocusStateChanged?.Invoke(this, new CameraFocusStateChangedEventArgs(state));
936 CameraErrorFactory.ThrowIfError(Native.SetFocusStateChangedCallback(_handle, _focusStateChangedCallback, IntPtr.Zero),
937 "Setting focus changed callback failed");
940 private void RegisterHdrCaptureProgress()
942 _hdrCaptureProgressCallback = (int percent, IntPtr userData) =>
944 _hdrCaptureProgress?.Invoke(this, new HdrCaptureProgressEventArgs(percent));
946 CameraErrorFactory.ThrowIfError(Native.SetHdrCaptureProgressCallback(_handle, _hdrCaptureProgressCallback, IntPtr.Zero),
947 "Setting Hdr capture progress callback failed");
950 private void UnregisterHdrCaptureProgress()
952 CameraErrorFactory.ThrowIfError(Native.UnsetHdrCaptureProgressCallback(_handle),
953 "Unsetting hdr capture progress is failed");
954 _hdrCaptureProgressCallback = null;
957 private void RegisterPreviewCallback()
959 _previewCallback = (IntPtr frame, IntPtr userData) =>
961 _preview?.Invoke(this, new PreviewEventArgs(new PreviewFrame(frame)));
963 CameraErrorFactory.ThrowIfError(Native.SetPreviewCallback(_handle, _previewCallback, IntPtr.Zero),
964 "Setting preview callback failed");
967 private void UnregisterPreviewCallback()
969 CameraErrorFactory.ThrowIfError(Native.UnsetPreviewCallback(_handle),
970 "Unsetting preview callback failed");
971 _previewCallback = null;
974 private void RegisterMediaPacketPreviewCallback()
976 _mediaPacketPreviewCallback = (IntPtr mediaPacket, IntPtr userData) =>
978 MediaPacket packet = MediaPacket.From(mediaPacket);
979 var eventHandler = _mediaPacketPreview;
981 if (eventHandler != null)
983 eventHandler.Invoke(this, new MediaPacketPreviewEventArgs(packet));
990 CameraErrorFactory.ThrowIfError(Native.SetMediaPacketPreviewCallback(_handle, _mediaPacketPreviewCallback, IntPtr.Zero),
991 "Setting media packet preview callback failed");
994 private void UnregisterMediaPacketPreviewCallback()
996 CameraErrorFactory.ThrowIfError(Native.UnsetMediaPacketPreviewCallback(_handle),
997 "Unsetting media packet preview callback failed");
998 _mediaPacketPreviewCallback = null;
1000 #endregion Callback registrations