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 /// This camera class provides methods to capture photos and supports setting up notifications
37 /// for state changes of capturing, previewing, focusing, and informing about the resolution and the 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, (For example, 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 /// An event that occurs when the camera interrupt is started by the policy.
152 public event EventHandler<CameraInterruptStartedEventArgs> InterruptStarted;
153 private Native.InterruptStartedCallback _interruptStartedCallback;
156 /// An event that occurs when an camera is interrupted by the policy.
158 /// <since_tizen> 3 </since_tizen>
159 public event EventHandler<CameraInterruptedEventArgs> Interrupted;
160 private Native.InterruptedCallback _interruptedCallback;
163 /// An 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 /// An 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 /// An event that occurs when a face is detected in the preview frame.
179 /// <since_tizen> 3 </since_tizen>
180 public event EventHandler<FaceDetectedEventArgs> FaceDetected;
181 private Native.FaceDetectedCallback _faceDetectedCallback;
184 /// An event that occurs during capture of an image.
186 /// <since_tizen> 3 </since_tizen>
187 public event EventHandler<CameraCapturingEventArgs> Capturing;
188 private Native.CapturingCallback _capturingCallback;
191 /// An 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 /// An event that occurs when there is a change in the HDR capture progress.
203 /// Checks whether the <see cref="CameraCapabilities.IsHdrCaptureSupported"/> is supported or not before adding 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 /// An event that occurs when the 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 /// An 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 /// An event that occurs once per frame when previewing.
289 /// Preview callback is registered when an user adds a 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 /// An event that occurs once per frame when previewing.
327 /// Preview callback is registered when an user adds a 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 /// Gets or sets 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 the 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 of.</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);
446 CameraError IDisplayable<CameraError>.ApplyEcoreWindow(IntPtr windowHandle)
448 throw new NotSupportedException("Camera does not support NUI.Window display.");
452 /// Gets the state of the camera.
454 /// <since_tizen> 3 </since_tizen>
455 /// <value> None, Created, Preview, Capturing, Captured.</value>
456 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
457 public CameraState State
461 ValidateNotDisposed();
463 CameraState val = CameraState.None;
464 CameraErrorFactory.ThrowIfError(Native.GetState(_handle, out val),
465 "Failed to get camera state");
472 /// The hint for the display reuse.
473 /// If the hint is set to true, the display will be reused when the camera device is changed with
474 /// the ChangeDevice method.
476 /// <since_tizen> 3 </since_tizen>
477 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
478 /// <exception cref="InvalidOperationException">An invalid state.</exception>
479 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
480 public bool DisplayReuseHint
484 ValidateNotDisposed();
486 CameraErrorFactory.ThrowIfError(Native.GetDisplayReuseHint(_handle, out bool val),
487 "Failed to get camera display reuse hint");
494 ValidateState(CameraState.Preview);
496 CameraErrorFactory.ThrowIfError(Native.SetDisplayReuseHint(_handle, value),
497 "Failed to set display reuse hint.");
502 /// Gets the facing direction of the camera module.
504 /// <since_tizen> 3 </since_tizen>
505 /// <value>A <see cref="CameraFacingDirection"/> that specifies the facing direction of the camera device.</value>
506 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
507 public CameraFacingDirection Direction
511 ValidateNotDisposed();
513 CameraErrorFactory.ThrowIfError(Native.GetFacingDirection(_handle, out var val),
514 "Failed to get camera direction");
521 /// Gets the camera device count.
523 /// <since_tizen> 3 </since_tizen>
524 /// <value>This returns 2, if the device supports primary and secondary cameras.
525 /// Otherwise 1, if the device only supports primary camera.</value>
526 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
527 public int CameraCount
531 ValidateNotDisposed();
533 CameraErrorFactory.ThrowIfError(Native.GetDeviceCount(_handle, out int val),
534 "Failed to get camera device count");
539 #endregion Properties
543 /// Changes the camera device.
545 /// <since_tizen> 3 </since_tizen>
546 /// <param name="device">The hardware camera to access.</param>
548 /// If display reuse is set using <see cref="DisplayReuseHint"/>
549 /// before stopping the preview, the display will be reused and last frame on the display
550 /// can be kept even though camera device is changed.
551 /// The camera must be in the <see cref="CameraState.Created"/>.
553 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
554 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
555 /// <exception cref="NotSupportedException">In case of the ChangeDevice feature is not supported.</exception>
556 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
557 public void ChangeDevice(CameraDevice device)
559 ValidateState(CameraState.Created);
560 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
562 CameraErrorFactory.ThrowIfError(Native.ChangeDevice(_handle, device),
563 "Failed to change the camera device");
567 /// Gets the device state.
569 /// <since_tizen> 3 </since_tizen>
570 /// <param name="device">The device to get the state.</param>
571 /// <returns>Returns the state of the camera device.</returns>
572 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
573 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
574 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
575 public static CameraDeviceState GetDeviceState(CameraDevice device)
577 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
579 CameraErrorFactory.ThrowIfError(Native.GetDeviceState(device, out var val),
580 "Failed to get the camera device state.");
586 /// Gets the flash state.
588 /// <since_tizen> 3 </since_tizen>
589 /// <param name="device">The device to get the state.</param>
590 /// <returns>Returns the flash state of the camera device.</returns>
591 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
592 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
593 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
594 public static CameraFlashState GetFlashState(CameraDevice device)
596 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
598 CameraErrorFactory.ThrowIfError(Native.GetFlashState(device, out var val),
599 "Failed to get camera flash state");
605 /// Starts capturing and drawing preview frames on the screen.
606 /// The display property must be set using <see cref="Display"/> before using this method.
607 /// If needed set fps <see cref="CameraSettings.PreviewFps"/>, preview resolution
608 /// <see cref="CameraSettings.PreviewResolution"/>, or preview format <see cref="CameraSettings.PreviewPixelFormat"/>
609 /// before using this method.
610 /// The camera must be in the <see cref="CameraState.Created"/> or the <see cref="CameraState.Captured"/> state.
612 /// <since_tizen> 3 </since_tizen>
614 /// http://tizen.org/privilege/camera
616 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
617 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
618 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
619 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
620 public void StartPreview()
622 ValidateState(CameraState.Created, CameraState.Captured);
624 CameraErrorFactory.ThrowIfError(Native.StartPreview(_handle),
625 "Failed to start the camera preview.");
627 // Update by StateChangedCallback can be delayed for dozens of milliseconds.
628 SetState(CameraState.Preview);
632 /// Stops capturing and drawing preview frames on the screen.
633 /// The camera must be in the <see cref="CameraState.Preview"/> state.
635 /// <since_tizen> 3 </since_tizen>
637 /// http://tizen.org/privilege/camera
639 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
640 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
641 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
642 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
643 public void StopPreview()
645 ValidateState(CameraState.Preview);
647 CameraErrorFactory.ThrowIfError(Native.StopPreview(_handle),
648 "Failed to stop the camera preview.");
650 SetState(CameraState.Created);
654 /// Starts capturing of still images.
655 /// EventHandler must be set for capturing using <see cref="Capturing"/>
656 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
657 /// The camera must be in the <see cref="CameraState.Preview"/> state.
659 /// <since_tizen> 3 </since_tizen>
661 /// http://tizen.org/privilege/camera
664 /// This function causes the transition of the camera state from capturing to captured
665 /// automatically and the corresponding EventHandlers will be invoked.
666 /// The preview should be restarted by calling the <see cref="StartPreview"/> method after capture is completed.
668 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
669 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
670 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
671 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
672 public void StartCapture()
674 ValidateState(CameraState.Preview);
676 CameraErrorFactory.ThrowIfError(Native.StartCapture(_handle, _capturingCallback, _captureCompletedCallback, IntPtr.Zero),
677 "Failed to start the camera capture.");
679 SetState(CameraState.Capturing);
683 /// Starts continuously capturing still images.
684 /// EventHandler must be set for capturing using <see cref="Capturing"/>
685 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
686 /// The camera must be in the <see cref="CameraState.Preview"/> state.
688 /// <since_tizen> 3 </since_tizen>
690 /// http://tizen.org/privilege/camera
692 /// <param name="count">The number of still images.</param>
693 /// <param name="interval">The interval of the capture(milliseconds).</param>
694 /// <param name="cancellationToken">The cancellation token to cancel capturing.</param>
695 /// <seealso cref="CancellationToken"/>
697 /// If this is not supported, zero shutter lag occurs. The capture resolution could be
698 /// changed to the preview resolution. This function causes the transition of the camera state
699 /// from capturing to captured automatically and the corresponding Eventhandlers will be invoked.
700 /// Each captured image will be delivered through Eventhandler set using the <see cref="Capturing"/> event.
701 /// The preview should be restarted by calling the <see cref="StartPreview"/> method after capture is completed.
703 /// <exception cref="ArgumentOutOfRangeException">In case of invalid parameters.</exception>
704 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
705 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
706 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
707 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
708 public void StartCapture(int count, int interval, CancellationToken cancellationToken)
710 ValidateState(CameraState.Preview);
714 throw new ArgumentOutOfRangeException(nameof(count), count, $"{nameof(count)} should be greater than one.");
719 throw new ArgumentOutOfRangeException(nameof(interval), interval, $"{nameof(interval)} should be greater than or equal to zero.");
722 //Handle CancellationToken
723 if (cancellationToken != CancellationToken.None)
725 cancellationToken.Register(() =>
727 CameraErrorFactory.ThrowIfError(Native.StopContinuousCapture(_handle),
728 "Failed to cancel the continuous capture");
729 SetState(CameraState.Captured);
733 CameraErrorFactory.ThrowIfError(Native.StartContinuousCapture(_handle, count, interval,
734 _capturingCallback, _captureCompletedCallback, IntPtr.Zero), "Failed to start the continuous capture.");
736 SetState(CameraState.Capturing);
740 /// Starts camera auto-focusing, asynchronously.
741 /// The camera must be in the <see cref="CameraState.Preview"/> or the <see cref="CameraState.Captured"/> state.
743 /// <since_tizen> 3 </since_tizen>
744 /// <param name="continuous">Continuous auto focus.</param>
746 /// http://tizen.org/privilege/camera
749 /// If continuous status is true, the camera continuously tries to focus.
751 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
752 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
753 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
754 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
755 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
756 public void StartFocusing(bool continuous)
758 ValidateState(CameraState.Preview, CameraState.Captured);
760 CameraErrorFactory.ThrowIfError(Native.StartFocusing(_handle, continuous),
761 "Failed to cancel the camera focus.");
765 /// Stops camera auto focusing.
766 /// The camera must be in the <see cref="CameraState.Preview"/> or the <see cref="CameraState.Captured"/> state.
768 /// <since_tizen> 3 </since_tizen>
770 /// http://tizen.org/privilege/camera
772 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
773 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
774 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
775 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
776 public void StopFocusing()
778 ValidateState(CameraState.Preview, CameraState.Captured);
780 CameraErrorFactory.ThrowIfError(Native.CancelFocusing(_handle),
781 "Failed to cancel the camera focus.");
785 /// Starts face detection.
786 /// The camera must be in the <see cref="CameraState.Preview"/> state.
788 /// <since_tizen> 3 </since_tizen>
790 /// http://tizen.org/privilege/camera
793 /// This should be called after <see cref="StartPreview"/> is started.
794 /// The Eventhandler set using <see cref="FaceDetected"/> is invoked when the face is detected in the preview frame.
795 /// Internally, it starts continuously focus and focusing on the detected face.
797 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
798 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
799 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
800 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
801 public void StartFaceDetection()
803 ValidateState(CameraState.Preview);
805 _faceDetectedCallback = (IntPtr faces, int count, IntPtr userData) =>
807 var result = new List<FaceDetectionData>();
808 IntPtr current = faces;
810 for (int i = 0; i < count; i++)
812 result.Add(new FaceDetectionData(current));
813 current = IntPtr.Add(current, Marshal.SizeOf<Native.DetectedFaceStruct>());
816 FaceDetected?.Invoke(this, new FaceDetectedEventArgs(result));
818 CameraErrorFactory.ThrowIfError(Native.StartFaceDetection(_handle, _faceDetectedCallback, IntPtr.Zero),
819 "Failed to start face detection");
823 /// Stops face detection.
825 /// <since_tizen> 3 </since_tizen>
827 /// http://tizen.org/privilege/camera
829 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
830 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
831 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
832 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
833 public void StopFaceDetection()
835 if (_faceDetectedCallback == null)
837 throw new InvalidOperationException("The face detection is not started.");
840 CameraErrorFactory.ThrowIfError(Native.StopFaceDetection(_handle),
841 "Failed to stop the face detection.");
843 _faceDetectedCallback = null;
847 #region Callback registrations
848 private void RegisterCallbacks()
850 RegisterErrorCallback();
851 RegisterFocusStateChanged();
852 RegisterInterruptStartedCallback();
853 RegisterInterruptedCallback();
854 RegisterStateChangedCallback();
856 //Define capturing callback
857 _capturingCallback = (IntPtr main, IntPtr postview, IntPtr thumbnail, IntPtr userData) =>
859 Capturing?.Invoke(this, new CameraCapturingEventArgs(new StillImage(main),
860 postview == IntPtr.Zero ? null : new StillImage(postview),
861 thumbnail == IntPtr.Zero ? null : new StillImage(thumbnail)));
864 //Define captureCompleted callback
865 _captureCompletedCallback = _ =>
867 SetState(CameraState.Captured);
868 CaptureCompleted?.Invoke(this, EventArgs.Empty);
872 private void RegisterInterruptStartedCallback()
874 _interruptStartedCallback = (CameraPolicy policy, CameraState state, IntPtr userData) =>
876 InterruptStarted?.Invoke(this, new CameraInterruptStartedEventArgs(policy, state));
878 CameraErrorFactory.ThrowIfError(Native.SetInterruptStartedCallback(_handle, _interruptStartedCallback, IntPtr.Zero),
879 "Failed to set interrupt callback");
882 private void RegisterInterruptedCallback()
884 _interruptedCallback = (CameraPolicy policy, CameraState previous, CameraState current, IntPtr userData) =>
886 Interrupted?.Invoke(this, new CameraInterruptedEventArgs(policy, previous, current));
888 CameraErrorFactory.ThrowIfError(Native.SetInterruptedCallback(_handle, _interruptedCallback, IntPtr.Zero),
889 "Failed to set interrupt callback");
892 private void RegisterErrorCallback()
894 _errorCallback = (CameraErrorCode error, CameraState current, IntPtr userData) =>
896 ErrorOccurred?.Invoke(this, new CameraErrorOccurredEventArgs(error, current));
898 CameraErrorFactory.ThrowIfError(Native.SetErrorCallback(_handle, _errorCallback, IntPtr.Zero),
899 "Setting error callback failed");
902 private void RegisterStateChangedCallback()
904 _stateChangedCallback = (CameraState previous, CameraState current, bool byPolicy, IntPtr _) =>
907 Log.Info(CameraLog.Tag, "Camera state changed " + previous.ToString() + " -> " + current.ToString());
908 StateChanged?.Invoke(this, new CameraStateChangedEventArgs(previous, current, byPolicy));
910 CameraErrorFactory.ThrowIfError(Native.SetStateChangedCallback(_handle, _stateChangedCallback, IntPtr.Zero),
911 "Setting state changed callback failed");
914 private static void RegisterDeviceStateChangedCallback()
916 _deviceStateChangedCallback = (CameraDevice device, CameraDeviceState state, IntPtr userData) =>
918 _deviceStateChanged?.Invoke(null, new CameraDeviceStateChangedEventArgs(device, state));
921 CameraErrorFactory.ThrowIfError(Native.SetDeviceStateChangedCallback(_deviceStateChangedCallback, IntPtr.Zero, out _deviceStateCallbackId),
922 "Failed to set device state changed callback");
924 Log.Info(CameraLog.Tag, "add callbackId " + _deviceStateCallbackId.ToString());
927 private static void UnregisterDeviceStateChangedCallback()
929 CameraErrorFactory.ThrowIfError(Native.UnsetDeviceStateChangedCallback(_deviceStateCallbackId),
930 "Unsetting device state changed callback failed");
931 _deviceStateChangedCallback = null;
932 _deviceStateCallbackId = 0;
935 private void RegisterFocusStateChanged()
937 _focusStateChangedCallback = (CameraFocusState state, IntPtr userData) =>
939 FocusStateChanged?.Invoke(this, new CameraFocusStateChangedEventArgs(state));
941 CameraErrorFactory.ThrowIfError(Native.SetFocusStateChangedCallback(_handle, _focusStateChangedCallback, IntPtr.Zero),
942 "Setting focus changed callback failed");
945 private void RegisterHdrCaptureProgress()
947 _hdrCaptureProgressCallback = (int percent, IntPtr userData) =>
949 _hdrCaptureProgress?.Invoke(this, new HdrCaptureProgressEventArgs(percent));
951 CameraErrorFactory.ThrowIfError(Native.SetHdrCaptureProgressCallback(_handle, _hdrCaptureProgressCallback, IntPtr.Zero),
952 "Setting Hdr capture progress callback failed");
955 private void UnregisterHdrCaptureProgress()
957 CameraErrorFactory.ThrowIfError(Native.UnsetHdrCaptureProgressCallback(_handle),
958 "Unsetting hdr capture progress is failed");
959 _hdrCaptureProgressCallback = null;
962 private void RegisterPreviewCallback()
964 _previewCallback = (IntPtr frame, IntPtr userData) =>
966 _preview?.Invoke(this, new PreviewEventArgs(new PreviewFrame(frame)));
968 CameraErrorFactory.ThrowIfError(Native.SetPreviewCallback(_handle, _previewCallback, IntPtr.Zero),
969 "Setting preview callback failed");
972 private void UnregisterPreviewCallback()
974 CameraErrorFactory.ThrowIfError(Native.UnsetPreviewCallback(_handle),
975 "Unsetting preview callback failed");
976 _previewCallback = null;
979 private void RegisterMediaPacketPreviewCallback()
981 _mediaPacketPreviewCallback = (IntPtr mediaPacket, IntPtr userData) =>
983 MediaPacket packet = MediaPacket.From(mediaPacket);
984 var eventHandler = _mediaPacketPreview;
986 if (eventHandler != null)
988 eventHandler.Invoke(this, new MediaPacketPreviewEventArgs(packet));
995 CameraErrorFactory.ThrowIfError(Native.SetMediaPacketPreviewCallback(_handle, _mediaPacketPreviewCallback, IntPtr.Zero),
996 "Setting media packet preview callback failed");
999 private void UnregisterMediaPacketPreviewCallback()
1001 CameraErrorFactory.ThrowIfError(Native.UnsetMediaPacketPreviewCallback(_handle),
1002 "Unsetting media packet preview callback failed");
1003 _mediaPacketPreviewCallback = null;
1005 #endregion Callback registrations