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 public class Camera : IDisposable, IDisplayable<CameraError>
44 private IntPtr _handle = IntPtr.Zero;
45 private bool _disposed = false;
46 private CameraState _state = CameraState.None;
49 /// Initializes a new instance of the <see cref="Camera"/> class.
51 /// <feature>http://tizen.org/feature/camera</feature>
52 /// <since_tizen> 3 </since_tizen>
53 /// <param name="device">The camera device to access.</param>
54 public Camera(CameraDevice device)
56 if (!Features.IsSupported(CameraFeatures.Camera))
58 throw new NotSupportedException("Camera feature is not supported.");
61 CameraErrorFactory.ThrowIfError(Native.Create(device, out _handle),
62 "Failed to create camera instance");
64 Capabilities = new CameraCapabilities(this);
65 Settings = new CameraSettings(this);
66 DisplaySettings = new CameraDisplaySettings(this);
70 SetState(CameraState.Created);
74 /// Finalizes an instance of the Camera class.
82 /// Gets the native handle of the camera.
84 /// <since_tizen> 3 </since_tizen>
85 public IntPtr Handle => GetHandle();
87 internal IntPtr GetHandle()
89 ValidateNotDisposed();
93 #region Dispose support
95 /// Releases the unmanaged resources used by the camera.
97 /// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources.</param>
98 /// <since_tizen> 3 </since_tizen>
99 protected virtual void Dispose(bool disposing)
105 // to be used if there are any other disposable objects
108 if (_handle != IntPtr.Zero)
110 Native.Destroy(_handle);
111 _handle = IntPtr.Zero;
119 /// Releases all resources used by the camera.
121 /// <since_tizen> 3 </since_tizen>
122 public void Dispose()
124 ReplaceDisplay(null);
126 GC.SuppressFinalize(this);
129 internal void ValidateNotDisposed()
133 Log.Error(CameraLog.Tag, "Camera handle is disposed.");
134 throw new ObjectDisposedException(nameof(Camera));
137 #endregion Dispose support
139 #region Check camera state
140 internal void ValidateState(params CameraState[] required)
142 ValidateNotDisposed();
144 Debug.Assert(required.Length > 0);
146 var curState = _state;
147 if (!required.Contains(curState))
149 throw new InvalidOperationException($"The camera is not in a valid state. " +
150 $"Current State : { curState }, Valid State : { string.Join(", ", required) }.");
154 internal void SetState(CameraState state)
158 #endregion Check camera state
160 #region EventHandlers
162 /// An event that occurs when the camera interrupt is started by the policy.
164 /// <since_tizen> 4 </since_tizen>
165 public event EventHandler<CameraInterruptStartedEventArgs> InterruptStarted;
166 private Native.InterruptStartedCallback _interruptStartedCallback;
169 /// An event that occurs when an camera is interrupted by the policy.
171 /// <since_tizen> 3 </since_tizen>
172 public event EventHandler<CameraInterruptedEventArgs> Interrupted;
173 private Native.InterruptedCallback _interruptedCallback;
176 /// An event that occurs when there is an asynchronous error.
178 /// <since_tizen> 3 </since_tizen>
179 public event EventHandler<CameraErrorOccurredEventArgs> ErrorOccurred;
180 private Native.ErrorCallback _errorCallback;
183 /// An event that occurs when the auto focus state is changed.
185 /// <since_tizen> 3 </since_tizen>
186 public event EventHandler<CameraFocusStateChangedEventArgs> FocusStateChanged;
187 private Native.FocusStateChangedCallback _focusStateChangedCallback;
190 /// An event that occurs when a face is detected in the preview frame.
192 /// <since_tizen> 3 </since_tizen>
193 public event EventHandler<FaceDetectedEventArgs> FaceDetected;
194 private Native.FaceDetectedCallback _faceDetectedCallback;
197 /// An event that occurs during capture of an image.
199 /// <since_tizen> 3 </since_tizen>
200 public event EventHandler<CameraCapturingEventArgs> Capturing;
201 private Native.CapturingCallback _capturingCallback;
204 /// An event that occurs after the capture of the image.
206 /// <since_tizen> 3 </since_tizen>
207 public event EventHandler<EventArgs> CaptureCompleted;
208 private Native.CaptureCompletedCallback _captureCompletedCallback;
210 private Native.HdrCaptureProgressCallback _hdrCaptureProgressCallback;
211 private event EventHandler<HdrCaptureProgressEventArgs> _hdrCaptureProgress;
212 private object _hdrCaptureProgressEventLock = new object();
215 /// An event that occurs when there is a change in the HDR capture progress.
216 /// Checks whether the <see cref="CameraCapabilities.IsHdrCaptureSupported"/> is supported or not before adding this EventHandler.
218 /// <since_tizen> 3 </since_tizen>
219 /// <exception cref="NotSupportedException">In case of HDR feature is not supported.</exception>
220 public event EventHandler<HdrCaptureProgressEventArgs> HdrCaptureProgress
224 lock (_hdrCaptureProgressEventLock)
226 if (_hdrCaptureProgress == null)
228 RegisterHdrCaptureProgress();
231 _hdrCaptureProgress += value;
237 lock (_hdrCaptureProgressEventLock)
239 _hdrCaptureProgress -= value;
241 if (_hdrCaptureProgress == null)
243 UnregisterHdrCaptureProgress();
250 /// An event that occurs when the camera state is changed.
252 /// <since_tizen> 3 </since_tizen>
253 public event EventHandler<CameraStateChangedEventArgs> StateChanged;
254 private Native.StateChangedCallback _stateChangedCallback;
256 private static Native.DeviceStateChangedCallback _deviceStateChangedCallback;
257 private static event EventHandler<CameraDeviceStateChangedEventArgs> _deviceStateChanged;
258 private static object _deviceStateChangedEventLock = new object();
259 private static int _deviceStateCallbackId;
262 /// An event that occurs after the <see cref="CameraDeviceState"/> is changed.
264 /// <since_tizen> 3 </since_tizen>
265 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
266 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
267 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
268 public static event EventHandler<CameraDeviceStateChangedEventArgs> DeviceStateChanged
272 lock (_deviceStateChangedEventLock)
274 if (_deviceStateChanged == null)
276 RegisterDeviceStateChangedCallback();
279 _deviceStateChanged += value;
285 lock (_deviceStateChangedEventLock)
287 _deviceStateChanged -= value;
289 if (_deviceStateChanged == null)
291 UnregisterDeviceStateChangedCallback();
297 private Native.PreviewCallback _previewCallback;
298 private event EventHandler<PreviewEventArgs> _preview;
299 private object _previewEventLock = new object();
301 /// An event that occurs once per frame when previewing.
302 /// Preview callback is registered when an user adds a callback explicitly to avoid useless P/Invoke.
304 /// <since_tizen> 3 </since_tizen>
305 public event EventHandler<PreviewEventArgs> Preview
309 lock (_previewEventLock)
311 if (_preview == null)
313 RegisterPreviewCallback();
322 lock (_previewEventLock)
326 if (_preview == null)
328 UnregisterPreviewCallback();
334 private Native.MediaPacketPreviewCallback _mediaPacketPreviewCallback;
335 private EventHandler<MediaPacketPreviewEventArgs> _mediaPacketPreview;
336 private object _mediaPacketPreviewEventLock = new object();
339 /// An event that occurs once per frame when previewing.
340 /// Preview callback is registered when an user adds a callback explicitly to avoid useless P/Invoke.
342 /// <since_tizen> 3 </since_tizen>
343 public event EventHandler<MediaPacketPreviewEventArgs> MediaPacketPreview
347 lock (_mediaPacketPreviewEventLock)
349 if (_mediaPacketPreview == null)
351 RegisterMediaPacketPreviewCallback();
354 _mediaPacketPreview += value;
360 lock (_mediaPacketPreviewEventLock)
362 _mediaPacketPreview -= value;
364 if (_mediaPacketPreview == null)
366 UnregisterMediaPacketPreviewCallback();
371 #endregion EventHandlers
375 /// Gets or sets the various camera settings.
377 /// <since_tizen> 4 </since_tizen>
378 public CameraSettings Settings { get; }
381 /// Gets the various camera capabilities.
383 /// <since_tizen> 4 </since_tizen>
384 public CameraCapabilities Capabilities { get; }
387 /// Get/set various camera display properties.
389 /// <since_tizen> 3 </since_tizen>
390 public CameraDisplaySettings DisplaySettings { get; }
392 private Display _display;
394 private CameraError SetDisplay(Display display)
398 return CameraDisplay.SetTarget(GetHandle(), DisplayType.None, IntPtr.Zero);
401 return display.ApplyTo(this);
404 private void ReplaceDisplay(Display newDisplay)
406 _display?.SetOwner(null);
407 _display = newDisplay;
408 _display?.SetOwner(this);
412 /// Sets or gets the display type and handle to show preview images.
413 /// The camera must be in the <see cref="CameraState.Created"/> state.
415 /// <since_tizen> 3 </since_tizen>
417 /// This must be set before the StartPreview() method.
418 /// In custom ROI display mode, DisplayRoiArea property must be set before calling this method.
420 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
421 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
422 /// <exception cref="ObjectDisposedException" > The camera already has been disposed of.</exception>
423 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
424 public Display Display
433 ValidateState(CameraState.Created);
435 if (value?.Owner != null)
437 if (ReferenceEquals(this, value.Owner))
442 throw new ArgumentException("The display has already been assigned to another.");
445 CameraErrorFactory.ThrowIfError(SetDisplay(value), "Failed to set the camera display");
447 ReplaceDisplay(value);
451 CameraError IDisplayable<CameraError>.ApplyEvasDisplay(DisplayType type, ElmSharp.EvasObject evasObject)
453 Debug.Assert(_disposed == false);
454 ValidationUtil.ValidateEnum(typeof(DisplayType), type, nameof(type));
456 return CameraDisplay.SetTarget(GetHandle(), type, evasObject);
459 CameraError IDisplayable<CameraError>.ApplyEcoreWindow(IntPtr windowHandle)
461 throw new NotSupportedException("Camera does not support NUI.Window display.");
465 /// Gets the state of the camera.
467 /// <since_tizen> 3 </since_tizen>
468 /// <value> None, Created, Preview, Capturing, Captured.</value>
469 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
470 public CameraState State
474 ValidateNotDisposed();
476 CameraState val = CameraState.None;
477 CameraErrorFactory.ThrowIfError(Native.GetState(_handle, out val),
478 "Failed to get camera state");
485 /// The hint for the display reuse.
486 /// If the hint is set to true, the display will be reused when the camera device is changed with
487 /// the ChangeDevice method.
489 /// <since_tizen> 3 </since_tizen>
490 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
491 /// <exception cref="InvalidOperationException">An invalid state.</exception>
492 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
493 public bool DisplayReuseHint
497 ValidateNotDisposed();
499 CameraErrorFactory.ThrowIfError(Native.GetDisplayReuseHint(_handle, out bool val),
500 "Failed to get camera display reuse hint");
507 ValidateState(CameraState.Preview);
509 CameraErrorFactory.ThrowIfError(Native.SetDisplayReuseHint(_handle, value),
510 "Failed to set display reuse hint.");
515 /// Gets the facing direction of the camera module.
517 /// <since_tizen> 3 </since_tizen>
518 /// <value>A <see cref="CameraFacingDirection"/> that specifies the facing direction of the camera device.</value>
519 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
520 public CameraFacingDirection Direction
524 ValidateNotDisposed();
526 CameraErrorFactory.ThrowIfError(Native.GetFacingDirection(_handle, out var val),
527 "Failed to get camera direction");
534 /// Gets the camera device count.
536 /// <since_tizen> 3 </since_tizen>
537 /// <value>This returns 2, if the device supports primary and secondary cameras.
538 /// Otherwise 1, if the device only supports primary camera.</value>
539 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
540 public int CameraCount
544 ValidateNotDisposed();
546 CameraErrorFactory.ThrowIfError(Native.GetDeviceCount(_handle, out int val),
547 "Failed to get camera device count");
552 #endregion Properties
556 /// Changes the camera device.
558 /// <since_tizen> 3 </since_tizen>
559 /// <param name="device">The hardware camera to access.</param>
561 /// If display reuse is set using <see cref="DisplayReuseHint"/>
562 /// before stopping the preview, the display will be reused and last frame on the display
563 /// can be kept even though camera device is changed.
564 /// The camera must be in the <see cref="CameraState.Created"/>.
566 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
567 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
568 /// <exception cref="NotSupportedException">In case of the ChangeDevice feature is not supported.</exception>
569 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
570 public void ChangeDevice(CameraDevice device)
572 ValidateState(CameraState.Created);
573 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
575 CameraErrorFactory.ThrowIfError(Native.ChangeDevice(_handle, device),
576 "Failed to change the camera device");
580 /// Gets the device state.
582 /// <since_tizen> 4 </since_tizen>
583 /// <param name="device">The device to get the state.</param>
584 /// <returns>Returns the state of the camera device.</returns>
585 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
586 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
587 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
588 public static CameraDeviceState GetDeviceState(CameraDevice device)
590 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
592 CameraErrorFactory.ThrowIfError(Native.GetDeviceState(device, out var val),
593 "Failed to get the camera device state.");
599 /// Gets the flash state.
601 /// <since_tizen> 3 </since_tizen>
602 /// <param name="device">The device to get the state.</param>
603 /// <returns>Returns the flash state of the camera device.</returns>
604 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
605 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
606 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
607 public static CameraFlashState GetFlashState(CameraDevice device)
609 ValidationUtil.ValidateEnum(typeof(CameraDevice), device, nameof(device));
611 CameraErrorFactory.ThrowIfError(Native.GetFlashState(device, out var val),
612 "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>
627 /// http://tizen.org/privilege/camera
629 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
630 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
631 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
632 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
633 public void StartPreview()
635 ValidateState(CameraState.Created, CameraState.Captured);
637 CameraErrorFactory.ThrowIfError(Native.StartPreview(_handle),
638 "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>
650 /// http://tizen.org/privilege/camera
652 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
653 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
654 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
655 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
656 public void StopPreview()
658 ValidateState(CameraState.Preview);
660 CameraErrorFactory.ThrowIfError(Native.StopPreview(_handle),
661 "Failed to stop the camera preview.");
663 SetState(CameraState.Created);
667 /// Starts capturing of still images.
668 /// EventHandler must be set for capturing using <see cref="Capturing"/>
669 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
670 /// The camera must be in the <see cref="CameraState.Preview"/> state.
672 /// <since_tizen> 3 </since_tizen>
674 /// http://tizen.org/privilege/camera
677 /// This function causes the transition of the camera state from capturing to captured
678 /// automatically and the corresponding EventHandlers will be invoked.
679 /// The preview should be restarted by calling the <see cref="StartPreview"/> method after capture is completed.
681 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
682 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
683 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
684 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
685 public void StartCapture()
687 ValidateState(CameraState.Preview);
689 CameraErrorFactory.ThrowIfError(Native.StartCapture(_handle, _capturingCallback, _captureCompletedCallback, IntPtr.Zero),
690 "Failed to start the camera capture.");
692 SetState(CameraState.Capturing);
696 /// Starts continuously capturing still images.
697 /// EventHandler must be set for capturing using <see cref="Capturing"/>
698 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
699 /// The camera must be in the <see cref="CameraState.Preview"/> state.
701 /// <since_tizen> 3 </since_tizen>
703 /// http://tizen.org/privilege/camera
705 /// <param name="count">The number of still images.</param>
706 /// <param name="interval">The interval of the capture(milliseconds).</param>
707 /// <param name="cancellationToken">The cancellation token to cancel capturing.</param>
708 /// <seealso cref="CancellationToken"/>
710 /// If this is not supported, zero shutter lag occurs. The capture resolution could be
711 /// changed to the preview resolution. This function causes the transition of the camera state
712 /// from capturing to captured automatically and the corresponding Eventhandlers will be invoked.
713 /// Each captured image will be delivered through Eventhandler set using the <see cref="Capturing"/> event.
714 /// The preview should be restarted by calling the <see cref="StartPreview"/> method after capture is completed.
716 /// <exception cref="ArgumentOutOfRangeException">In case of invalid parameters.</exception>
717 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
718 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
719 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
720 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
721 public void StartCapture(int count, int interval, CancellationToken cancellationToken)
723 ValidateState(CameraState.Preview);
727 throw new ArgumentOutOfRangeException(nameof(count), count, $"{nameof(count)} should be greater than one.");
732 throw new ArgumentOutOfRangeException(nameof(interval), interval, $"{nameof(interval)} should be greater than or equal to zero.");
735 //Handle CancellationToken
736 if (cancellationToken != CancellationToken.None)
738 cancellationToken.Register(() =>
740 CameraErrorFactory.ThrowIfError(Native.StopContinuousCapture(_handle),
741 "Failed to cancel the continuous capture");
742 SetState(CameraState.Captured);
746 CameraErrorFactory.ThrowIfError(Native.StartContinuousCapture(_handle, count, interval,
747 _capturingCallback, _captureCompletedCallback, IntPtr.Zero), "Failed to start the continuous capture.");
749 SetState(CameraState.Capturing);
753 /// Starts camera auto-focusing, asynchronously.
754 /// The camera must be in the <see cref="CameraState.Preview"/> or the <see cref="CameraState.Captured"/> state.
756 /// <since_tizen> 3 </since_tizen>
757 /// <param name="continuous">Continuous auto focus.</param>
759 /// http://tizen.org/privilege/camera
762 /// If continuous status is true, the camera continuously tries to focus.
764 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
765 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
766 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
767 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
768 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
769 public void StartFocusing(bool continuous)
771 ValidateState(CameraState.Preview, CameraState.Captured);
773 CameraErrorFactory.ThrowIfError(Native.StartFocusing(_handle, continuous),
774 "Failed to cancel the camera focus.");
778 /// Stops camera auto focusing.
779 /// The camera must be in the <see cref="CameraState.Preview"/> or the <see cref="CameraState.Captured"/> state.
781 /// <since_tizen> 3 </since_tizen>
783 /// http://tizen.org/privilege/camera
785 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
786 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
787 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
788 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
789 public void StopFocusing()
791 ValidateState(CameraState.Preview, CameraState.Captured);
793 CameraErrorFactory.ThrowIfError(Native.CancelFocusing(_handle),
794 "Failed to cancel the camera focus.");
798 /// Starts face detection.
799 /// The camera must be in the <see cref="CameraState.Preview"/> state.
801 /// <since_tizen> 3 </since_tizen>
803 /// http://tizen.org/privilege/camera
806 /// This should be called after <see cref="StartPreview"/> is started.
807 /// The Eventhandler set using <see cref="FaceDetected"/> is invoked when the face is detected in the preview frame.
808 /// Internally, it starts continuously focus and focusing on the detected face.
810 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
811 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
812 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
813 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
814 public void StartFaceDetection()
816 ValidateState(CameraState.Preview);
818 _faceDetectedCallback = (IntPtr faces, int count, IntPtr userData) =>
820 var result = new List<FaceDetectionData>();
821 IntPtr current = faces;
823 for (int i = 0; i < count; i++)
825 result.Add(new FaceDetectionData(current));
826 current = IntPtr.Add(current, Marshal.SizeOf<Native.DetectedFaceStruct>());
829 FaceDetected?.Invoke(this, new FaceDetectedEventArgs(result));
831 CameraErrorFactory.ThrowIfError(Native.StartFaceDetection(_handle, _faceDetectedCallback, IntPtr.Zero),
832 "Failed to start face detection");
836 /// Stops face detection.
838 /// <since_tizen> 3 </since_tizen>
840 /// http://tizen.org/privilege/camera
842 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
843 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
844 /// <exception cref="ObjectDisposedException">The camera already has been disposed of.</exception>
845 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
846 public void StopFaceDetection()
848 if (_faceDetectedCallback == null)
850 throw new InvalidOperationException("The face detection is not started.");
853 CameraErrorFactory.ThrowIfError(Native.StopFaceDetection(_handle),
854 "Failed to stop the face detection.");
856 _faceDetectedCallback = null;
860 #region Callback registrations
861 private void RegisterCallbacks()
863 RegisterErrorCallback();
864 RegisterFocusStateChanged();
865 RegisterInterruptStartedCallback();
866 RegisterInterruptedCallback();
867 RegisterStateChangedCallback();
869 //Define capturing callback
870 _capturingCallback = (IntPtr main, IntPtr postview, IntPtr thumbnail, IntPtr userData) =>
872 Capturing?.Invoke(this, new CameraCapturingEventArgs(new StillImage(main),
873 postview == IntPtr.Zero ? null : new StillImage(postview),
874 thumbnail == IntPtr.Zero ? null : new StillImage(thumbnail)));
877 //Define captureCompleted callback
878 _captureCompletedCallback = _ =>
880 SetState(CameraState.Captured);
881 CaptureCompleted?.Invoke(this, EventArgs.Empty);
885 private void RegisterInterruptStartedCallback()
887 _interruptStartedCallback = (CameraPolicy policy, CameraState state, IntPtr userData) =>
889 InterruptStarted?.Invoke(this, new CameraInterruptStartedEventArgs(policy, state));
891 CameraErrorFactory.ThrowIfError(Native.SetInterruptStartedCallback(_handle, _interruptStartedCallback, IntPtr.Zero),
892 "Failed to set interrupt callback");
895 private void RegisterInterruptedCallback()
897 _interruptedCallback = (CameraPolicy policy, CameraState previous, CameraState current, IntPtr userData) =>
899 Interrupted?.Invoke(this, new CameraInterruptedEventArgs(policy, previous, current));
901 CameraErrorFactory.ThrowIfError(Native.SetInterruptedCallback(_handle, _interruptedCallback, IntPtr.Zero),
902 "Failed to set interrupt callback");
905 private void RegisterErrorCallback()
907 _errorCallback = (CameraErrorCode error, CameraState current, IntPtr userData) =>
909 ErrorOccurred?.Invoke(this, new CameraErrorOccurredEventArgs(error, current));
911 CameraErrorFactory.ThrowIfError(Native.SetErrorCallback(_handle, _errorCallback, IntPtr.Zero),
912 "Setting error callback failed");
915 private void RegisterStateChangedCallback()
917 _stateChangedCallback = (CameraState previous, CameraState current, bool byPolicy, IntPtr _) =>
920 Log.Info(CameraLog.Tag, "Camera state changed " + previous.ToString() + " -> " + current.ToString());
921 StateChanged?.Invoke(this, new CameraStateChangedEventArgs(previous, current, byPolicy));
923 CameraErrorFactory.ThrowIfError(Native.SetStateChangedCallback(_handle, _stateChangedCallback, IntPtr.Zero),
924 "Setting state changed callback failed");
927 private static void RegisterDeviceStateChangedCallback()
929 _deviceStateChangedCallback = (CameraDevice device, CameraDeviceState state, IntPtr userData) =>
931 _deviceStateChanged?.Invoke(null, new CameraDeviceStateChangedEventArgs(device, state));
934 CameraErrorFactory.ThrowIfError(Native.SetDeviceStateChangedCallback(_deviceStateChangedCallback, IntPtr.Zero, out _deviceStateCallbackId),
935 "Failed to set device state changed callback");
937 Log.Info(CameraLog.Tag, "add callbackId " + _deviceStateCallbackId.ToString());
940 private static void UnregisterDeviceStateChangedCallback()
942 CameraErrorFactory.ThrowIfError(Native.UnsetDeviceStateChangedCallback(_deviceStateCallbackId),
943 "Unsetting device state changed callback failed");
944 _deviceStateChangedCallback = null;
945 _deviceStateCallbackId = 0;
948 private void RegisterFocusStateChanged()
950 _focusStateChangedCallback = (CameraFocusState state, IntPtr userData) =>
952 FocusStateChanged?.Invoke(this, new CameraFocusStateChangedEventArgs(state));
954 CameraErrorFactory.ThrowIfError(Native.SetFocusStateChangedCallback(_handle, _focusStateChangedCallback, IntPtr.Zero),
955 "Setting focus changed callback failed");
958 private void RegisterHdrCaptureProgress()
960 _hdrCaptureProgressCallback = (int percent, IntPtr userData) =>
962 _hdrCaptureProgress?.Invoke(this, new HdrCaptureProgressEventArgs(percent));
964 CameraErrorFactory.ThrowIfError(Native.SetHdrCaptureProgressCallback(_handle, _hdrCaptureProgressCallback, IntPtr.Zero),
965 "Setting Hdr capture progress callback failed");
968 private void UnregisterHdrCaptureProgress()
970 CameraErrorFactory.ThrowIfError(Native.UnsetHdrCaptureProgressCallback(_handle),
971 "Unsetting hdr capture progress is failed");
972 _hdrCaptureProgressCallback = null;
975 private void RegisterPreviewCallback()
977 _previewCallback = (IntPtr frame, IntPtr userData) =>
979 _preview?.Invoke(this, new PreviewEventArgs(new PreviewFrame(frame)));
981 CameraErrorFactory.ThrowIfError(Native.SetPreviewCallback(_handle, _previewCallback, IntPtr.Zero),
982 "Setting preview callback failed");
985 private void UnregisterPreviewCallback()
987 CameraErrorFactory.ThrowIfError(Native.UnsetPreviewCallback(_handle),
988 "Unsetting preview callback failed");
989 _previewCallback = null;
992 private void RegisterMediaPacketPreviewCallback()
994 _mediaPacketPreviewCallback = (IntPtr mediaPacket, IntPtr userData) =>
996 MediaPacket packet = MediaPacket.From(mediaPacket);
997 var eventHandler = _mediaPacketPreview;
999 if (eventHandler != null)
1001 eventHandler.Invoke(this, new MediaPacketPreviewEventArgs(packet));
1008 CameraErrorFactory.ThrowIfError(Native.SetMediaPacketPreviewCallback(_handle, _mediaPacketPreviewCallback, IntPtr.Zero),
1009 "Setting media packet preview callback failed");
1012 private void UnregisterMediaPacketPreviewCallback()
1014 CameraErrorFactory.ThrowIfError(Native.UnsetMediaPacketPreviewCallback(_handle),
1015 "Unsetting media packet preview callback failed");
1016 _mediaPacketPreviewCallback = null;
1018 #endregion Callback registrations