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 /// <since_tizen> 3 </since_tizen>
42 /// <feature> http://tizen.org/feature/camera </feature>
43 public class Camera : IDisposable, IDisplayable<CameraError>
45 private IntPtr _handle = IntPtr.Zero;
46 private bool _disposed = false;
47 private CameraState _state = CameraState.None;
50 /// Initializes a new instance of the <see cref="Camera"/> class.
52 /// <param name="device">The camera device to access.</param>
53 /// <exception cref="ArgumentException">Invalid CameraDevice type.</exception>
54 /// <exception cref="NotSupportedException">The camera feature is not supported.</exception>
55 /// <since_tizen> 3 </since_tizen>
56 /// <feature> http://tizen.org/feature/camera </feature>
57 public Camera(CameraDevice device)
59 if (!Features.IsSupported(CameraFeatures.Camera))
61 throw new NotSupportedException("Camera feature is not supported.");
64 Native.Create(device, out _handle).ThrowIfFailed("Failed to create camera instance");
66 Capabilities = new CameraCapabilities(this);
67 Settings = new CameraSettings(this);
68 DisplaySettings = new CameraDisplaySettings(this);
72 SetState(CameraState.Created);
76 /// Finalizes an instance of the Camera class.
84 /// Gets the native handle of the camera.
86 /// <since_tizen> 3 </since_tizen>
87 /// <feature> http://tizen.org/feature/camera </feature>
88 public IntPtr Handle => GetHandle();
90 internal IntPtr GetHandle()
92 ValidateNotDisposed();
96 #region Dispose support
98 /// Releases the unmanaged resources used by the camera.
100 /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
101 /// <since_tizen> 3 </since_tizen>
102 protected virtual void Dispose(bool disposing)
108 // to be used if there are any other disposable objects
111 if (_handle != IntPtr.Zero)
113 Native.Destroy(_handle);
114 _handle = IntPtr.Zero;
122 /// Releases all resources used by the camera.
124 /// <since_tizen> 3 </since_tizen>
125 /// <feature> http://tizen.org/feature/camera </feature>
126 public void Dispose()
128 ReplaceDisplay(null);
130 GC.SuppressFinalize(this);
133 internal void ValidateNotDisposed()
137 Log.Error(CameraLog.Tag, "Camera handle is disposed.");
138 throw new ObjectDisposedException(nameof(Camera));
141 #endregion Dispose support
143 #region Check camera state
144 internal void ValidateState(params CameraState[] required)
146 ValidateNotDisposed();
148 Debug.Assert(required.Length > 0);
150 var curState = _state;
151 if (!required.Contains(curState))
153 throw new InvalidOperationException($"The camera is not in a valid state. " +
154 $"Current State : { curState }, Valid State : { string.Join(", ", required) }.");
158 internal void SetState(CameraState state)
162 #endregion Check camera state
164 #region EventHandlers
166 /// An event that occurs when the camera interrupt is started by the policy.
168 /// <since_tizen> 4 </since_tizen>
169 public event EventHandler<CameraInterruptStartedEventArgs> InterruptStarted;
170 private Native.InterruptStartedCallback _interruptStartedCallback;
173 /// An event that occurs when an camera is interrupted by the policy.
175 /// <since_tizen> 3 </since_tizen>
176 public event EventHandler<CameraInterruptedEventArgs> Interrupted;
177 private Native.InterruptedCallback _interruptedCallback;
180 /// An event that occurs when there is an asynchronous error.
182 /// <since_tizen> 3 </since_tizen>
183 public event EventHandler<CameraErrorOccurredEventArgs> ErrorOccurred;
184 private Native.ErrorCallback _errorCallback;
187 /// An event that occurs when the auto focus state is changed.
189 /// <since_tizen> 3 </since_tizen>
190 public event EventHandler<CameraFocusStateChangedEventArgs> FocusStateChanged;
191 private Native.FocusStateChangedCallback _focusStateChangedCallback;
194 /// An event that occurs when a face is detected in the preview frame.
196 /// <since_tizen> 3 </since_tizen>
197 public event EventHandler<FaceDetectedEventArgs> FaceDetected;
198 private Native.FaceDetectedCallback _faceDetectedCallback;
201 /// An event that occurs during capture of an image.
203 /// <since_tizen> 3 </since_tizen>
204 public event EventHandler<CameraCapturingEventArgs> Capturing;
205 private Native.CapturingCallback _capturingCallback;
208 /// An event that occurs after the capture of the image.
210 /// <since_tizen> 3 </since_tizen>
211 public event EventHandler<EventArgs> CaptureCompleted;
212 private Native.CaptureCompletedCallback _captureCompletedCallback;
214 private Native.HdrCaptureProgressCallback _hdrCaptureProgressCallback;
215 private event EventHandler<HdrCaptureProgressEventArgs> _hdrCaptureProgress;
216 private object _hdrCaptureProgressEventLock = new object();
219 /// An event that occurs when there is a change in the HDR capture progress.
220 /// Checks whether the <see cref="CameraCapabilities.IsHdrCaptureSupported"/> is supported or not before adding this EventHandler.
222 /// <since_tizen> 3 </since_tizen>
223 /// <exception cref="NotSupportedException">In case of HDR feature is not supported.</exception>
224 public event EventHandler<HdrCaptureProgressEventArgs> HdrCaptureProgress
228 lock (_hdrCaptureProgressEventLock)
230 if (_hdrCaptureProgress == null)
232 RegisterHdrCaptureProgress();
235 _hdrCaptureProgress += value;
241 lock (_hdrCaptureProgressEventLock)
243 _hdrCaptureProgress -= value;
245 if (_hdrCaptureProgress == null)
247 UnregisterHdrCaptureProgress();
254 /// An event that occurs when the camera state is changed.
256 /// <since_tizen> 3 </since_tizen>
257 public event EventHandler<CameraStateChangedEventArgs> StateChanged;
258 private Native.StateChangedCallback _stateChangedCallback;
260 private static Native.DeviceStateChangedCallback _deviceStateChangedCallback;
261 private static event EventHandler<CameraDeviceStateChangedEventArgs> _deviceStateChanged;
262 private static object _deviceStateChangedEventLock = new object();
263 private static int _deviceStateCallbackId;
266 /// An event that occurs after the <see cref="CameraDeviceState"/> is changed.
268 /// <since_tizen> 3 </since_tizen>
269 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
270 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
271 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
272 public static event EventHandler<CameraDeviceStateChangedEventArgs> DeviceStateChanged
276 lock (_deviceStateChangedEventLock)
278 if (_deviceStateChanged == null)
280 RegisterDeviceStateChangedCallback();
283 _deviceStateChanged += value;
289 lock (_deviceStateChangedEventLock)
291 _deviceStateChanged -= value;
293 if (_deviceStateChanged == null)
295 UnregisterDeviceStateChangedCallback();
301 private Native.PreviewCallback _previewCallback;
302 private event EventHandler<PreviewEventArgs> _preview;
303 private object _previewEventLock = new object();
305 /// An event that occurs once per frame when previewing.
306 /// Preview callback is registered when an user adds a callback explicitly to avoid useless P/Invoke.
308 /// <since_tizen> 3 </since_tizen>
309 public event EventHandler<PreviewEventArgs> Preview
313 lock (_previewEventLock)
315 if (_preview == null)
317 RegisterPreviewCallback();
326 lock (_previewEventLock)
330 if (_preview == null)
332 UnregisterPreviewCallback();
338 private Native.MediaPacketPreviewCallback _mediaPacketPreviewCallback;
339 private EventHandler<MediaPacketPreviewEventArgs> _mediaPacketPreview;
340 private object _mediaPacketPreviewEventLock = new object();
343 /// An event that occurs once per frame when previewing.
344 /// Preview callback is registered when an user adds a callback explicitly to avoid useless P/Invoke.
346 /// <since_tizen> 3 </since_tizen>
347 public event EventHandler<MediaPacketPreviewEventArgs> MediaPacketPreview
351 lock (_mediaPacketPreviewEventLock)
353 if (_mediaPacketPreview == null)
355 RegisterMediaPacketPreviewCallback();
358 _mediaPacketPreview += value;
364 lock (_mediaPacketPreviewEventLock)
366 _mediaPacketPreview -= value;
368 if (_mediaPacketPreview == null)
370 UnregisterMediaPacketPreviewCallback();
375 #endregion EventHandlers
379 /// Gets or sets the various camera settings.
381 /// <since_tizen> 4 </since_tizen>
382 public CameraSettings Settings { get; }
385 /// Gets the various camera capabilities.
387 /// <since_tizen> 4 </since_tizen>
388 public CameraCapabilities Capabilities { get; }
391 /// Get/set various camera display properties.
393 /// <since_tizen> 3 </since_tizen>
394 public CameraDisplaySettings DisplaySettings { get; }
396 private Display _display;
398 private CameraError SetDisplay(Display display)
402 return CameraDisplay.SetTarget(GetHandle(), DisplayType.None, IntPtr.Zero);
405 return display.ApplyTo(this);
408 private void ReplaceDisplay(Display newDisplay)
410 _display?.SetOwner(null);
411 _display = newDisplay;
412 _display?.SetOwner(this);
416 /// Sets or gets the display type and handle to show preview images.
417 /// The camera must be in the <see cref="CameraState.Created"/> state.
419 /// <since_tizen> 3 </since_tizen>
421 /// This must be set before the StartPreview() method.
422 /// In custom ROI display mode, DisplayRoiArea property must be set before calling this method.
424 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
425 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
426 /// <exception cref="ObjectDisposedException" > The camera already has been disposed of.</exception>
427 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
428 public Display Display
437 ValidateState(CameraState.Created);
439 if (value?.Owner != null)
441 if (ReferenceEquals(this, value.Owner))
446 throw new ArgumentException("The display has already been assigned to another.");
449 SetDisplay(value).ThrowIfFailed("Failed to set the camera display");
451 ReplaceDisplay(value);
455 CameraError IDisplayable<CameraError>.ApplyEvasDisplay(DisplayType type, ElmSharp.EvasObject evasObject)
457 Debug.Assert(_disposed == false);
458 ValidationUtil.ValidateEnum(typeof(DisplayType), type, nameof(type));
460 return CameraDisplay.SetTarget(GetHandle(), type, evasObject);
463 CameraError IDisplayable<CameraError>.ApplyEcoreWindow(IntPtr windowHandle)
465 throw new NotSupportedException("Camera does not support NUI.Window display.");
469 /// Gets the state of the camera.
471 /// <since_tizen> 3 </since_tizen>
472 /// <value> None, Created, Preview, Capturing, Captured.</value>
473 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
474 public CameraState State
478 ValidateNotDisposed();
480 CameraState val = CameraState.None;
482 Native.GetState(_handle, out val).ThrowIfFailed("Failed to get camera state");
489 /// The hint for the display reuse.
490 /// If the hint is set to true, the display will be reused when the camera device is changed with
491 /// the ChangeDevice method.
493 /// <since_tizen> 3 </since_tizen>
494 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
495 /// <exception cref="InvalidOperationException">An invalid state.</exception>
496 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
497 public bool DisplayReuseHint
501 ValidateNotDisposed();
503 Native.GetDisplayReuseHint(_handle, out bool val).ThrowIfFailed("Failed to get camera display reuse hint");
510 ValidateState(CameraState.Preview);
512 Native.SetDisplayReuseHint(_handle, value).ThrowIfFailed("Failed to set display reuse hint.");
517 /// Gets the facing direction of the camera module.
519 /// <since_tizen> 3 </since_tizen>
520 /// <value>A <see cref="CameraFacingDirection"/> that specifies the facing direction of the camera device.</value>
521 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
522 public CameraFacingDirection Direction
526 ValidateNotDisposed();
528 Native.GetFacingDirection(_handle, out var val).ThrowIfFailed("Failed to get camera direction");
535 /// Gets the camera device count.
537 /// <since_tizen> 3 </since_tizen>
538 /// <value>This returns 2, if the device supports primary and secondary cameras.
539 /// Otherwise 1, if the device only supports primary camera.</value>
540 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
541 public int CameraCount
545 ValidateNotDisposed();
547 Native.GetDeviceCount(_handle, out int val).ThrowIfFailed("Failed to get camera device count");
552 #endregion Properties
556 /// Changes the camera device.
558 /// <param name="device">The hardware camera to access.</param>
559 /// <since_tizen> 3 </since_tizen>
560 /// <feature> http://tizen.org/feature/camera </feature>
562 /// If display reuse is set using <see cref="DisplayReuseHint"/>
563 /// before stopping the preview, the display will be reused and last frame on the display
564 /// can be kept even though camera device is changed.
565 /// The camera must be in the <see cref="CameraState.Created"/>.
567 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
568 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
569 /// <exception cref="NotSupportedException">In case of the ChangeDevice feature is not supported.</exception>
570 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
571 public void ChangeDevice(CameraDevice device)
573 ValidateState(CameraState.Created);
574 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
576 Native.ChangeDevice(_handle, device).ThrowIfFailed("Failed to change the camera device");
580 /// Gets the device state.
582 /// <param name="device">The device to get the state.</param>
583 /// <returns>Returns the state of the camera device.</returns>
584 /// <since_tizen> 4 </since_tizen>
585 /// <feature> http://tizen.org/feature/camera </feature>
586 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
587 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
588 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
589 public static CameraDeviceState GetDeviceState(CameraDevice device)
591 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
593 Native.GetDeviceState(device, out var val).ThrowIfFailed("Failed to get the camera device state.");
599 /// Gets the flash state.
601 /// <param name="device">The device to get the state.</param>
602 /// <returns>Returns the flash state of the camera device.</returns>
603 /// <since_tizen> 3 </since_tizen>
604 /// <feature> http://tizen.org/feature/camera </feature>
605 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
606 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
607 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
608 public static CameraFlashState GetFlashState(CameraDevice device)
610 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
612 Native.GetFlashState(device, out var val).ThrowIfFailed("Failed to get camera flash state");
618 /// Starts capturing and drawing preview frames on the screen.
619 /// The display property must be set using <see cref="Display"/> before using this method.
620 /// If needed set fps <see cref="CameraSettings.PreviewFps"/>, preview resolution
621 /// <see cref="CameraSettings.PreviewResolution"/>, or preview format <see cref="CameraSettings.PreviewPixelFormat"/>
622 /// before using this method.
623 /// The camera must be in the <see cref="CameraState.Created"/> or the <see cref="CameraState.Captured"/> state.
625 /// <since_tizen> 3 </since_tizen>
626 /// <privilege> http://tizen.org/privilege/camera </privilege>
627 /// <feature> http://tizen.org/feature/camera </feature>
628 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
629 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
630 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
631 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
632 public void StartPreview()
634 ValidateState(CameraState.Created, CameraState.Captured);
636 Native.StartPreview(_handle).ThrowIfFailed("Failed to start the camera preview.");
638 // Update by StateChangedCallback can be delayed for dozens of milliseconds.
639 SetState(CameraState.Preview);
643 /// Stops capturing and drawing preview frames on the screen.
644 /// The camera must be in the <see cref="CameraState.Preview"/> state.
646 /// <since_tizen> 3 </since_tizen>
647 /// <privilege> http://tizen.org/privilege/camera </privilege>
648 /// <feature> http://tizen.org/feature/camera </feature>
649 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
650 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
651 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
652 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
653 public void StopPreview()
655 ValidateState(CameraState.Preview);
657 Native.StopPreview(_handle).ThrowIfFailed("Failed to stop the camera preview.");
659 SetState(CameraState.Created);
663 /// Starts capturing of still images.
664 /// EventHandler must be set for capturing using <see cref="Capturing"/>
665 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
666 /// The camera must be in the <see cref="CameraState.Preview"/> state.
668 /// <since_tizen> 3 </since_tizen>
669 /// <privilege> http://tizen.org/privilege/camera </privilege>
670 /// <feature> http://tizen.org/feature/camera </feature>
672 /// This function causes the transition of the camera state from capturing to captured
673 /// automatically and the corresponding EventHandlers will be invoked.
674 /// The preview should be restarted by calling the <see cref="StartPreview"/> method after capture is completed.
676 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
677 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
678 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
679 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
680 public void StartCapture()
682 ValidateState(CameraState.Preview);
684 Native.StartCapture(_handle, _capturingCallback, _captureCompletedCallback, IntPtr.Zero).
685 ThrowIfFailed("Failed to start the camera capture.");
687 SetState(CameraState.Capturing);
691 /// Starts continuously capturing still images.
692 /// EventHandler must be set for capturing using <see cref="Capturing"/>
693 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
694 /// The camera must be in the <see cref="CameraState.Preview"/> state.
696 /// <param name="count">The number of still images.</param>
697 /// <param name="interval">The interval of the capture(milliseconds).</param>
698 /// <param name="cancellationToken">The cancellation token to cancel capturing.</param>
699 /// <seealso cref="CancellationToken"/>
700 /// <since_tizen> 3 </since_tizen>
701 /// <privilege> http://tizen.org/privilege/camera </privilege>
702 /// <feature> http://tizen.org/feature/camera </feature>
704 /// If this is not supported, zero shutter lag occurs. The capture resolution could be
705 /// changed to the preview resolution. This function causes the transition of the camera state
706 /// from capturing to captured automatically and the corresponding Eventhandlers will be invoked.
707 /// Each captured image will be delivered through Eventhandler set using the <see cref="Capturing"/> event.
708 /// The preview should be restarted by calling the <see cref="StartPreview"/> method after capture is completed.
710 /// <exception cref="ArgumentOutOfRangeException">In case of invalid parameters.</exception>
711 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
712 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
713 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
714 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
715 public void StartCapture(int count, int interval, CancellationToken cancellationToken)
717 ValidateState(CameraState.Preview);
721 throw new ArgumentOutOfRangeException(nameof(count), count, $"{nameof(count)} should be greater than one.");
726 throw new ArgumentOutOfRangeException(nameof(interval), interval, $"{nameof(interval)} should be greater than or equal to zero.");
729 //Handle CancellationToken
730 if (cancellationToken != CancellationToken.None)
732 cancellationToken.Register(() =>
734 Native.StopContinuousCapture(_handle).ThrowIfFailed("Failed to cancel the continuous capture");
735 SetState(CameraState.Captured);
739 Native.StartContinuousCapture(_handle, count, interval, _capturingCallback, _captureCompletedCallback, IntPtr.Zero).
740 ThrowIfFailed("Failed to start the continuous capture.");
742 SetState(CameraState.Capturing);
746 /// Starts camera auto-focusing, asynchronously.
747 /// The camera must be in the <see cref="CameraState.Preview"/> or the <see cref="CameraState.Captured"/> state.
749 /// <param name="continuous">Continuous auto focus.</param>
750 /// <since_tizen> 3 </since_tizen>
751 /// <privilege> http://tizen.org/privilege/camera </privilege>
752 /// <feature> http://tizen.org/feature/camera </feature>
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 of.</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 Native.StartFocusing(_handle, continuous).ThrowIfFailed("Failed to cancel the camera focus.");
769 /// Stops camera auto focusing.
770 /// The camera must be in the <see cref="CameraState.Preview"/> or the <see cref="CameraState.Captured"/> state.
772 /// <since_tizen> 3 </since_tizen>
773 /// <privilege> http://tizen.org/privilege/camera </privilege>
774 /// <feature> http://tizen.org/feature/camera </feature>
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 Native.CancelFocusing(_handle).ThrowIfFailed("Failed to cancel the camera focus.");
787 /// Starts face detection.
788 /// The camera must be in the <see cref="CameraState.Preview"/> state.
790 /// <since_tizen> 3 </since_tizen>
791 /// <privilege> http://tizen.org/privilege/camera </privilege>
792 /// <feature> http://tizen.org/feature/camera </feature>
794 /// This should be called after <see cref="StartPreview"/> is started.
795 /// The Eventhandler set using <see cref="FaceDetected"/> is invoked when the face is detected in the preview frame.
796 /// Internally, it starts continuously focus and focusing on the detected face.
798 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
799 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
800 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
801 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
802 public void StartFaceDetection()
804 ValidateState(CameraState.Preview);
806 _faceDetectedCallback = (IntPtr faces, int count, IntPtr userData) =>
808 var result = new List<FaceDetectionData>();
809 IntPtr current = faces;
811 for (int i = 0; i < count; i++)
813 result.Add(new FaceDetectionData(current));
814 current = IntPtr.Add(current, Marshal.SizeOf<Native.DetectedFaceStruct>());
817 FaceDetected?.Invoke(this, new FaceDetectedEventArgs(result));
820 Native.StartFaceDetection(_handle, _faceDetectedCallback, IntPtr.Zero).
821 ThrowIfFailed("Failed to start face detection");
825 /// Stops face detection.
827 /// <since_tizen> 3 </since_tizen>
828 /// <privilege> http://tizen.org/privilege/camera </privilege>
829 /// <feature> http://tizen.org/feature/camera </feature>
830 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
831 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
832 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
833 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
834 public void StopFaceDetection()
836 ValidateNotDisposed();
838 if (_faceDetectedCallback == null)
840 throw new InvalidOperationException("The face detection is not started.");
843 Native.StopFaceDetection(_handle).ThrowIfFailed("Failed to stop the face detection.");
845 _faceDetectedCallback = null;
849 #region Callback registrations
850 private void RegisterCallbacks()
852 RegisterErrorCallback();
853 RegisterFocusStateChanged();
854 RegisterInterruptStartedCallback();
855 RegisterInterruptedCallback();
856 RegisterStateChangedCallback();
858 //Define capturing callback
859 _capturingCallback = (IntPtr main, IntPtr postview, IntPtr thumbnail, IntPtr userData) =>
861 Capturing?.Invoke(this, new CameraCapturingEventArgs(new StillImage(main),
862 postview == IntPtr.Zero ? null : new StillImage(postview),
863 thumbnail == IntPtr.Zero ? null : new StillImage(thumbnail)));
866 //Define captureCompleted callback
867 _captureCompletedCallback = _ =>
869 SetState(CameraState.Captured);
870 CaptureCompleted?.Invoke(this, EventArgs.Empty);
874 private void RegisterInterruptStartedCallback()
876 _interruptStartedCallback = (CameraPolicy policy, CameraState state, IntPtr userData) =>
878 InterruptStarted?.Invoke(this, new CameraInterruptStartedEventArgs(policy, state));
881 Native.SetInterruptStartedCallback(_handle, _interruptStartedCallback, IntPtr.Zero).
882 ThrowIfFailed("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));
892 Native.SetInterruptedCallback(_handle, _interruptedCallback, IntPtr.Zero).
893 ThrowIfFailed("Failed to set interrupt callback");
896 private void RegisterErrorCallback()
898 _errorCallback = (CameraErrorCode error, CameraState current, IntPtr userData) =>
900 ErrorOccurred?.Invoke(this, new CameraErrorOccurredEventArgs(error, current));
903 Native.SetErrorCallback(_handle, _errorCallback, IntPtr.Zero).ThrowIfFailed("Setting error callback failed");
906 private void RegisterStateChangedCallback()
908 _stateChangedCallback = (CameraState previous, CameraState current, bool byPolicy, IntPtr _) =>
911 Log.Info(CameraLog.Tag, "Camera state changed " + previous.ToString() + " -> " + current.ToString());
912 StateChanged?.Invoke(this, new CameraStateChangedEventArgs(previous, current, byPolicy));
915 Native.SetStateChangedCallback(_handle, _stateChangedCallback, IntPtr.Zero).
916 ThrowIfFailed("Setting state changed callback failed");
919 private static void RegisterDeviceStateChangedCallback()
921 _deviceStateChangedCallback = (CameraDevice device, CameraDeviceState state, IntPtr userData) =>
923 _deviceStateChanged?.Invoke(null, new CameraDeviceStateChangedEventArgs(device, state));
926 Native.SetDeviceStateChangedCallback(_deviceStateChangedCallback, IntPtr.Zero, out _deviceStateCallbackId).
927 ThrowIfFailed("Failed to set device state changed callback");
929 Log.Info(CameraLog.Tag, "add callbackId " + _deviceStateCallbackId.ToString());
932 private static void UnregisterDeviceStateChangedCallback()
934 Native.UnsetDeviceStateChangedCallback(_deviceStateCallbackId).
935 ThrowIfFailed("Unsetting device state changed callback failed");
937 _deviceStateChangedCallback = null;
938 _deviceStateCallbackId = 0;
941 private void RegisterFocusStateChanged()
943 _focusStateChangedCallback = (CameraFocusState state, IntPtr userData) =>
945 FocusStateChanged?.Invoke(this, new CameraFocusStateChangedEventArgs(state));
948 Native.SetFocusStateChangedCallback(_handle, _focusStateChangedCallback, IntPtr.Zero).
949 ThrowIfFailed("Setting focus changed callback failed");
952 private void RegisterHdrCaptureProgress()
954 _hdrCaptureProgressCallback = (int percent, IntPtr userData) =>
956 _hdrCaptureProgress?.Invoke(this, new HdrCaptureProgressEventArgs(percent));
959 Native.SetHdrCaptureProgressCallback(_handle, _hdrCaptureProgressCallback, IntPtr.Zero).
960 ThrowIfFailed("Setting Hdr capture progress callback failed");
963 private void UnregisterHdrCaptureProgress()
965 Native.UnsetHdrCaptureProgressCallback(_handle).
966 ThrowIfFailed("Unsetting hdr capture progress is failed");
968 _hdrCaptureProgressCallback = null;
971 private void RegisterPreviewCallback()
973 _previewCallback = (IntPtr frame, IntPtr userData) =>
975 _preview?.Invoke(this, new PreviewEventArgs(new PreviewFrame(frame)));
978 Native.SetPreviewCallback(_handle, _previewCallback, IntPtr.Zero).
979 ThrowIfFailed("Setting preview callback failed");
982 private void UnregisterPreviewCallback()
984 Native.UnsetPreviewCallback(_handle).ThrowIfFailed("Unsetting preview callback failed");
986 _previewCallback = null;
989 private void RegisterMediaPacketPreviewCallback()
991 _mediaPacketPreviewCallback = (IntPtr mediaPacket, IntPtr userData) =>
993 MediaPacket packet = MediaPacket.From(mediaPacket);
995 var eventHandler = _mediaPacketPreview;
997 if (eventHandler != null)
999 eventHandler.Invoke(this, new MediaPacketPreviewEventArgs(packet));
1005 Native.SetMediaPacketPreviewCallback(_handle, _mediaPacketPreviewCallback, IntPtr.Zero).
1006 ThrowIfFailed("Setting media packet preview callback failed");
1009 private void UnregisterMediaPacketPreviewCallback()
1011 Native.UnsetMediaPacketPreviewCallback(_handle).
1012 ThrowIfFailed("Unsetting media packet preview callback failed");
1014 _mediaPacketPreviewCallback = null;
1016 #endregion Callback registrations