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="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 handle must be set using <see cref="CameraDisplaySettings.SetInfo"/>
602 /// before using this method.
603 /// If needed set fps <see cref="CameraSettings.PreviewFps"/>, preview resolution
604 /// <see cref="CameraSettings.PreviewResolution"/>, or preview format <see cref="CameraSettings.PreviewPixelFormat"/>
605 /// before using this method.
606 /// The camera must be in the <see cref="CameraState.Created"/> or <see cref="CameraState.Captured"/> state.
608 /// <since_tizen> 3 </since_tizen>
610 /// http://tizen.org/privilege/camera
612 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
613 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
614 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
615 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
616 public void StartPreview()
618 ValidateState(CameraState.Created, CameraState.Captured);
620 CameraErrorFactory.ThrowIfError(Native.StartPreview(_handle),
621 "Failed to start the camera preview.");
623 // Update by StateChangedCallback can be delayed for dozens of milliseconds.
624 SetState(CameraState.Preview);
628 /// Stops capturing and drawing preview frames on the screen.
629 /// The camera must be in the <see cref="CameraState.Preview"/> state.
631 /// <since_tizen> 3 </since_tizen>
633 /// http://tizen.org/privilege/camera
635 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
636 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
637 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
638 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
639 public void StopPreview()
641 ValidateState(CameraState.Preview);
643 CameraErrorFactory.ThrowIfError(Native.StopPreview(_handle),
644 "Failed to stop the camera preview.");
646 SetState(CameraState.Created);
650 /// Starts capturing of still images.
651 /// EventHandler must be set for capturing using <see cref="Capturing"/>
652 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
653 /// The camera must be in the <see cref="CameraState.Preview"/> state.
655 /// <since_tizen> 3 </since_tizen>
657 /// http://tizen.org/privilege/camera
660 /// This function causes the transition of the camera state from Capturing to Captured
661 /// automatically and the corresponding EventHandlers will be invoked.
662 /// The preview should be restarted by calling <see cref="StartPreview"/> method after capture is completed.
664 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
665 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
666 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
667 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
668 public void StartCapture()
670 ValidateState(CameraState.Preview);
672 CameraErrorFactory.ThrowIfError(Native.StartCapture(_handle, _capturingCallback, _captureCompletedCallback, IntPtr.Zero),
673 "Failed to start the camera capture.");
675 SetState(CameraState.Capturing);
679 /// Starts continuously capturing still images.
680 /// EventHandler must be set for capturing using <see cref="Capturing"/>
681 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
682 /// The camera must be in the <see cref="CameraState.Preview"/> state.
684 /// <since_tizen> 3 </since_tizen>
686 /// http://tizen.org/privilege/camera
688 /// <param name="count">The number of still images.</param>
689 /// <param name="interval">The interval of the capture(milliseconds).</param>
690 /// <param name="cancellationToken">The cancellation token to cancel capturing.</param>
691 /// <seealso cref="System.Threading.CancellationToken"/>
693 /// If this is not supported zero shutter lag occurs. The capture resolution could be
694 /// changed to the preview resolution. This function causes the transition of the camera state
695 /// from Capturing to Captured automatically and the corresponding Eventhandlers will be invoked.
696 /// Each captured image will be delivered through Eventhandler set using <see cref="Capturing"/> event.
697 /// The preview should be restarted by calling <see cref="StartPreview"/> method after capture is completed.
699 /// <exception cref="ArgumentOutOfRangeException">In case of invalid parameters.</exception>
700 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
701 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
702 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
703 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
704 public void StartCapture(int count, int interval, CancellationToken cancellationToken)
706 ValidateState(CameraState.Preview);
710 throw new ArgumentOutOfRangeException(nameof(count), count, $"{nameof(count)} should be greater than one.");
715 throw new ArgumentOutOfRangeException(nameof(interval), interval, $"{nameof(interval)} should be greater than or equal to zero.");
718 //Handle CancellationToken
719 if (cancellationToken != CancellationToken.None)
721 cancellationToken.Register(() =>
723 CameraErrorFactory.ThrowIfError(Native.StopContinuousCapture(_handle),
724 "Failed to cancel the continuous capture");
725 SetState(CameraState.Captured);
729 CameraErrorFactory.ThrowIfError(Native.StartContinuousCapture(_handle, count, interval,
730 _capturingCallback, _captureCompletedCallback, IntPtr.Zero), "Failed to start the continuous capture.");
732 SetState(CameraState.Capturing);
736 /// Starts camera auto-focusing, asynchronously.
737 /// The camera must be in the <see cref="CameraState.Preview"/> or <see cref="CameraState.Captured"/> state.
739 /// <since_tizen> 3 </since_tizen>
740 /// <param name="continuous">Continuous auto focus</param>
742 /// http://tizen.org/privilege/camera
745 /// If continuous status is true, the camera continuously tries to focus.
747 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
748 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
749 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
750 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
751 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
752 public void StartFocusing(bool continuous)
754 ValidateState(CameraState.Preview, CameraState.Captured);
756 CameraErrorFactory.ThrowIfError(Native.StartFocusing(_handle, continuous),
757 "Failed to cancel the camera focus.");
761 /// Stops camera auto focusing.
762 /// The camera must be in the <see cref="CameraState.Preview"/> or <see cref="CameraState.Captured"/> state.
764 /// <since_tizen> 3 </since_tizen>
766 /// http://tizen.org/privilege/camera
768 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
769 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
770 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
771 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
772 public void StopFocusing()
774 ValidateState(CameraState.Preview, CameraState.Captured);
776 CameraErrorFactory.ThrowIfError(Native.CancelFocusing(_handle),
777 "Failed to cancel the camera focus.");
781 /// Starts face detection.
782 /// The camera must be in the <see cref="CameraState.Preview"/> state.
784 /// <since_tizen> 3 </since_tizen>
786 /// http://tizen.org/privilege/camera
789 /// This should be called after <see cref="StartPreview"/> is started.
790 /// The Eventhandler set using <see cref="FaceDetected"/> invoked when the face is detected in preview frame.
791 /// Internally it starts continuous focus and focusing on the detected face.
793 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
794 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
795 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
796 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
797 public void StartFaceDetection()
799 ValidateState(CameraState.Preview);
801 _faceDetectedCallback = (IntPtr faces, int count, IntPtr userData) =>
803 var result = new List<FaceDetectionData>();
804 IntPtr current = faces;
806 for (int i = 0; i < count; i++)
808 result.Add(new FaceDetectionData(current));
809 current = IntPtr.Add(current, Marshal.SizeOf<Native.DetectedFaceStruct>());
812 FaceDetected?.Invoke(this, new FaceDetectedEventArgs(result));
814 CameraErrorFactory.ThrowIfError(Native.StartFaceDetection(_handle, _faceDetectedCallback, IntPtr.Zero),
815 "Failed to start face detection");
819 /// Stops face detection.
821 /// <since_tizen> 3 </since_tizen>
823 /// http://tizen.org/privilege/camera
825 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
826 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
827 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
828 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
829 public void StopFaceDetection()
831 if (_faceDetectedCallback == null)
833 throw new InvalidOperationException("The face detection is not started.");
836 CameraErrorFactory.ThrowIfError(Native.StopFaceDetection(_handle),
837 "Failed to stop the face detection.");
839 _faceDetectedCallback = null;
843 #region Callback registrations
844 private void RegisterCallbacks()
846 RegisterErrorCallback();
847 RegisterFocusStateChanged();
848 RegisterInterruptStartedCallback();
849 RegisterInterruptedCallback();
850 RegisterStateChangedCallback();
852 //Define capturing callback
853 _capturingCallback = (IntPtr main, IntPtr postview, IntPtr thumbnail, IntPtr userData) =>
855 Capturing?.Invoke(this, new CameraCapturingEventArgs(new StillImage(main),
856 postview == IntPtr.Zero ? null : new StillImage(postview),
857 thumbnail == IntPtr.Zero ? null : new StillImage(thumbnail)));
860 //Define captureCompleted callback
861 _captureCompletedCallback = _ =>
863 SetState(CameraState.Captured);
864 CaptureCompleted?.Invoke(this, EventArgs.Empty);
868 private void RegisterInterruptStartedCallback()
870 _interruptStartedCallback = (CameraPolicy policy, CameraState state, IntPtr userData) =>
872 InterruptStarted?.Invoke(this, new CameraInterruptStartedEventArgs(policy, state));
874 CameraErrorFactory.ThrowIfError(Native.SetInterruptStartedCallback(_handle, _interruptStartedCallback, IntPtr.Zero),
875 "Failed to set interrupt callback");
878 private void RegisterInterruptedCallback()
880 _interruptedCallback = (CameraPolicy policy, CameraState previous, CameraState current, IntPtr userData) =>
882 Interrupted?.Invoke(this, new CameraInterruptedEventArgs(policy, previous, current));
884 CameraErrorFactory.ThrowIfError(Native.SetInterruptedCallback(_handle, _interruptedCallback, IntPtr.Zero),
885 "Failed to set interrupt callback");
888 private void RegisterErrorCallback()
890 _errorCallback = (CameraErrorCode error, CameraState current, IntPtr userData) =>
892 ErrorOccurred?.Invoke(this, new CameraErrorOccurredEventArgs(error, current));
894 CameraErrorFactory.ThrowIfError(Native.SetErrorCallback(_handle, _errorCallback, IntPtr.Zero),
895 "Setting error callback failed");
898 private void RegisterStateChangedCallback()
900 _stateChangedCallback = (CameraState previous, CameraState current, bool byPolicy, IntPtr _) =>
903 Log.Info(CameraLog.Tag, "Camera state changed " + previous.ToString() + " -> " + current.ToString());
904 StateChanged?.Invoke(this, new CameraStateChangedEventArgs(previous, current, byPolicy));
906 CameraErrorFactory.ThrowIfError(Native.SetStateChangedCallback(_handle, _stateChangedCallback, IntPtr.Zero),
907 "Setting state changed callback failed");
910 private static void RegisterDeviceStateChangedCallback()
912 _deviceStateChangedCallback = (CameraDevice device, CameraDeviceState state, IntPtr userData) =>
914 _deviceStateChanged?.Invoke(null, new CameraDeviceStateChangedEventArgs(device, state));
917 CameraErrorFactory.ThrowIfError(Native.SetDeviceStateChangedCallback(_deviceStateChangedCallback, IntPtr.Zero, out _deviceStateCallbackId),
918 "Failed to set device state changed callback");
920 Log.Info(CameraLog.Tag, "add callbackId " + _deviceStateCallbackId.ToString());
923 private static void UnregisterDeviceStateChangedCallback()
925 CameraErrorFactory.ThrowIfError(Native.UnsetDeviceStateChangedCallback(_deviceStateCallbackId),
926 "Unsetting device state changed callback failed");
927 _deviceStateChangedCallback = null;
928 _deviceStateCallbackId = 0;
931 private void RegisterFocusStateChanged()
933 _focusStateChangedCallback = (CameraFocusState state, IntPtr userData) =>
935 FocusStateChanged?.Invoke(this, new CameraFocusStateChangedEventArgs(state));
937 CameraErrorFactory.ThrowIfError(Native.SetFocusStateChangedCallback(_handle, _focusStateChangedCallback, IntPtr.Zero),
938 "Setting focus changed callback failed");
941 private void RegisterHdrCaptureProgress()
943 _hdrCaptureProgressCallback = (int percent, IntPtr userData) =>
945 _hdrCaptureProgress?.Invoke(this, new HdrCaptureProgressEventArgs(percent));
947 CameraErrorFactory.ThrowIfError(Native.SetHdrCaptureProgressCallback(_handle, _hdrCaptureProgressCallback, IntPtr.Zero),
948 "Setting Hdr capture progress callback failed");
951 private void UnregisterHdrCaptureProgress()
953 CameraErrorFactory.ThrowIfError(Native.UnsetHdrCaptureProgressCallback(_handle),
954 "Unsetting hdr capture progress is failed");
955 _hdrCaptureProgressCallback = null;
958 private void RegisterPreviewCallback()
960 _previewCallback = (IntPtr frame, IntPtr userData) =>
962 _preview?.Invoke(this, new PreviewEventArgs(new PreviewFrame(frame)));
964 CameraErrorFactory.ThrowIfError(Native.SetPreviewCallback(_handle, _previewCallback, IntPtr.Zero),
965 "Setting preview callback failed");
968 private void UnregisterPreviewCallback()
970 CameraErrorFactory.ThrowIfError(Native.UnsetPreviewCallback(_handle),
971 "Unsetting preview callback failed");
972 _previewCallback = null;
975 private void RegisterMediaPacketPreviewCallback()
977 _mediaPacketPreviewCallback = (IntPtr mediaPacket, IntPtr userData) =>
979 MediaPacket packet = MediaPacket.From(mediaPacket);
980 var eventHandler = _mediaPacketPreview;
982 if (eventHandler != null)
984 eventHandler.Invoke(this, new MediaPacketPreviewEventArgs(packet));
991 CameraErrorFactory.ThrowIfError(Native.SetMediaPacketPreviewCallback(_handle, _mediaPacketPreviewCallback, IntPtr.Zero),
992 "Setting media packet preview callback failed");
995 private void UnregisterMediaPacketPreviewCallback()
997 CameraErrorFactory.ThrowIfError(Native.UnsetMediaPacketPreviewCallback(_handle),
998 "Unsetting media packet preview callback failed");
999 _mediaPacketPreviewCallback = null;
1001 #endregion Callback registrations