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;
46 private static Dictionary<object, int> _callbackIdInfo = new Dictionary<object, int>();
49 /// Initializes a new instance of the <see cref="Camera"/> Class.
51 /// <since_tizen> 3 </since_tizen>
52 /// <param name="device">The camera device to access</param>
53 public Camera(CameraDevice device)
55 CameraErrorFactory.ThrowIfError(Native.Create(device, out _handle),
56 "Failed to create camera instance");
58 Feature = new CameraFeatures(this);
59 Setting = new CameraSettings(this);
60 DisplaySettings = new CameraDisplaySettings(this);
64 SetState(CameraState.Created);
68 /// Destructor of the camera class.
75 public IntPtr Handle => GetHandle();
77 internal IntPtr GetHandle()
79 ValidateNotDisposed();
83 #region Dispose support
85 /// Releases the unmanaged resources used by the Camera.
87 /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
88 protected virtual void Dispose(bool disposing)
94 // to be used if there are any other disposable objects
97 if (_handle != IntPtr.Zero)
99 Native.Destroy(_handle);
100 _handle = IntPtr.Zero;
108 /// Releases all resources used by the Camera.
110 /// <since_tizen> 3 </since_tizen>
111 public void Dispose()
113 ReplaceDisplay(null);
115 GC.SuppressFinalize(this);
118 internal void ValidateNotDisposed()
122 Log.Error(CameraLog.Tag, "Camera handle is disposed.");
123 throw new ObjectDisposedException(nameof(Camera));
126 #endregion Dispose support
128 #region Check camera state
129 internal void ValidateState(params CameraState[] required)
131 ValidateNotDisposed();
133 Debug.Assert(required.Length > 0);
135 var curState = _state;
136 if (!required.Contains(curState))
138 throw new InvalidOperationException($"The camera is not in a valid state. " +
139 $"Current State : { curState }, Valid State : { string.Join(", ", required) }.");
143 internal void SetState(CameraState state)
147 #endregion Check camera state
149 #region EventHandlers
151 /// Event that occurs when an camera is interrupted by policy.
153 /// <since_tizen> 3 </since_tizen>
154 public event EventHandler<CameraInterruptedEventArgs> Interrupted;
155 private Native.InterruptedCallback _interruptedCallback;
158 /// Event that occurs when there is an asynchronous error.
160 /// <since_tizen> 3 </since_tizen>
161 public event EventHandler<CameraErrorOccurredEventArgs> ErrorOccurred;
162 private Native.ErrorCallback _errorCallback;
165 /// Event that occurs when the auto focus state is changed.
167 /// <since_tizen> 3 </since_tizen>
168 public event EventHandler<CameraFocusStateChangedEventArgs> FocusStateChanged;
169 private Native.FocusStateChangedCallback _focusStateChangedCallback;
172 /// Event that occurs when a face is detected in preview frame.
174 /// <since_tizen> 3 </since_tizen>
175 public event EventHandler<FaceDetectedEventArgs> FaceDetected;
176 private Native.FaceDetectedCallback _faceDetectedCallback;
179 /// Event that occurs during capture of image.
181 /// <since_tizen> 3 </since_tizen>
182 public event EventHandler<CameraCapturingEventArgs> Capturing;
183 private Native.CapturingCallback _capturingCallback;
186 /// Event that occurs after the capture of the image.
188 /// <since_tizen> 3 </since_tizen>
189 public event EventHandler<EventArgs> CaptureCompleted;
190 private Native.CaptureCompletedCallback _captureCompletedCallback;
193 /// Event that occurs when there is change in HDR capture progress.
194 /// Check whether HdrCapture feature is supported or not before add this EventHandler.
196 /// <since_tizen> 3 </since_tizen>
197 public event EventHandler<HdrCaptureProgressEventArgs> HdrCaptureProgress;
198 private Native.HdrCaptureProgressCallback _hdrCaptureProgressCallback;
201 /// Event that occurs when camera state is changed.
203 /// <since_tizen> 3 </since_tizen>
204 public event EventHandler<CameraStateChangedEventArgs> StateChanged;
205 private Native.StateChangedCallback _stateChangedCallback;
207 #region DeviceStateChanged callback
208 internal static Native.DeviceStateChangedCallback _deviceStateChangedCallback;
209 private static event EventHandler<CameraDeviceStateChangedEventArgs> _deviceStateChanged;
210 private static object _deviceStateChangedEventLock = new object();
213 /// Set the DeviceStateChanged Callback.
214 /// User doesn't need to create camera instance.
215 /// This static EventHandler calls platform function every time because each callback function have to remain its own callbackId.
217 /// <since_tizen> 3 </since_tizen>
218 /// <param name="callback">Callback of type <see cref="Native.DeviceStateChangedCallback"/>.</param>
219 /// <param name="callbackId">The Id of registered callback.</param>
220 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
221 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
222 /// <exception cref="ArgumentException">In case of invalid parameters</exception>
223 public static event EventHandler<CameraDeviceStateChangedEventArgs> DeviceStateChanged
227 lock (_deviceStateChangedEventLock)
229 _deviceStateChangedCallback = (CameraDevice device, CameraDeviceState state, IntPtr userData) =>
231 _deviceStateChanged?.Invoke(null, new CameraDeviceStateChangedEventArgs(device, state));
233 CameraErrorFactory.ThrowIfError(Native.SetDeviceStateChangedCallback(_deviceStateChangedCallback, IntPtr.Zero, out int callbackId),
234 "Failed to set interrupt callback");
236 // Keep current callbackId and EventHandler pair to remove EventHandler later.
237 _callbackIdInfo.Add(value, callbackId);
238 Log.Info(CameraLog.Tag, "add callbackId " + callbackId.ToString());
240 _deviceStateChanged += value;
246 lock (_deviceStateChangedEventLock)
248 _deviceStateChanged -= value;
250 _callbackIdInfo.TryGetValue(value, out int callbackId);
251 Log.Info(CameraLog.Tag, "remove callbackId " + callbackId.ToString());
253 CameraErrorFactory.ThrowIfError(Native.UnsetDeviceStateChangedCallback(callbackId),
254 "Unsetting media packet preview callback failed");
256 _callbackIdInfo.Remove(value);
258 if (_deviceStateChanged == null)
260 _deviceStateChangedCallback = null;
265 #endregion DeviceStateChanged callback
267 #region Preview EventHandler
268 private Native.PreviewCallback _previewCallback;
269 private event EventHandler<PreviewEventArgs> _preview;
270 private object _previewEventLock = new object();
272 /// Event that occurs once per frame when previewing.
273 /// Preview callback is registered when user add callback explicitly to avoid useless P/Invoke.
275 /// <since_tizen> 3 </since_tizen>
276 public event EventHandler<PreviewEventArgs> Preview
280 lock (_previewEventLock)
282 if (_preview == null)
284 RegisterPreviewCallback();
293 lock (_previewEventLock)
297 if (_preview == null)
299 CameraErrorFactory.ThrowIfError(Native.UnsetPreviewCallback(_handle),
300 "Unsetting preview callback failed");
301 _previewCallback = null;
306 #endregion Preview EventHandler
308 #region MediaPacketPreview EventHandler
309 private Native.MediaPacketPreviewCallback _mediaPacketPreviewCallback;
310 private EventHandler<MediaPacketPreviewEventArgs> _mediaPacketPreview;
311 private object _mediaPacketPreviewEventLock = new object();
314 /// Event that occurs once per frame when previewing.
315 /// Preview callback is registered when user add callback explicitly to avoid useless P/Invoke.
317 /// <since_tizen> 3 </since_tizen>
318 public event EventHandler<MediaPacketPreviewEventArgs> MediaPacketPreview
322 lock (_mediaPacketPreviewEventLock)
324 if (_mediaPacketPreview == null)
326 RegisterMediaPacketPreviewCallback();
329 _mediaPacketPreview += value;
335 lock (_mediaPacketPreviewEventLock)
337 _mediaPacketPreview -= value;
339 if (_mediaPacketPreview == null)
341 CameraErrorFactory.ThrowIfError(Native.UnsetMediaPacketPreviewCallback(_handle),
342 "Unsetting media packet preview callback failed");
343 _mediaPacketPreviewCallback = null;
348 #endregion MediaPacketPreview EventHandler
349 #endregion EventHandlers
353 /// Get/Set the various camera settings.
355 /// <since_tizen> 3 </since_tizen>
356 public CameraSettings Setting { get; }
359 /// Gets the various camera features.
361 /// <since_tizen> 3 </since_tizen>
362 public CameraFeatures Feature { get; }
365 /// Get/set various camera display properties.
367 /// <since_tizen> 3 </since_tizen>
368 public CameraDisplaySettings DisplaySettings{ get; }
370 private Display _display;
372 private CameraError SetDisplay(Display display)
376 return CameraDisplay.SetTarget(GetHandle(), DisplayType.None, IntPtr.Zero);
379 return display.ApplyTo(this);
382 private void ReplaceDisplay(Display newDisplay)
384 if (_display != null)
386 _display.Owner = null;
388 _display = newDisplay;
389 if (_display != null)
391 _display.Owner = this;
396 /// Sets or gets the display type and handle to show preview images.
397 /// The camera must be in the <see cref="CameraState.Created"/> state.
399 /// <since_tizen> 3 </since_tizen>
401 /// This must be set before StartPreview() method.
402 /// In Custom ROI display mode, DisplayRoiArea property must be set before calling this method.
404 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
405 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
406 /// <exception cref="ObjectDisposedException" > The camera already has been disposed.</exception>
407 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
408 public Display Display
417 ValidateState(CameraState.Created);
419 if (value != null && value.Owner != null)
421 if (ReferenceEquals(this, value.Owner))
427 throw new ArgumentException("The display has already been assigned to another.");
430 CameraErrorFactory.ThrowIfError(SetDisplay(value), "Failed to set the camera display");
432 ReplaceDisplay(value);
436 CameraError IDisplayable<CameraError>.ApplyEvasDisplay(DisplayType type, ElmSharp.EvasObject evasObject)
438 Debug.Assert(_disposed == false);
439 ValidationUtil.ValidateEnum(typeof(DisplayType), type, nameof(type));
441 return CameraDisplay.SetTarget(GetHandle(), type, evasObject);
445 /// Gets the state of the camera.
447 /// <since_tizen> 3 </since_tizen>
448 /// <value> None, Created, Preview, Capturing, Captured </value>
449 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
450 public CameraState State
454 ValidateNotDisposed();
456 CameraState val = CameraState.None;
457 CameraErrorFactory.ThrowIfError(Native.GetState(_handle, out val),
458 "Failed to get camera state");
465 /// The hint for display reuse.
466 /// If the hint is set to true, the display will be reused when the camera device is changed with
467 /// ChangeDevice method.
469 /// <since_tizen> 3 </since_tizen>
470 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
471 /// <exception cref="InvalidOperationException">Invalid state.</exception>
472 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
473 public bool DisplayReuseHint
477 ValidateNotDisposed();
479 CameraErrorFactory.ThrowIfError(Native.GetDisplayReuseHint(_handle, out bool val),
480 "Failed to get camera display reuse hint");
487 ValidateState(CameraState.Preview);
489 CameraErrorFactory.ThrowIfError(Native.SetDisplayReuseHint(_handle, value),
490 "Failed to set display reuse hint.");
495 /// Gets the facing direction of camera module.
497 /// <since_tizen> 3 </since_tizen>
498 /// <value>A <see cref="CameraFacingDirection"/> that specifies the facing direction of camera device.</value>
499 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
500 public CameraFacingDirection Direction
504 ValidateNotDisposed();
506 CameraErrorFactory.ThrowIfError(Native.GetFacingDirection(_handle, out var val),
507 "Failed to get camera direction");
514 /// Gets the camera device count.
516 /// <since_tizen> 3 </since_tizen>
517 /// <value>This returns 2, if the device supports primary and secondary cameras.
518 /// Otherwise 1, if the device only supports primary camera.</value>
519 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
520 public int CameraCount
524 ValidateNotDisposed();
526 CameraErrorFactory.ThrowIfError(Native.GetDeviceCount(_handle, out int val),
527 "Failed to get camera device count");
532 #endregion Properties
536 /// Changes the camera device.
538 /// <since_tizen> 3 </since_tizen>
539 /// <param name="device">The hardware camera to access.</param>
541 /// If display reuse is set using <see cref="DisplayReuseHint"/>
542 /// before stopping the preview, the display will be reused and last frame on the display
543 /// can be kept even though camera device is changed.
544 /// The camera must be in the <see cref="CameraState.Created"/>.
546 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
547 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
548 /// <exception cref="NotSupportedException">In case of ChangeDevice feature is not supported.</exception>
549 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
550 public void ChangeDevice(CameraDevice device)
552 ValidateState(CameraState.Created);
553 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
555 CameraErrorFactory.ThrowIfError(Native.ChangeDevice(_handle, device),
556 "Failed to change the camera device");
560 /// Gets the device state.
562 /// <since_tizen> 3 </since_tizen>
563 /// <param name="device">The device to get state.</param>
564 /// <returns>Returns the state of camera device</returns>
565 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
566 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
567 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
568 public CameraDeviceState GetDeviceState(CameraDevice device)
570 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
572 CameraErrorFactory.ThrowIfError(Native.GetDeviceState(device, out var val),
573 "Failed to get the camera device state.");
579 /// Gets the flash state.
581 /// <since_tizen> 3 </since_tizen>
582 /// <param name="device">The device to get state.</param>
583 /// <returns>Returns the flash state of camera device</returns>
584 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
585 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
586 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
587 public static CameraFlashState GetFlashState(CameraDevice device)
589 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
591 CameraErrorFactory.ThrowIfError(Native.GetFlashState(device, out var val),
592 "Failed to get camera flash state");
598 /// Starts capturing and drawing preview frames on the screen.
599 /// The display handle must be set using <see cref="CameraDisplaySettings.SetInfo"/>
600 /// before using this method.
601 /// If needed set fps <see cref="CameraSettings.PreviewFps"/>, preview resolution
602 /// <see cref="CameraSettings.PreviewResolution"/>, or preview format <see cref="CameraSettings.PreviewPixelFormat"/>
603 /// before using this method.
604 /// The camera must be in the <see cref="CameraState.Created"/> or <see cref="CameraState.Captured"/> state.
606 /// <since_tizen> 3 </since_tizen>
608 /// http://tizen.org/privilege/camera
610 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
611 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
612 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
613 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
614 public void StartPreview()
616 ValidateState(CameraState.Created, CameraState.Captured);
618 CameraErrorFactory.ThrowIfError(Native.StartPreview(_handle),
619 "Failed to start the camera preview.");
621 // Update by StateChangedCallback can be delayed for dozens of milliseconds.
622 SetState(CameraState.Preview);
626 /// Stops capturing and drawing preview frames on the screen.
627 /// The camera must be in the <see cref="CameraState.Preview"/> state.
629 /// <since_tizen> 3 </since_tizen>
631 /// http://tizen.org/privilege/camera
633 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
634 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
635 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
636 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
637 public void StopPreview()
639 ValidateState(CameraState.Preview);
641 CameraErrorFactory.ThrowIfError(Native.StopPreview(_handle),
642 "Failed to stop the camera preview.");
644 SetState(CameraState.Created);
648 /// Starts capturing of still images.
649 /// EventHandler must be set for capturing using <see cref="Capturing"/>
650 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
651 /// The camera must be in the <see cref="CameraState.Preview"/> state.
653 /// <since_tizen> 3 </since_tizen>
655 /// http://tizen.org/privilege/camera
658 /// This function causes the transition of the camera state from Capturing to Captured
659 /// automatically and the corresponding EventHandlers will be invoked.
660 /// The preview should be restarted by calling <see cref="StartPreview"/> method after capture is completed.
662 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
663 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
664 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
665 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
666 public void StartCapture()
668 ValidateState(CameraState.Preview);
670 CameraErrorFactory.ThrowIfError(Native.StartCapture(_handle, _capturingCallback, _captureCompletedCallback, IntPtr.Zero),
671 "Failed to start the camera capture.");
673 SetState(CameraState.Capturing);
677 /// Starts continuously capturing still images.
678 /// EventHandler must be set for capturing using <see cref="Capturing"/>
679 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
680 /// The camera must be in the <see cref="CameraState.Preview"/> state.
682 /// <since_tizen> 3 </since_tizen>
684 /// http://tizen.org/privilege/camera
686 /// <param name="count">The number of still images.</param>
687 /// <param name="interval">The interval of the capture(milliseconds).</param>
688 /// <param name="cancellationToken">The cancellation token to cancel capturing.</param>
689 /// <seealso cref="System.Threading.CancellationToken"/>
691 /// If this is not supported zero shutter lag occurs. The capture resolution could be
692 /// changed to the preview resolution. This function causes the transition of the camera state
693 /// from Capturing to Captured automatically and the corresponding Eventhandlers will be invoked.
694 /// Each captured image will be delivered through Eventhandler set using <see cref="Capturing"/> event.
695 /// The preview should be restarted by calling <see cref="StartPreview"/> method after capture is completed.
697 /// <exception cref="ArgumentOutOfRangeException">In case of invalid parameters.</exception>
698 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
699 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
700 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
701 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
702 public void StartCapture(int count, int interval, CancellationToken cancellationToken)
704 ValidateState(CameraState.Preview);
708 throw new ArgumentOutOfRangeException(nameof(count), count, $"{nameof(count)} should be greater than one.");
713 throw new ArgumentOutOfRangeException(nameof(interval), interval, $"{nameof(interval)} should be greater than or equal to zero.");
716 //Handle CancellationToken
717 if (cancellationToken != CancellationToken.None)
719 cancellationToken.Register(() =>
721 CameraErrorFactory.ThrowIfError(Native.StopContinuousCapture(_handle),
722 "Failed to cancel the continuous capture");
723 SetState(CameraState.Captured);
727 CameraErrorFactory.ThrowIfError(Native.StartContinuousCapture(_handle, count, interval,
728 _capturingCallback, _captureCompletedCallback, IntPtr.Zero), "Failed to start the continuous capture.");
730 SetState(CameraState.Capturing);
734 /// Starts camera auto-focusing, asynchronously.
735 /// The camera must be in the <see cref="CameraState.Preview"/> or <see cref="CameraState.Captured"/> state.
737 /// <since_tizen> 3 </since_tizen>
738 /// <param name="continuous">Continuous auto focus</param>
740 /// http://tizen.org/privilege/camera
743 /// If continuous status is true, the camera continuously tries to focus.
745 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
746 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
747 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
748 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
749 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
750 public void StartFocusing(bool continuous)
752 ValidateState(CameraState.Preview, CameraState.Captured);
754 CameraErrorFactory.ThrowIfError(Native.StartFocusing(_handle, continuous),
755 "Failed to cancel the camera focus.");
759 /// Stops camera auto focusing.
760 /// The camera must be in the <see cref="CameraState.Preview"/> or <see cref="CameraState.Captured"/> state.
762 /// <since_tizen> 3 </since_tizen>
764 /// http://tizen.org/privilege/camera
766 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
767 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
768 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
769 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
770 public void StopFocusing()
772 ValidateState(CameraState.Preview, CameraState.Captured);
774 CameraErrorFactory.ThrowIfError(Native.CancelFocusing(_handle),
775 "Failed to cancel the camera focus.");
779 /// Starts face detection.
780 /// The camera must be in the <see cref="CameraState.Preview"/> state.
782 /// <since_tizen> 3 </since_tizen>
784 /// http://tizen.org/privilege/camera
787 /// This should be called after <see cref="StartPreview"/> is started.
788 /// The Eventhandler set using <see cref="FaceDetected"/> invoked when the face is detected in preview frame.
789 /// Internally it starts continuous focus and focusing on the detected face.
791 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
792 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
793 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
794 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
795 public void StartFaceDetection()
797 ValidateState(CameraState.Preview);
799 _faceDetectedCallback = (IntPtr faces, int count, IntPtr userData) =>
801 var result = new List<FaceDetectionData>();
802 IntPtr current = faces;
804 for (int i = 0; i < count; i++)
806 result.Add(new FaceDetectionData(current));
807 current = IntPtr.Add(current, Marshal.SizeOf<Native.DetectedFaceStruct>());
810 FaceDetected?.Invoke(this, new FaceDetectedEventArgs(result));
812 CameraErrorFactory.ThrowIfError(Native.StartFaceDetection(_handle, _faceDetectedCallback, IntPtr.Zero),
813 "Failed to start face detection");
817 /// Stops face detection.
819 /// <since_tizen> 3 </since_tizen>
821 /// http://tizen.org/privilege/camera
823 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
824 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
825 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
826 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
827 public void StopFaceDetection()
829 if (_faceDetectedCallback == null)
831 throw new InvalidOperationException("The face detection is not started.");
834 CameraErrorFactory.ThrowIfError(Native.StopFaceDetection(_handle),
835 "Failed to stop the face detection.");
837 _faceDetectedCallback = null;
841 #region Callback registrations
842 private void RegisterCallbacks()
844 RegisterErrorCallback();
845 RegisterFocusStateChanged();
846 RegisterHdrCaptureProgress();
847 RegisterInterruptedCallback();
848 RegisterStateChangedCallback();
850 //Define capturing callback
851 _capturingCallback = (IntPtr image, IntPtr postview, IntPtr thumbnail, IntPtr userData) =>
853 Capturing?.Invoke(this, new CameraCapturingEventArgs(new ImageData(image),
854 postview == IntPtr.Zero ? null : new ImageData(postview),
855 thumbnail == IntPtr.Zero ? null : new ImageData(thumbnail)));
858 //Define captureCompleted callback
859 _captureCompletedCallback = _ =>
861 SetState(CameraState.Captured);
862 CaptureCompleted?.Invoke(this, EventArgs.Empty);
866 private void RegisterInterruptedCallback()
868 _interruptedCallback = (CameraPolicy policy, CameraState previous, CameraState current, IntPtr userData) =>
870 Interrupted?.Invoke(this, new CameraInterruptedEventArgs(policy, previous, current));
872 CameraErrorFactory.ThrowIfError(Native.SetInterruptedCallback(_handle, _interruptedCallback, IntPtr.Zero),
873 "Failed to set interrupt callback");
876 private void RegisterErrorCallback()
878 _errorCallback = (CameraErrorCode error, CameraState current, IntPtr userData) =>
880 ErrorOccurred?.Invoke(this, new CameraErrorOccurredEventArgs(error, current));
882 CameraErrorFactory.ThrowIfError(Native.SetErrorCallback(_handle, _errorCallback, IntPtr.Zero),
883 "Setting error callback failed");
886 private void RegisterStateChangedCallback()
888 _stateChangedCallback = (CameraState previous, CameraState current, bool byPolicy, IntPtr _) =>
891 Log.Info(CameraLog.Tag, "Camera state changed " + previous.ToString() + " -> " + current.ToString());
892 StateChanged?.Invoke(this, new CameraStateChangedEventArgs(previous, current, byPolicy));
894 CameraErrorFactory.ThrowIfError(Native.SetStateChangedCallback(_handle, _stateChangedCallback, IntPtr.Zero),
895 "Setting state changed callback failed");
898 private void RegisterFocusStateChanged()
900 _focusStateChangedCallback = (CameraFocusState state, IntPtr userData) =>
902 FocusStateChanged?.Invoke(this, new CameraFocusStateChangedEventArgs(state));
904 CameraErrorFactory.ThrowIfError(Native.SetFocusStateChangedCallback(_handle, _focusStateChangedCallback, IntPtr.Zero),
905 "Setting focus changed callback failed");
908 private void RegisterHdrCaptureProgress()
910 //Hdr Capture can not be supported.
911 if (Feature.IsHdrCaptureSupported)
913 _hdrCaptureProgressCallback = (int percent, IntPtr userData) =>
915 HdrCaptureProgress?.Invoke(this, new HdrCaptureProgressEventArgs(percent));
917 CameraErrorFactory.ThrowIfError(Native.SetHdrCaptureProgressCallback(_handle, _hdrCaptureProgressCallback, IntPtr.Zero),
918 "Setting Hdr capture progress callback failed");
922 private void RegisterPreviewCallback()
924 _previewCallback = (IntPtr frame, IntPtr userData) =>
926 _preview?.Invoke(this, new PreviewEventArgs(new PreviewData(frame)));
928 CameraErrorFactory.ThrowIfError(Native.SetPreviewCallback(_handle, _previewCallback, IntPtr.Zero),
929 "Setting preview callback failed");
932 private void RegisterMediaPacketPreviewCallback()
934 _mediaPacketPreviewCallback = (IntPtr mediaPacket, IntPtr userData) =>
936 MediaPacket packet = MediaPacket.From(mediaPacket);
937 var eventHandler = _mediaPacketPreview;
939 if (eventHandler != null)
941 eventHandler.Invoke(this, new MediaPacketPreviewEventArgs(packet));
948 CameraErrorFactory.ThrowIfError(Native.SetMediaPacketPreviewCallback(_handle, _mediaPacketPreviewCallback, IntPtr.Zero),
949 "Setting media packet preview callback failed");
951 #endregion Callback registrations