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.SetDisplay(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.SetDisplay(GetHandle(), type, evasObject);
463 CameraError IDisplayable<CameraError>.ApplyEcoreWindow(IntPtr windowHandle)
465 Debug.Assert(_disposed == false);
467 return CameraDisplay.SetEcoreDisplay(GetHandle(), windowHandle);
471 /// Gets the state of the camera.
473 /// <since_tizen> 3 </since_tizen>
474 /// <value> None, Created, Preview, Capturing, Captured.</value>
475 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
476 public CameraState State
480 ValidateNotDisposed();
482 CameraState val = CameraState.None;
484 Native.GetState(_handle, out val).ThrowIfFailed("Failed to get camera state");
491 /// The hint for the display reuse.
492 /// If the hint is set to true, the display will be reused when the camera device is changed with
493 /// the ChangeDevice method.
495 /// <since_tizen> 3 </since_tizen>
496 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
497 /// <exception cref="InvalidOperationException">An invalid state.</exception>
498 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
499 public bool DisplayReuseHint
503 ValidateNotDisposed();
505 Native.GetDisplayReuseHint(_handle, out bool val).ThrowIfFailed("Failed to get camera display reuse hint");
512 ValidateState(CameraState.Preview);
514 Native.SetDisplayReuseHint(_handle, value).ThrowIfFailed("Failed to set display reuse hint.");
519 /// Gets the facing direction of the camera module.
521 /// <since_tizen> 3 </since_tizen>
522 /// <value>A <see cref="CameraFacingDirection"/> that specifies the facing direction of the camera device.</value>
523 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
524 public CameraFacingDirection Direction
528 ValidateNotDisposed();
530 Native.GetFacingDirection(_handle, out var val).ThrowIfFailed("Failed to get camera direction");
537 /// Gets the camera device count.
539 /// <since_tizen> 3 </since_tizen>
540 /// <value>This returns 2, if the device supports primary and secondary cameras.
541 /// Otherwise 1, if the device only supports primary camera.</value>
542 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
543 public int CameraCount
547 ValidateNotDisposed();
549 Native.GetDeviceCount(_handle, out int val).ThrowIfFailed("Failed to get camera device count");
554 #endregion Properties
558 /// Changes the camera device.
560 /// <param name="device">The hardware camera to access.</param>
561 /// <since_tizen> 3 </since_tizen>
562 /// <feature> http://tizen.org/feature/camera </feature>
564 /// If display reuse is set using <see cref="DisplayReuseHint"/>
565 /// before stopping the preview, the display will be reused and last frame on the display
566 /// can be kept even though camera device is changed.
567 /// The camera must be in the <see cref="CameraState.Created"/>.
569 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
570 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
571 /// <exception cref="NotSupportedException">In case of the ChangeDevice feature is not supported.</exception>
572 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
573 public void ChangeDevice(CameraDevice device)
575 ValidateState(CameraState.Created);
576 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
578 Native.ChangeDevice(_handle, device).ThrowIfFailed("Failed to change the camera device");
582 /// Gets the device state.
584 /// <param name="device">The device to get the state.</param>
585 /// <returns>Returns the state of the camera device.</returns>
586 /// <since_tizen> 4 </since_tizen>
587 /// <feature> http://tizen.org/feature/camera </feature>
588 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
589 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
590 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
591 public static CameraDeviceState GetDeviceState(CameraDevice device)
593 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
595 Native.GetDeviceState(device, out var val).ThrowIfFailed("Failed to get the camera device state.");
601 /// Gets the flash state.
603 /// <param name="device">The device to get the state.</param>
604 /// <returns>Returns the flash state of the camera device.</returns>
605 /// <since_tizen> 3 </since_tizen>
606 /// <feature> http://tizen.org/feature/camera </feature>
607 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
608 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
609 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
610 public static CameraFlashState GetFlashState(CameraDevice device)
612 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
614 Native.GetFlashState(device, out var val).ThrowIfFailed("Failed to get camera flash state");
620 /// Starts capturing and drawing preview frames on the screen.
621 /// The display property must be set using <see cref="Display"/> before using this method.
622 /// If needed set fps <see cref="CameraSettings.PreviewFps"/>, preview resolution
623 /// <see cref="CameraSettings.PreviewResolution"/>, or preview format <see cref="CameraSettings.PreviewPixelFormat"/>
624 /// before using this method.
625 /// The camera must be in the <see cref="CameraState.Created"/> or the <see cref="CameraState.Captured"/> state.
627 /// <since_tizen> 3 </since_tizen>
628 /// <privilege> http://tizen.org/privilege/camera </privilege>
629 /// <feature> http://tizen.org/feature/camera </feature>
630 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
631 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
632 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
633 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
634 public void StartPreview()
636 ValidateState(CameraState.Created, CameraState.Captured);
638 Native.StartPreview(_handle).ThrowIfFailed("Failed to start the camera preview.");
640 // Update by StateChangedCallback can be delayed for dozens of milliseconds.
641 SetState(CameraState.Preview);
645 /// Stops capturing and drawing preview frames on the screen.
646 /// The camera must be in the <see cref="CameraState.Preview"/> state.
648 /// <since_tizen> 3 </since_tizen>
649 /// <privilege> http://tizen.org/privilege/camera </privilege>
650 /// <feature> http://tizen.org/feature/camera </feature>
651 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
652 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
653 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
654 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
655 public void StopPreview()
657 ValidateState(CameraState.Preview);
659 Native.StopPreview(_handle).ThrowIfFailed("Failed to stop the camera preview.");
661 SetState(CameraState.Created);
665 /// Starts capturing of still images.
666 /// EventHandler must be set for capturing using <see cref="Capturing"/>
667 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
668 /// The camera must be in the <see cref="CameraState.Preview"/> state.
670 /// <since_tizen> 3 </since_tizen>
671 /// <privilege> http://tizen.org/privilege/camera </privilege>
672 /// <feature> http://tizen.org/feature/camera </feature>
674 /// This function causes the transition of the camera state from capturing to captured
675 /// automatically and the corresponding EventHandlers will be invoked.
676 /// The preview should be restarted by calling the <see cref="StartPreview"/> method after capture is completed.
678 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
679 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
680 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
681 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
682 public void StartCapture()
684 ValidateState(CameraState.Preview);
686 Native.StartCapture(_handle, _capturingCallback, _captureCompletedCallback, IntPtr.Zero).
687 ThrowIfFailed("Failed to start the camera capture.");
689 SetState(CameraState.Capturing);
693 /// Starts continuously capturing still images.
694 /// EventHandler must be set for capturing using <see cref="Capturing"/>
695 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
696 /// The camera must be in the <see cref="CameraState.Preview"/> state.
698 /// <param name="count">The number of still images.</param>
699 /// <param name="interval">The interval of the capture(milliseconds).</param>
700 /// <param name="cancellationToken">The cancellation token to cancel capturing.</param>
701 /// <seealso cref="CancellationToken"/>
702 /// <since_tizen> 3 </since_tizen>
703 /// <privilege> http://tizen.org/privilege/camera </privilege>
704 /// <feature> http://tizen.org/feature/camera </feature>
706 /// If this is not supported, zero shutter lag occurs. The capture resolution could be
707 /// changed to the preview resolution. This function causes the transition of the camera state
708 /// from capturing to captured automatically and the corresponding Eventhandlers will be invoked.
709 /// Each captured image will be delivered through Eventhandler set using the <see cref="Capturing"/> event.
710 /// The preview should be restarted by calling the <see cref="StartPreview"/> method after capture is completed.
712 /// <exception cref="ArgumentOutOfRangeException">In case of invalid parameters.</exception>
713 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
714 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
715 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
716 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
717 public void StartCapture(int count, int interval, CancellationToken cancellationToken)
719 ValidateState(CameraState.Preview);
723 throw new ArgumentOutOfRangeException(nameof(count), count, $"{nameof(count)} should be greater than one.");
728 throw new ArgumentOutOfRangeException(nameof(interval), interval, $"{nameof(interval)} should be greater than or equal to zero.");
731 //Handle CancellationToken
732 if (cancellationToken != CancellationToken.None)
734 cancellationToken.Register(() =>
736 Native.StopContinuousCapture(_handle).ThrowIfFailed("Failed to cancel the continuous capture");
737 SetState(CameraState.Captured);
741 Native.StartContinuousCapture(_handle, count, interval, _capturingCallback, _captureCompletedCallback, IntPtr.Zero).
742 ThrowIfFailed("Failed to start the continuous capture.");
744 SetState(CameraState.Capturing);
748 /// Starts camera auto-focusing, asynchronously.
749 /// The camera must be in the <see cref="CameraState.Preview"/> or the <see cref="CameraState.Captured"/> state.
751 /// <param name="continuous">Continuous auto focus.</param>
752 /// <since_tizen> 3 </since_tizen>
753 /// <privilege> http://tizen.org/privilege/camera </privilege>
754 /// <feature> http://tizen.org/feature/camera </feature>
756 /// If continuous status is true, the camera continuously tries to focus.
758 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
759 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
760 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
761 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
762 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
763 public void StartFocusing(bool continuous)
765 ValidateState(CameraState.Preview, CameraState.Captured);
767 Native.StartFocusing(_handle, continuous).ThrowIfFailed("Failed to cancel the camera focus.");
771 /// Stops camera auto focusing.
772 /// The camera must be in the <see cref="CameraState.Preview"/> or the <see cref="CameraState.Captured"/> state.
774 /// <since_tizen> 3 </since_tizen>
775 /// <privilege> http://tizen.org/privilege/camera </privilege>
776 /// <feature> http://tizen.org/feature/camera </feature>
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 of.</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 Native.CancelFocusing(_handle).ThrowIfFailed("Failed to cancel the camera focus.");
789 /// Starts face detection.
790 /// The camera must be in the <see cref="CameraState.Preview"/> state.
792 /// <since_tizen> 3 </since_tizen>
793 /// <privilege> http://tizen.org/privilege/camera </privilege>
794 /// <feature> http://tizen.org/feature/camera </feature>
796 /// This should be called after <see cref="StartPreview"/> is started.
797 /// The Eventhandler set using <see cref="FaceDetected"/> is invoked when the face is detected in the preview frame.
798 /// Internally, it starts continuously focus and focusing on the detected face.
800 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
801 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
802 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
803 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
804 public void StartFaceDetection()
806 ValidateState(CameraState.Preview);
808 _faceDetectedCallback = (IntPtr faces, int count, IntPtr userData) =>
810 var result = new List<FaceDetectionData>();
811 IntPtr current = faces;
813 for (int i = 0; i < count; i++)
815 result.Add(new FaceDetectionData(current));
816 current = IntPtr.Add(current, Marshal.SizeOf<Native.DetectedFaceStruct>());
819 FaceDetected?.Invoke(this, new FaceDetectedEventArgs(result));
822 Native.StartFaceDetection(_handle, _faceDetectedCallback, IntPtr.Zero).
823 ThrowIfFailed("Failed to start face detection");
827 /// Stops face detection.
829 /// <since_tizen> 3 </since_tizen>
830 /// <privilege> http://tizen.org/privilege/camera </privilege>
831 /// <feature> http://tizen.org/feature/camera </feature>
832 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
833 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
834 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
835 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
836 public void StopFaceDetection()
838 ValidateNotDisposed();
840 if (_faceDetectedCallback == null)
842 throw new InvalidOperationException("The face detection is not started.");
845 Native.StopFaceDetection(_handle).ThrowIfFailed("Failed to stop the face detection.");
847 _faceDetectedCallback = null;
851 #region Callback registrations
852 private void RegisterCallbacks()
854 RegisterErrorCallback();
855 RegisterFocusStateChanged();
856 RegisterInterruptStartedCallback();
857 RegisterInterruptedCallback();
858 RegisterStateChangedCallback();
860 //Define capturing callback
861 _capturingCallback = (IntPtr main, IntPtr postview, IntPtr thumbnail, IntPtr userData) =>
863 Capturing?.Invoke(this, new CameraCapturingEventArgs(new StillImage(main),
864 postview == IntPtr.Zero ? null : new StillImage(postview),
865 thumbnail == IntPtr.Zero ? null : new StillImage(thumbnail)));
868 //Define captureCompleted callback
869 _captureCompletedCallback = _ =>
871 SetState(CameraState.Captured);
872 CaptureCompleted?.Invoke(this, EventArgs.Empty);
876 private void RegisterInterruptStartedCallback()
878 _interruptStartedCallback = (CameraPolicy policy, CameraState state, IntPtr userData) =>
880 InterruptStarted?.Invoke(this, new CameraInterruptStartedEventArgs(policy, state));
883 Native.SetInterruptStartedCallback(_handle, _interruptStartedCallback, IntPtr.Zero).
884 ThrowIfFailed("Failed to set interrupt callback");
887 private void RegisterInterruptedCallback()
889 _interruptedCallback = (CameraPolicy policy, CameraState previous, CameraState current, IntPtr userData) =>
891 Interrupted?.Invoke(this, new CameraInterruptedEventArgs(policy, previous, current));
894 Native.SetInterruptedCallback(_handle, _interruptedCallback, IntPtr.Zero).
895 ThrowIfFailed("Failed to set interrupt callback");
898 private void RegisterErrorCallback()
900 _errorCallback = (CameraErrorCode error, CameraState current, IntPtr userData) =>
902 ErrorOccurred?.Invoke(this, new CameraErrorOccurredEventArgs(error, current));
905 Native.SetErrorCallback(_handle, _errorCallback, IntPtr.Zero).ThrowIfFailed("Setting error callback failed");
908 private void RegisterStateChangedCallback()
910 _stateChangedCallback = (CameraState previous, CameraState current, bool byPolicy, IntPtr _) =>
913 Log.Info(CameraLog.Tag, "Camera state changed " + previous.ToString() + " -> " + current.ToString());
914 StateChanged?.Invoke(this, new CameraStateChangedEventArgs(previous, current, byPolicy));
917 Native.SetStateChangedCallback(_handle, _stateChangedCallback, IntPtr.Zero).
918 ThrowIfFailed("Setting state changed callback failed");
921 private static void RegisterDeviceStateChangedCallback()
923 _deviceStateChangedCallback = (CameraDevice device, CameraDeviceState state, IntPtr userData) =>
925 _deviceStateChanged?.Invoke(null, new CameraDeviceStateChangedEventArgs(device, state));
928 Native.SetDeviceStateChangedCallback(_deviceStateChangedCallback, IntPtr.Zero, out _deviceStateCallbackId).
929 ThrowIfFailed("Failed to set device state changed callback");
931 Log.Info(CameraLog.Tag, "add callbackId " + _deviceStateCallbackId.ToString());
934 private static void UnregisterDeviceStateChangedCallback()
936 Native.UnsetDeviceStateChangedCallback(_deviceStateCallbackId).
937 ThrowIfFailed("Unsetting device state changed callback failed");
939 _deviceStateChangedCallback = null;
940 _deviceStateCallbackId = 0;
943 private void RegisterFocusStateChanged()
945 _focusStateChangedCallback = (CameraFocusState state, IntPtr userData) =>
947 FocusStateChanged?.Invoke(this, new CameraFocusStateChangedEventArgs(state));
950 Native.SetFocusStateChangedCallback(_handle, _focusStateChangedCallback, IntPtr.Zero).
951 ThrowIfFailed("Setting focus changed callback failed");
954 private void RegisterHdrCaptureProgress()
956 _hdrCaptureProgressCallback = (int percent, IntPtr userData) =>
958 _hdrCaptureProgress?.Invoke(this, new HdrCaptureProgressEventArgs(percent));
961 Native.SetHdrCaptureProgressCallback(_handle, _hdrCaptureProgressCallback, IntPtr.Zero).
962 ThrowIfFailed("Setting Hdr capture progress callback failed");
965 private void UnregisterHdrCaptureProgress()
967 Native.UnsetHdrCaptureProgressCallback(_handle).
968 ThrowIfFailed("Unsetting hdr capture progress is failed");
970 _hdrCaptureProgressCallback = null;
973 private void RegisterPreviewCallback()
975 _previewCallback = (IntPtr frame, IntPtr userData) =>
977 _preview?.Invoke(this, new PreviewEventArgs(new PreviewFrame(frame)));
980 Native.SetPreviewCallback(_handle, _previewCallback, IntPtr.Zero).
981 ThrowIfFailed("Setting preview callback failed");
984 private void UnregisterPreviewCallback()
986 Native.UnsetPreviewCallback(_handle).ThrowIfFailed("Unsetting preview callback failed");
988 _previewCallback = null;
991 private void RegisterMediaPacketPreviewCallback()
993 _mediaPacketPreviewCallback = (IntPtr mediaPacket, IntPtr userData) =>
995 MediaPacket packet = MediaPacket.From(mediaPacket);
997 var eventHandler = _mediaPacketPreview;
999 if (eventHandler != null)
1001 eventHandler.Invoke(this, new MediaPacketPreviewEventArgs(packet));
1007 Native.SetMediaPacketPreviewCallback(_handle, _mediaPacketPreviewCallback, IntPtr.Zero).
1008 ThrowIfFailed("Setting media packet preview callback failed");
1011 private void UnregisterMediaPacketPreviewCallback()
1013 Native.UnsetMediaPacketPreviewCallback(_handle).
1014 ThrowIfFailed("Unsetting media packet preview callback failed");
1016 _mediaPacketPreviewCallback = null;
1018 #endregion Callback registrations