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.
75 /// Gets the native handle of the camera.
77 public IntPtr Handle => GetHandle();
79 internal IntPtr GetHandle()
81 ValidateNotDisposed();
85 #region Dispose support
87 /// Releases the unmanaged resources used by the camera.
89 /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
90 protected virtual void Dispose(bool disposing)
96 // to be used if there are any other disposable objects
99 if (_handle != IntPtr.Zero)
101 Native.Destroy(_handle);
102 _handle = IntPtr.Zero;
110 /// Releases all resources used by the camera.
112 /// <since_tizen> 3 </since_tizen>
113 public void Dispose()
115 ReplaceDisplay(null);
117 GC.SuppressFinalize(this);
120 internal void ValidateNotDisposed()
124 Log.Error(CameraLog.Tag, "Camera handle is disposed.");
125 throw new ObjectDisposedException(nameof(Camera));
128 #endregion Dispose support
130 #region Check camera state
131 internal void ValidateState(params CameraState[] required)
133 ValidateNotDisposed();
135 Debug.Assert(required.Length > 0);
137 var curState = _state;
138 if (!required.Contains(curState))
140 throw new InvalidOperationException($"The camera is not in a valid state. " +
141 $"Current State : { curState }, Valid State : { string.Join(", ", required) }.");
145 internal void SetState(CameraState state)
149 #endregion Check camera state
151 #region EventHandlers
153 /// An event that occurs when the camera interrupt is started by the policy.
155 public event EventHandler<CameraInterruptStartedEventArgs> InterruptStarted;
156 private Native.InterruptStartedCallback _interruptStartedCallback;
159 /// An event that occurs when an camera is interrupted by the policy.
161 /// <since_tizen> 3 </since_tizen>
162 public event EventHandler<CameraInterruptedEventArgs> Interrupted;
163 private Native.InterruptedCallback _interruptedCallback;
166 /// An event that occurs when there is an asynchronous error.
168 /// <since_tizen> 3 </since_tizen>
169 public event EventHandler<CameraErrorOccurredEventArgs> ErrorOccurred;
170 private Native.ErrorCallback _errorCallback;
173 /// An event that occurs when the auto focus state is changed.
175 /// <since_tizen> 3 </since_tizen>
176 public event EventHandler<CameraFocusStateChangedEventArgs> FocusStateChanged;
177 private Native.FocusStateChangedCallback _focusStateChangedCallback;
180 /// An event that occurs when a face is detected in the preview frame.
182 /// <since_tizen> 3 </since_tizen>
183 public event EventHandler<FaceDetectedEventArgs> FaceDetected;
184 private Native.FaceDetectedCallback _faceDetectedCallback;
187 /// An event that occurs during capture of an image.
189 /// <since_tizen> 3 </since_tizen>
190 public event EventHandler<CameraCapturingEventArgs> Capturing;
191 private Native.CapturingCallback _capturingCallback;
194 /// An event that occurs after the capture of the image.
196 /// <since_tizen> 3 </since_tizen>
197 public event EventHandler<EventArgs> CaptureCompleted;
198 private Native.CaptureCompletedCallback _captureCompletedCallback;
200 private Native.HdrCaptureProgressCallback _hdrCaptureProgressCallback;
201 private event EventHandler<HdrCaptureProgressEventArgs> _hdrCaptureProgress;
202 private object _hdrCaptureProgressEventLock = new object();
205 /// An event that occurs when there is a change in the HDR capture progress.
206 /// Checks whether the <see cref="CameraCapabilities.IsHdrCaptureSupported"/> is supported or not before adding this EventHandler.
208 /// <since_tizen> 3 </since_tizen>
209 /// <exception cref="NotSupportedException">In case of HDR feature is not supported.</exception>
210 public event EventHandler<HdrCaptureProgressEventArgs> HdrCaptureProgress
214 lock (_hdrCaptureProgressEventLock)
216 if (_hdrCaptureProgress == null)
218 RegisterHdrCaptureProgress();
221 _hdrCaptureProgress += value;
227 lock (_hdrCaptureProgressEventLock)
229 _hdrCaptureProgress -= value;
231 if (_hdrCaptureProgress == null)
233 UnregisterHdrCaptureProgress();
240 /// An event that occurs when the camera state is changed.
242 /// <since_tizen> 3 </since_tizen>
243 public event EventHandler<CameraStateChangedEventArgs> StateChanged;
244 private Native.StateChangedCallback _stateChangedCallback;
246 private static Native.DeviceStateChangedCallback _deviceStateChangedCallback;
247 private static event EventHandler<CameraDeviceStateChangedEventArgs> _deviceStateChanged;
248 private static object _deviceStateChangedEventLock = new object();
249 private static int _deviceStateCallbackId;
252 /// An event that occurs after the <see cref="CameraDeviceState"/> is changed.
254 /// <since_tizen> 3 </since_tizen>
255 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
256 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
257 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
258 public static event EventHandler<CameraDeviceStateChangedEventArgs> DeviceStateChanged
262 lock (_deviceStateChangedEventLock)
264 if (_deviceStateChanged == null)
266 RegisterDeviceStateChangedCallback();
269 _deviceStateChanged += value;
275 lock (_deviceStateChangedEventLock)
277 _deviceStateChanged -= value;
279 if (_deviceStateChanged == null)
281 UnregisterDeviceStateChangedCallback();
287 private Native.PreviewCallback _previewCallback;
288 private event EventHandler<PreviewEventArgs> _preview;
289 private object _previewEventLock = new object();
291 /// An event that occurs once per frame when previewing.
292 /// Preview callback is registered when an user adds a callback explicitly to avoid useless P/Invoke.
294 /// <since_tizen> 3 </since_tizen>
295 public event EventHandler<PreviewEventArgs> Preview
299 lock (_previewEventLock)
301 if (_preview == null)
303 RegisterPreviewCallback();
312 lock (_previewEventLock)
316 if (_preview == null)
318 UnregisterPreviewCallback();
324 private Native.MediaPacketPreviewCallback _mediaPacketPreviewCallback;
325 private EventHandler<MediaPacketPreviewEventArgs> _mediaPacketPreview;
326 private object _mediaPacketPreviewEventLock = new object();
329 /// An event that occurs once per frame when previewing.
330 /// Preview callback is registered when an user adds a callback explicitly to avoid useless P/Invoke.
332 /// <since_tizen> 3 </since_tizen>
333 public event EventHandler<MediaPacketPreviewEventArgs> MediaPacketPreview
337 lock (_mediaPacketPreviewEventLock)
339 if (_mediaPacketPreview == null)
341 RegisterMediaPacketPreviewCallback();
344 _mediaPacketPreview += value;
350 lock (_mediaPacketPreviewEventLock)
352 _mediaPacketPreview -= value;
354 if (_mediaPacketPreview == null)
356 UnregisterMediaPacketPreviewCallback();
361 #endregion EventHandlers
365 /// Gets or sets the various camera settings.
367 /// <since_tizen> 3 </since_tizen>
368 public CameraSettings Settings { get; }
371 /// Gets the various camera capabilities.
373 /// <since_tizen> 3 </since_tizen>
374 public CameraCapabilities Capabilities { get; }
377 /// Get/set various camera display properties.
379 /// <since_tizen> 3 </since_tizen>
380 public CameraDisplaySettings DisplaySettings { get; }
382 private Display _display;
384 private CameraError SetDisplay(Display display)
388 return CameraDisplay.SetTarget(GetHandle(), DisplayType.None, IntPtr.Zero);
391 return display.ApplyTo(this);
394 private void ReplaceDisplay(Display newDisplay)
396 _display?.SetOwner(null);
397 _display = newDisplay;
398 _display?.SetOwner(this);
402 /// Sets or gets the display type and handle to show preview images.
403 /// The camera must be in the <see cref="CameraState.Created"/> state.
405 /// <since_tizen> 3 </since_tizen>
407 /// This must be set before the StartPreview() method.
408 /// In custom ROI display mode, DisplayRoiArea property must be set before calling this method.
410 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
411 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
412 /// <exception cref="ObjectDisposedException" > The camera already has been disposed of.</exception>
413 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
414 public Display Display
423 ValidateState(CameraState.Created);
425 if (value?.Owner != null)
427 if (ReferenceEquals(this, value.Owner))
432 throw new ArgumentException("The display has already been assigned to another.");
435 CameraErrorFactory.ThrowIfError(SetDisplay(value), "Failed to set the camera display");
437 ReplaceDisplay(value);
441 CameraError IDisplayable<CameraError>.ApplyEvasDisplay(DisplayType type, ElmSharp.EvasObject evasObject)
443 Debug.Assert(_disposed == false);
444 ValidationUtil.ValidateEnum(typeof(DisplayType), type, nameof(type));
446 return CameraDisplay.SetTarget(GetHandle(), type, evasObject);
449 CameraError IDisplayable<CameraError>.ApplyEcoreWindow(IntPtr windowHandle)
451 throw new NotSupportedException("Camera does not support NUI.Window display.");
455 /// Gets the state of the camera.
457 /// <since_tizen> 3 </since_tizen>
458 /// <value> None, Created, Preview, Capturing, Captured.</value>
459 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
460 public CameraState State
464 ValidateNotDisposed();
466 CameraState val = CameraState.None;
467 CameraErrorFactory.ThrowIfError(Native.GetState(_handle, out val),
468 "Failed to get camera state");
475 /// The hint for the display reuse.
476 /// If the hint is set to true, the display will be reused when the camera device is changed with
477 /// the ChangeDevice method.
479 /// <since_tizen> 3 </since_tizen>
480 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
481 /// <exception cref="InvalidOperationException">An invalid state.</exception>
482 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
483 public bool DisplayReuseHint
487 ValidateNotDisposed();
489 CameraErrorFactory.ThrowIfError(Native.GetDisplayReuseHint(_handle, out bool val),
490 "Failed to get camera display reuse hint");
497 ValidateState(CameraState.Preview);
499 CameraErrorFactory.ThrowIfError(Native.SetDisplayReuseHint(_handle, value),
500 "Failed to set display reuse hint.");
505 /// Gets the facing direction of the camera module.
507 /// <since_tizen> 3 </since_tizen>
508 /// <value>A <see cref="CameraFacingDirection"/> that specifies the facing direction of the camera device.</value>
509 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
510 public CameraFacingDirection Direction
514 ValidateNotDisposed();
516 CameraErrorFactory.ThrowIfError(Native.GetFacingDirection(_handle, out var val),
517 "Failed to get camera direction");
524 /// Gets the camera device count.
526 /// <since_tizen> 3 </since_tizen>
527 /// <value>This returns 2, if the device supports primary and secondary cameras.
528 /// Otherwise 1, if the device only supports primary camera.</value>
529 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
530 public int CameraCount
534 ValidateNotDisposed();
536 CameraErrorFactory.ThrowIfError(Native.GetDeviceCount(_handle, out int val),
537 "Failed to get camera device count");
542 #endregion Properties
546 /// Changes the camera device.
548 /// <since_tizen> 3 </since_tizen>
549 /// <param name="device">The hardware camera to access.</param>
551 /// If display reuse is set using <see cref="DisplayReuseHint"/>
552 /// before stopping the preview, the display will be reused and last frame on the display
553 /// can be kept even though camera device is changed.
554 /// The camera must be in the <see cref="CameraState.Created"/>.
556 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
557 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
558 /// <exception cref="NotSupportedException">In case of the ChangeDevice feature is not supported.</exception>
559 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
560 public void ChangeDevice(CameraDevice device)
562 ValidateState(CameraState.Created);
563 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
565 CameraErrorFactory.ThrowIfError(Native.ChangeDevice(_handle, device),
566 "Failed to change the camera device");
570 /// Gets the device state.
572 /// <since_tizen> 3 </since_tizen>
573 /// <param name="device">The device to get the state.</param>
574 /// <returns>Returns the state of the camera device.</returns>
575 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
576 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
577 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
578 public static CameraDeviceState GetDeviceState(CameraDevice device)
580 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
582 CameraErrorFactory.ThrowIfError(Native.GetDeviceState(device, out var val),
583 "Failed to get the camera device state.");
589 /// Gets the flash state.
591 /// <since_tizen> 3 </since_tizen>
592 /// <param name="device">The device to get the state.</param>
593 /// <returns>Returns the flash state of the camera device.</returns>
594 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
595 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
596 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
597 public static CameraFlashState GetFlashState(CameraDevice device)
599 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
601 CameraErrorFactory.ThrowIfError(Native.GetFlashState(device, out var val),
602 "Failed to get camera flash state");
608 /// Starts capturing and drawing preview frames on the screen.
609 /// The display property must be set using <see cref="Display"/> before using this method.
610 /// If needed set fps <see cref="CameraSettings.PreviewFps"/>, preview resolution
611 /// <see cref="CameraSettings.PreviewResolution"/>, or preview format <see cref="CameraSettings.PreviewPixelFormat"/>
612 /// before using this method.
613 /// The camera must be in the <see cref="CameraState.Created"/> or the <see cref="CameraState.Captured"/> state.
615 /// <since_tizen> 3 </since_tizen>
617 /// http://tizen.org/privilege/camera
619 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
620 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
621 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
622 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
623 public void StartPreview()
625 ValidateState(CameraState.Created, CameraState.Captured);
627 CameraErrorFactory.ThrowIfError(Native.StartPreview(_handle),
628 "Failed to start the camera preview.");
630 // Update by StateChangedCallback can be delayed for dozens of milliseconds.
631 SetState(CameraState.Preview);
635 /// Stops capturing and drawing preview frames on the screen.
636 /// The camera must be in the <see cref="CameraState.Preview"/> state.
638 /// <since_tizen> 3 </since_tizen>
640 /// http://tizen.org/privilege/camera
642 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
643 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
644 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
645 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
646 public void StopPreview()
648 ValidateState(CameraState.Preview);
650 CameraErrorFactory.ThrowIfError(Native.StopPreview(_handle),
651 "Failed to stop the camera preview.");
653 SetState(CameraState.Created);
657 /// Starts capturing of still images.
658 /// EventHandler must be set for capturing using <see cref="Capturing"/>
659 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
660 /// The camera must be in the <see cref="CameraState.Preview"/> state.
662 /// <since_tizen> 3 </since_tizen>
664 /// http://tizen.org/privilege/camera
667 /// This function causes the transition of the camera state from capturing to captured
668 /// automatically and the corresponding EventHandlers will be invoked.
669 /// The preview should be restarted by calling the <see cref="StartPreview"/> method after capture is completed.
671 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
672 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
673 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
674 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
675 public void StartCapture()
677 ValidateState(CameraState.Preview);
679 CameraErrorFactory.ThrowIfError(Native.StartCapture(_handle, _capturingCallback, _captureCompletedCallback, IntPtr.Zero),
680 "Failed to start the camera capture.");
682 SetState(CameraState.Capturing);
686 /// Starts continuously capturing still images.
687 /// EventHandler must be set for capturing using <see cref="Capturing"/>
688 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
689 /// The camera must be in the <see cref="CameraState.Preview"/> state.
691 /// <since_tizen> 3 </since_tizen>
693 /// http://tizen.org/privilege/camera
695 /// <param name="count">The number of still images.</param>
696 /// <param name="interval">The interval of the capture(milliseconds).</param>
697 /// <param name="cancellationToken">The cancellation token to cancel capturing.</param>
698 /// <seealso cref="CancellationToken"/>
700 /// If this is not supported, zero shutter lag occurs. The capture resolution could be
701 /// changed to the preview resolution. This function causes the transition of the camera state
702 /// from capturing to captured automatically and the corresponding Eventhandlers will be invoked.
703 /// Each captured image will be delivered through Eventhandler set using the <see cref="Capturing"/> event.
704 /// The preview should be restarted by calling the <see cref="StartPreview"/> method after capture is completed.
706 /// <exception cref="ArgumentOutOfRangeException">In case of invalid parameters.</exception>
707 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
708 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
709 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
710 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
711 public void StartCapture(int count, int interval, CancellationToken cancellationToken)
713 ValidateState(CameraState.Preview);
717 throw new ArgumentOutOfRangeException(nameof(count), count, $"{nameof(count)} should be greater than one.");
722 throw new ArgumentOutOfRangeException(nameof(interval), interval, $"{nameof(interval)} should be greater than or equal to zero.");
725 //Handle CancellationToken
726 if (cancellationToken != CancellationToken.None)
728 cancellationToken.Register(() =>
730 CameraErrorFactory.ThrowIfError(Native.StopContinuousCapture(_handle),
731 "Failed to cancel the continuous capture");
732 SetState(CameraState.Captured);
736 CameraErrorFactory.ThrowIfError(Native.StartContinuousCapture(_handle, count, interval,
737 _capturingCallback, _captureCompletedCallback, IntPtr.Zero), "Failed to start the continuous capture.");
739 SetState(CameraState.Capturing);
743 /// Starts camera auto-focusing, asynchronously.
744 /// The camera must be in the <see cref="CameraState.Preview"/> or the <see cref="CameraState.Captured"/> state.
746 /// <since_tizen> 3 </since_tizen>
747 /// <param name="continuous">Continuous auto focus.</param>
749 /// http://tizen.org/privilege/camera
752 /// If continuous status is true, the camera continuously tries to focus.
754 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
755 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
756 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
757 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
758 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
759 public void StartFocusing(bool continuous)
761 ValidateState(CameraState.Preview, CameraState.Captured);
763 CameraErrorFactory.ThrowIfError(Native.StartFocusing(_handle, continuous),
764 "Failed to cancel the camera focus.");
768 /// Stops camera auto focusing.
769 /// The camera must be in the <see cref="CameraState.Preview"/> or the <see cref="CameraState.Captured"/> state.
771 /// <since_tizen> 3 </since_tizen>
773 /// http://tizen.org/privilege/camera
775 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
776 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
777 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
778 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
779 public void StopFocusing()
781 ValidateState(CameraState.Preview, CameraState.Captured);
783 CameraErrorFactory.ThrowIfError(Native.CancelFocusing(_handle),
784 "Failed to cancel the camera focus.");
788 /// Starts face detection.
789 /// The camera must be in the <see cref="CameraState.Preview"/> state.
791 /// <since_tizen> 3 </since_tizen>
793 /// http://tizen.org/privilege/camera
796 /// This should be called after <see cref="StartPreview"/> is started.
797 /// The Eventhandler set using <see cref="FaceDetected"/> is invoked when the face is detected in the preview frame.
798 /// Internally, it starts continuously focus and focusing on the detected face.
800 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
801 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
802 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
803 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
804 public void StartFaceDetection()
806 ValidateState(CameraState.Preview);
808 _faceDetectedCallback = (IntPtr faces, int count, IntPtr userData) =>
810 var result = new List<FaceDetectionData>();
811 IntPtr current = faces;
813 for (int i = 0; i < count; i++)
815 result.Add(new FaceDetectionData(current));
816 current = IntPtr.Add(current, Marshal.SizeOf<Native.DetectedFaceStruct>());
819 FaceDetected?.Invoke(this, new FaceDetectedEventArgs(result));
821 CameraErrorFactory.ThrowIfError(Native.StartFaceDetection(_handle, _faceDetectedCallback, IntPtr.Zero),
822 "Failed to start face detection");
826 /// Stops face detection.
828 /// <since_tizen> 3 </since_tizen>
830 /// http://tizen.org/privilege/camera
832 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
833 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
834 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
835 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
836 public void StopFaceDetection()
838 if (_faceDetectedCallback == null)
840 throw new InvalidOperationException("The face detection is not started.");
843 CameraErrorFactory.ThrowIfError(Native.StopFaceDetection(_handle),
844 "Failed to stop the face detection.");
846 _faceDetectedCallback = null;
850 #region Callback registrations
851 private void RegisterCallbacks()
853 RegisterErrorCallback();
854 RegisterFocusStateChanged();
855 RegisterInterruptStartedCallback();
856 RegisterInterruptedCallback();
857 RegisterStateChangedCallback();
859 //Define capturing callback
860 _capturingCallback = (IntPtr main, IntPtr postview, IntPtr thumbnail, IntPtr userData) =>
862 Capturing?.Invoke(this, new CameraCapturingEventArgs(new StillImage(main),
863 postview == IntPtr.Zero ? null : new StillImage(postview),
864 thumbnail == IntPtr.Zero ? null : new StillImage(thumbnail)));
867 //Define captureCompleted callback
868 _captureCompletedCallback = _ =>
870 SetState(CameraState.Captured);
871 CaptureCompleted?.Invoke(this, EventArgs.Empty);
875 private void RegisterInterruptStartedCallback()
877 _interruptStartedCallback = (CameraPolicy policy, CameraState state, IntPtr userData) =>
879 InterruptStarted?.Invoke(this, new CameraInterruptStartedEventArgs(policy, state));
881 CameraErrorFactory.ThrowIfError(Native.SetInterruptStartedCallback(_handle, _interruptStartedCallback, IntPtr.Zero),
882 "Failed to set interrupt callback");
885 private void RegisterInterruptedCallback()
887 _interruptedCallback = (CameraPolicy policy, CameraState previous, CameraState current, IntPtr userData) =>
889 Interrupted?.Invoke(this, new CameraInterruptedEventArgs(policy, previous, current));
891 CameraErrorFactory.ThrowIfError(Native.SetInterruptedCallback(_handle, _interruptedCallback, IntPtr.Zero),
892 "Failed to set interrupt callback");
895 private void RegisterErrorCallback()
897 _errorCallback = (CameraErrorCode error, CameraState current, IntPtr userData) =>
899 ErrorOccurred?.Invoke(this, new CameraErrorOccurredEventArgs(error, current));
901 CameraErrorFactory.ThrowIfError(Native.SetErrorCallback(_handle, _errorCallback, IntPtr.Zero),
902 "Setting error callback failed");
905 private void RegisterStateChangedCallback()
907 _stateChangedCallback = (CameraState previous, CameraState current, bool byPolicy, IntPtr _) =>
910 Log.Info(CameraLog.Tag, "Camera state changed " + previous.ToString() + " -> " + current.ToString());
911 StateChanged?.Invoke(this, new CameraStateChangedEventArgs(previous, current, byPolicy));
913 CameraErrorFactory.ThrowIfError(Native.SetStateChangedCallback(_handle, _stateChangedCallback, IntPtr.Zero),
914 "Setting state changed callback failed");
917 private static void RegisterDeviceStateChangedCallback()
919 _deviceStateChangedCallback = (CameraDevice device, CameraDeviceState state, IntPtr userData) =>
921 _deviceStateChanged?.Invoke(null, new CameraDeviceStateChangedEventArgs(device, state));
924 CameraErrorFactory.ThrowIfError(Native.SetDeviceStateChangedCallback(_deviceStateChangedCallback, IntPtr.Zero, out _deviceStateCallbackId),
925 "Failed to set device state changed callback");
927 Log.Info(CameraLog.Tag, "add callbackId " + _deviceStateCallbackId.ToString());
930 private static void UnregisterDeviceStateChangedCallback()
932 CameraErrorFactory.ThrowIfError(Native.UnsetDeviceStateChangedCallback(_deviceStateCallbackId),
933 "Unsetting device state changed callback failed");
934 _deviceStateChangedCallback = null;
935 _deviceStateCallbackId = 0;
938 private void RegisterFocusStateChanged()
940 _focusStateChangedCallback = (CameraFocusState state, IntPtr userData) =>
942 FocusStateChanged?.Invoke(this, new CameraFocusStateChangedEventArgs(state));
944 CameraErrorFactory.ThrowIfError(Native.SetFocusStateChangedCallback(_handle, _focusStateChangedCallback, IntPtr.Zero),
945 "Setting focus changed callback failed");
948 private void RegisterHdrCaptureProgress()
950 _hdrCaptureProgressCallback = (int percent, IntPtr userData) =>
952 _hdrCaptureProgress?.Invoke(this, new HdrCaptureProgressEventArgs(percent));
954 CameraErrorFactory.ThrowIfError(Native.SetHdrCaptureProgressCallback(_handle, _hdrCaptureProgressCallback, IntPtr.Zero),
955 "Setting Hdr capture progress callback failed");
958 private void UnregisterHdrCaptureProgress()
960 CameraErrorFactory.ThrowIfError(Native.UnsetHdrCaptureProgressCallback(_handle),
961 "Unsetting hdr capture progress is failed");
962 _hdrCaptureProgressCallback = null;
965 private void RegisterPreviewCallback()
967 _previewCallback = (IntPtr frame, IntPtr userData) =>
969 _preview?.Invoke(this, new PreviewEventArgs(new PreviewFrame(frame)));
971 CameraErrorFactory.ThrowIfError(Native.SetPreviewCallback(_handle, _previewCallback, IntPtr.Zero),
972 "Setting preview callback failed");
975 private void UnregisterPreviewCallback()
977 CameraErrorFactory.ThrowIfError(Native.UnsetPreviewCallback(_handle),
978 "Unsetting preview callback failed");
979 _previewCallback = null;
982 private void RegisterMediaPacketPreviewCallback()
984 _mediaPacketPreviewCallback = (IntPtr mediaPacket, IntPtr userData) =>
986 MediaPacket packet = MediaPacket.From(mediaPacket);
987 var eventHandler = _mediaPacketPreview;
989 if (eventHandler != null)
991 eventHandler.Invoke(this, new MediaPacketPreviewEventArgs(packet));
998 CameraErrorFactory.ThrowIfError(Native.SetMediaPacketPreviewCallback(_handle, _mediaPacketPreviewCallback, IntPtr.Zero),
999 "Setting media packet preview callback failed");
1002 private void UnregisterMediaPacketPreviewCallback()
1004 CameraErrorFactory.ThrowIfError(Native.UnsetMediaPacketPreviewCallback(_handle),
1005 "Unsetting media packet preview callback failed");
1006 _mediaPacketPreviewCallback = null;
1008 #endregion Callback registrations