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)
231 _deviceStateChangedCallback = (CameraDevice device, CameraDeviceState state, IntPtr userData) =>
233 _deviceStateChanged?.Invoke(null, new CameraDeviceStateChangedEventArgs(device, state));
235 CameraErrorFactory.ThrowIfError(Native.SetDeviceStateChangedCallback(_deviceStateChangedCallback, IntPtr.Zero, out callbackId),
236 "Failed to set interrupt callback");
238 // Keep current callbackId and EventHandler pair to remove EventHandler later.
239 _callbackIdInfo.Add(value, callbackId);
240 Log.Info(CameraLog.Tag, "add callbackId " + callbackId.ToString());
242 _deviceStateChanged += value;
248 lock (_deviceStateChangedEventLock)
250 _deviceStateChanged -= value;
253 _callbackIdInfo.TryGetValue(value, out callbackId);
254 Log.Info(CameraLog.Tag, "remove callbackId " + callbackId.ToString());
256 CameraErrorFactory.ThrowIfError(Native.UnsetDeviceStateChangedCallback(callbackId),
257 "Unsetting media packet preview callback failed");
259 _callbackIdInfo.Remove(value);
261 if (_deviceStateChanged == null)
263 _deviceStateChangedCallback = null;
268 #endregion DeviceStateChanged callback
270 #region Preview EventHandler
271 private Native.PreviewCallback _previewCallback;
272 private event EventHandler<PreviewEventArgs> _preview;
273 private object _previewEventLock = new object();
275 /// Event that occurs once per frame when previewing.
276 /// Preview callback is registered when user add callback explicitly to avoid useless P/Invoke.
278 /// <since_tizen> 3 </since_tizen>
279 public event EventHandler<PreviewEventArgs> Preview
283 lock (_previewEventLock)
285 if (_preview == null)
287 RegisterPreviewCallback();
296 lock (_previewEventLock)
300 if (_preview == null)
302 CameraErrorFactory.ThrowIfError(Native.UnsetPreviewCallback(_handle),
303 "Unsetting preview callback failed");
304 _previewCallback = null;
309 #endregion Preview EventHandler
311 #region MediaPacketPreview EventHandler
312 private Native.MediaPacketPreviewCallback _mediaPacketPreviewCallback;
313 private EventHandler<MediaPacketPreviewEventArgs> _mediaPacketPreview;
314 private object _mediaPacketPreviewEventLock = new object();
317 /// Event that occurs once per frame when previewing.
318 /// Preview callback is registered when user add callback explicitly to avoid useless P/Invoke.
320 /// <since_tizen> 3 </since_tizen>
321 public event EventHandler<MediaPacketPreviewEventArgs> MediaPacketPreview
325 lock (_mediaPacketPreviewEventLock)
327 if (_mediaPacketPreview == null)
329 RegisterMediaPacketPreviewCallback();
332 _mediaPacketPreview += value;
338 lock (_mediaPacketPreviewEventLock)
340 _mediaPacketPreview -= value;
342 if (_mediaPacketPreview == null)
344 CameraErrorFactory.ThrowIfError(Native.UnsetMediaPacketPreviewCallback(_handle),
345 "Unsetting media packet preview callback failed");
346 _mediaPacketPreviewCallback = null;
351 #endregion MediaPacketPreview EventHandler
352 #endregion EventHandlers
356 /// Get/Set the various camera settings.
358 /// <since_tizen> 3 </since_tizen>
359 public CameraSettings Setting { get; }
362 /// Gets the various camera features.
364 /// <since_tizen> 3 </since_tizen>
365 public CameraFeatures Feature { get; }
368 /// Get/set various camera display properties.
370 /// <since_tizen> 3 </since_tizen>
371 public CameraDisplaySettings DisplaySettings{ get; }
373 private Display _display;
375 private CameraError SetDisplay(Display display)
379 return CameraDisplay.SetTarget(GetHandle(), DisplayType.None, IntPtr.Zero);
382 return display.ApplyTo(this);
385 private void ReplaceDisplay(Display newDisplay)
387 if (_display != null)
389 _display.Owner = null;
391 _display = newDisplay;
392 if (_display != null)
394 _display.Owner = this;
399 /// Sets or gets the display type and handle to show preview images.
400 /// The camera must be in the <see cref="CameraState.Created"/> state.
402 /// <since_tizen> 3 </since_tizen>
404 /// This must be set before StartPreview() method.
405 /// In Custom ROI display mode, DisplayRoiArea property must be set before calling this method.
407 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
408 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
409 /// <exception cref="ObjectDisposedException" > The camera already has been disposed.</exception>
410 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
411 public Display Display
420 ValidateState(CameraState.Created);
422 if (value != null && value.Owner != null)
424 if (ReferenceEquals(this, value.Owner))
430 throw new ArgumentException("The display has already been assigned to another.");
433 CameraErrorFactory.ThrowIfError(SetDisplay(value), "Failed to set the camera display");
435 ReplaceDisplay(value);
439 CameraError IDisplayable<CameraError>.ApplyEvasDisplay(DisplayType type, ElmSharp.EvasObject evasObject)
441 Debug.Assert(_disposed == false);
442 ValidationUtil.ValidateEnum(typeof(DisplayType), type, nameof(type));
444 return CameraDisplay.SetTarget(GetHandle(), type, evasObject);
448 /// Gets the state of the camera.
450 /// <since_tizen> 3 </since_tizen>
451 /// <value> None, Created, Preview, Capturing, Captured </value>
452 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
453 public CameraState State
457 ValidateNotDisposed();
459 CameraState val = CameraState.None;
460 CameraErrorFactory.ThrowIfError(Native.GetState(_handle, out val),
461 "Failed to get camera state");
468 /// The hint for display reuse.
469 /// If the hint is set to true, the display will be reused when the camera device is changed with
470 /// ChangeDevice method.
472 /// <since_tizen> 3 </since_tizen>
473 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
474 /// <exception cref="InvalidOperationException">Invalid state.</exception>
475 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
476 public bool DisplayReuseHint
480 ValidateNotDisposed();
484 CameraErrorFactory.ThrowIfError(Native.GetDisplayReuseHint(_handle, out val),
485 "Failed to get camera display reuse hint");
492 ValidateState(CameraState.Preview);
494 CameraErrorFactory.ThrowIfError(Native.SetDisplayReuseHint(_handle, value),
495 "Failed to set display reuse hint.");
500 /// Gets the facing direction of camera module.
502 /// <since_tizen> 3 </since_tizen>
503 /// <value>A <see cref="CameraFacingDirection"/> that specifies the facing direction of camera device.</value>
504 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
505 public CameraFacingDirection Direction
509 ValidateNotDisposed();
511 CameraFacingDirection val = 0;
513 CameraErrorFactory.ThrowIfError(Native.GetFacingDirection(_handle, out 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.</exception>
527 public int CameraCount
531 ValidateNotDisposed();
535 CameraErrorFactory.ThrowIfError(Native.GetDeviceCount(_handle, out val),
536 "Failed to get camera device count");
541 #endregion Properties
545 /// Changes the camera device.
547 /// <since_tizen> 3 </since_tizen>
548 /// <param name="device">The hardware camera to access.</param>
550 /// If display reuse is set using <see cref="DisplayReuseHint"/>
551 /// before stopping the preview, the display will be reused and last frame on the display
552 /// can be kept even though camera device is changed.
553 /// The camera must be in the <see cref="CameraState.Created"/>.
555 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
556 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
557 /// <exception cref="NotSupportedException">In case of ChangeDevice feature is not supported.</exception>
558 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
559 public void ChangeDevice(CameraDevice device)
561 ValidateState(CameraState.Created);
562 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
564 CameraErrorFactory.ThrowIfError(Native.ChangeDevice(_handle, (int)device),
565 "Failed to change the camera device");
569 /// Gets the device state.
571 /// <since_tizen> 3 </since_tizen>
572 /// <param name="device">The device to get state.</param>
573 /// <returns>Returns the state of camera device</returns>
574 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
575 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
576 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
577 public CameraDeviceState GetDeviceState(CameraDevice device)
580 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
582 CameraErrorFactory.ThrowIfError(Native.GetDeviceState(device, out val),
583 "Failed to get the camera device state.");
585 return (CameraDeviceState)val;
589 /// Gets the flash state.
591 /// <since_tizen> 3 </since_tizen>
592 /// <param name="device">The device to get state.</param>
593 /// <returns>Returns the flash state of 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 CameraFlashState val = CameraFlashState.NotUsed;
600 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
602 CameraErrorFactory.ThrowIfError(Native.GetFlashState(device, out val),
603 "Failed to get camera flash state");
609 /// Starts capturing and drawing preview frames on the screen.
610 /// The display handle must be set using <see cref="CameraDisplaySettings.SetInfo"/>
611 /// before using this method.
612 /// If needed set fps <see cref="CameraSettings.PreviewFps"/>, preview resolution
613 /// <see cref="CameraSettings.PreviewResolution"/>, or preview format <see cref="CameraSettings.PreviewPixelFormat"/>
614 /// before using this method.
615 /// The camera must be in the <see cref="CameraState.Created"/> or <see cref="CameraState.Captured"/> state.
617 /// <since_tizen> 3 </since_tizen>
619 /// http://tizen.org/privilege/camera
621 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
622 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
623 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
624 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
625 public void StartPreview()
627 ValidateState(CameraState.Created, CameraState.Captured);
629 CameraErrorFactory.ThrowIfError(Native.StartPreview(_handle),
630 "Failed to start the camera preview.");
632 // Update by StateChangedCallback can be delayed for dozens of milliseconds.
633 SetState(CameraState.Preview);
637 /// Stops capturing and drawing preview frames on the screen.
638 /// The camera must be in the <see cref="CameraState.Preview"/> state.
640 /// <since_tizen> 3 </since_tizen>
642 /// http://tizen.org/privilege/camera
644 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
645 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
646 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
647 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
648 public void StopPreview()
650 ValidateState(CameraState.Preview);
652 CameraErrorFactory.ThrowIfError(Native.StopPreview(_handle),
653 "Failed to stop the camera preview.");
655 SetState(CameraState.Created);
659 /// Starts capturing of still images.
660 /// EventHandler must be set for capturing using <see cref="Capturing"/>
661 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
662 /// The camera must be in the <see cref="CameraState.Preview"/> state.
664 /// <since_tizen> 3 </since_tizen>
666 /// http://tizen.org/privilege/camera
669 /// This function causes the transition of the camera state from Capturing to Captured
670 /// automatically and the corresponding EventHandlers will be invoked.
671 /// The preview should be restarted by calling <see cref="StartPreview"/> method after capture is completed.
673 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
674 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
675 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
676 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
677 public void StartCapture()
679 ValidateState(CameraState.Preview);
681 CameraErrorFactory.ThrowIfError(Native.StartCapture(_handle, _capturingCallback, _captureCompletedCallback, IntPtr.Zero),
682 "Failed to start the camera capture.");
684 SetState(CameraState.Capturing);
688 /// Starts continuously capturing still images.
689 /// EventHandler must be set for capturing using <see cref="Capturing"/>
690 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
691 /// The camera must be in the <see cref="CameraState.Preview"/> state.
693 /// <since_tizen> 3 </since_tizen>
695 /// http://tizen.org/privilege/camera
697 /// <param name="count">The number of still images.</param>
698 /// <param name="interval">The interval of the capture(milliseconds).</param>
699 /// <param name="cancellationToken">The cancellation token to cancel capturing.</param>
700 /// <seealso cref="System.Threading.CancellationToken"/>
702 /// If this is not supported zero shutter lag occurs. The capture resolution could be
703 /// changed to the preview resolution. This function causes the transition of the camera state
704 /// from Capturing to Captured automatically and the corresponding Eventhandlers will be invoked.
705 /// Each captured image will be delivered through Eventhandler set using <see cref="Capturing"/> event.
706 /// The preview should be restarted by calling <see cref="StartPreview"/> method after capture is completed.
708 /// <exception cref="ArgumentOutOfRangeException">In case of invalid parameters.</exception>
709 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
710 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
711 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
712 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
713 public void StartCapture(int count, int interval, CancellationToken cancellationToken)
715 ValidateState(CameraState.Preview);
719 throw new ArgumentOutOfRangeException(nameof(count), count, $"{nameof(count)} should be greater than one.");
724 throw new ArgumentOutOfRangeException(nameof(interval), interval, $"{nameof(interval)} should be greater than or equal to zero.");
727 //Handle CancellationToken
728 if (cancellationToken != CancellationToken.None)
730 cancellationToken.Register(() =>
732 CameraErrorFactory.ThrowIfError(Native.StopContinuousCapture(_handle),
733 "Failed to cancel the continuous capture");
734 SetState(CameraState.Captured);
738 CameraErrorFactory.ThrowIfError(Native.StartContinuousCapture(_handle, count, interval,
739 _capturingCallback, _captureCompletedCallback, IntPtr.Zero), "Failed to start the continuous capture.");
741 SetState(CameraState.Capturing);
745 /// Starts camera auto-focusing, asynchronously.
746 /// The camera must be in the <see cref="CameraState.Preview"/> or <see cref="CameraState.Captured"/> state.
748 /// <since_tizen> 3 </since_tizen>
749 /// <param name="continuous">Continuous auto focus</param>
751 /// http://tizen.org/privilege/camera
754 /// If continuous status is true, the camera continuously tries to focus.
756 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
757 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
758 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
759 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
760 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
761 public void StartFocusing(bool continuous)
763 ValidateState(CameraState.Preview, CameraState.Captured);
765 CameraErrorFactory.ThrowIfError(Native.StartFocusing(_handle, continuous),
766 "Failed to cancel the camera focus.");
770 /// Stops camera auto focusing.
771 /// The camera must be in the <see cref="CameraState.Preview"/> or <see cref="CameraState.Captured"/> state.
773 /// <since_tizen> 3 </since_tizen>
775 /// http://tizen.org/privilege/camera
777 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
778 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
779 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
780 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
781 public void StopFocusing()
783 ValidateState(CameraState.Preview, CameraState.Captured);
785 CameraErrorFactory.ThrowIfError(Native.CancelFocusing(_handle),
786 "Failed to cancel the camera focus.");
790 /// Starts face detection.
791 /// The camera must be in the <see cref="CameraState.Preview"/> state.
793 /// <since_tizen> 3 </since_tizen>
795 /// http://tizen.org/privilege/camera
798 /// This should be called after <see cref="StartPreview"/> is started.
799 /// The Eventhandler set using <see cref="FaceDetected"/> invoked when the face is detected in preview frame.
800 /// Internally it starts continuous focus and focusing on the detected face.
802 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
803 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
804 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
805 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
806 public void StartFaceDetection()
808 ValidateState(CameraState.Preview);
810 _faceDetectedCallback = (IntPtr faces, int count, IntPtr userData) =>
812 var result = new List<FaceDetectionData>();
813 IntPtr current = faces;
815 for (int i = 0; i < count; i++)
817 result.Add(new FaceDetectionData(current));
818 current = IntPtr.Add(current, Marshal.SizeOf<Native.DetectedFaceStruct>());
821 FaceDetected?.Invoke(this, new FaceDetectedEventArgs(result));
823 CameraErrorFactory.ThrowIfError(Native.StartFaceDetection(_handle, _faceDetectedCallback, IntPtr.Zero),
824 "Failed to start face detection");
828 /// Stops face detection.
830 /// <since_tizen> 3 </since_tizen>
832 /// http://tizen.org/privilege/camera
834 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
835 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
836 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
837 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
838 public void StopFaceDetection()
840 if (_faceDetectedCallback == null)
842 throw new InvalidOperationException("The face detection is not started.");
845 CameraErrorFactory.ThrowIfError(Native.StopFaceDetection(_handle),
846 "Failed to stop the face detection.");
848 _faceDetectedCallback = null;
852 #region Callback registrations
853 private void RegisterCallbacks()
855 RegisterErrorCallback();
856 RegisterFocusStateChanged();
857 RegisterHdrCaptureProgress();
858 RegisterInterruptedCallback();
859 RegisterStateChangedCallback();
861 //Define capturing callback
862 _capturingCallback = (IntPtr image, IntPtr postview, IntPtr thumbnail, IntPtr userData) =>
864 Capturing?.Invoke(this, new CameraCapturingEventArgs(new ImageData(image),
865 postview == IntPtr.Zero ? null : new ImageData(postview),
866 thumbnail == IntPtr.Zero ? null : new ImageData(thumbnail)));
869 //Define captureCompleted callback
870 _captureCompletedCallback = _ =>
872 SetState(CameraState.Captured);
873 CaptureCompleted?.Invoke(this, EventArgs.Empty);
877 private void RegisterInterruptedCallback()
879 _interruptedCallback = (CameraPolicy policy, CameraState previous, CameraState current, IntPtr userData) =>
881 Interrupted?.Invoke(this, new CameraInterruptedEventArgs(policy, previous, current));
883 CameraErrorFactory.ThrowIfError(Native.SetInterruptedCallback(_handle, _interruptedCallback, IntPtr.Zero),
884 "Failed to set interrupt callback");
887 private void RegisterErrorCallback()
889 _errorCallback = (CameraErrorCode error, CameraState current, IntPtr userData) =>
891 ErrorOccurred?.Invoke(this, new CameraErrorOccurredEventArgs(error, current));
893 CameraErrorFactory.ThrowIfError(Native.SetErrorCallback(_handle, _errorCallback, IntPtr.Zero),
894 "Setting error callback failed");
897 private void RegisterStateChangedCallback()
899 _stateChangedCallback = (CameraState previous, CameraState current, bool byPolicy, IntPtr _) =>
902 Log.Info(CameraLog.Tag, "Camera state changed " + previous.ToString() + " -> " + current.ToString());
903 StateChanged?.Invoke(this, new CameraStateChangedEventArgs(previous, current, byPolicy));
905 CameraErrorFactory.ThrowIfError(Native.SetStateChangedCallback(_handle, _stateChangedCallback, IntPtr.Zero),
906 "Setting state changed callback failed");
909 private void RegisterFocusStateChanged()
911 _focusStateChangedCallback = (CameraFocusState state, IntPtr userData) =>
913 FocusStateChanged?.Invoke(this, new CameraFocusStateChangedEventArgs(state));
915 CameraErrorFactory.ThrowIfError(Native.SetFocusStateChangedCallback(_handle, _focusStateChangedCallback, IntPtr.Zero),
916 "Setting focus changed callback failed");
919 private void RegisterHdrCaptureProgress()
921 //Hdr Capture can not be supported.
922 if (Feature.IsHdrCaptureSupported)
924 _hdrCaptureProgressCallback = (int percent, IntPtr userData) =>
926 HdrCaptureProgress?.Invoke(this, new HdrCaptureProgressEventArgs(percent));
928 CameraErrorFactory.ThrowIfError(Native.SetHdrCaptureProgressCallback(_handle, _hdrCaptureProgressCallback, IntPtr.Zero),
929 "Setting Hdr capture progress callback failed");
933 private void RegisterPreviewCallback()
935 _previewCallback = (IntPtr frame, IntPtr userData) =>
937 _preview?.Invoke(this, new PreviewEventArgs(new PreviewData(frame)));
939 CameraErrorFactory.ThrowIfError(Native.SetPreviewCallback(_handle, _previewCallback, IntPtr.Zero),
940 "Setting preview callback failed");
943 private void RegisterMediaPacketPreviewCallback()
945 _mediaPacketPreviewCallback = (IntPtr mediaPacket, IntPtr userData) =>
947 MediaPacket packet = MediaPacket.From(mediaPacket);
948 var eventHandler = _mediaPacketPreview;
950 if (eventHandler != null)
952 eventHandler.Invoke(this, new MediaPacketPreviewEventArgs(packet));
959 CameraErrorFactory.ThrowIfError(Native.SetMediaPacketPreviewCallback(_handle, _mediaPacketPreviewCallback, IntPtr.Zero),
960 "Setting media packet preview callback failed");
962 #endregion Callback registrations