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;
23 using System.Collections;
24 namespace Tizen.Multimedia
26 static internal class CameraLog
28 internal const string Tag = "Tizen.Multimedia.Camera";
29 internal const string Enter = "[Enter]";
30 internal const string Leave = "[Leave]";
34 /// The camera class provides methods to capture photos and support setting up notifications
35 /// for state changes of capturing, previewing, focusing, information about resolution and binary format
36 /// and functions for picture manipulations like sepia negative and many more.
37 /// It also notifies you when a significant picture parameter changes e.g. focus.
40 /// http://tizen.org/privilege/camera
42 public class Camera : IDisposable
44 private IntPtr _handle = IntPtr.Zero;
45 private bool _disposed = false;
46 private CameraState _state = CameraState.None;
47 private static Dictionary<object, int> _callbackIdInfo = new Dictionary<object, int>();
50 /// Initializes a new instance of the <see cref="Camera"/> Class.
52 /// <param name="device">The camera device to access</param>
54 /// http://tizen.org/privilege/camera
56 public Camera(CameraDevice device)
58 CameraErrorFactory.ThrowIfError(Interop.Camera.Create((int)device, out _handle),
59 "Failed to create camera instance");
61 Feature = new CameraFeatures(this);
62 Setting = new CameraSettings(this);
63 Display = new CameraDisplay(this);
67 SetState(CameraState.Created);
71 /// Destructor of the camera class.
78 internal IntPtr GetHandle()
80 ValidateNotDisposed();
84 #region Dispose support
86 /// Release any unmanaged resources used by this object.
91 GC.SuppressFinalize(this);
94 protected virtual void Dispose(bool disposing)
100 // to be used if there are any other disposable objects
103 if (_handle != IntPtr.Zero)
105 Interop.Camera.Destroy(_handle);
106 _handle = IntPtr.Zero;
113 internal void ValidateNotDisposed()
117 Log.Error(CameraLog.Tag, "Camera handle is disposed.");
118 throw new ObjectDisposedException(nameof(Camera));
121 #endregion Dispose support
123 #region Check camera state
124 internal void ValidateState(params CameraState[] required)
126 ValidateNotDisposed();
128 Debug.Assert(required.Length > 0);
130 var curState = _state;
131 if (!required.Contains(curState))
133 throw new InvalidOperationException($"The camera is not in a valid state. " +
134 $"Current State : { curState }, Valid State : { string.Join(", ", required) }.");
138 internal void SetState(CameraState state)
142 #endregion Check camera state
144 #region EventHandlers
146 /// Event that occurs when an camera is interrupted by policy.
148 public event EventHandler<CameraInterruptedEventArgs> Interrupted;
149 private Interop.Camera.InterruptedCallback _interruptedCallback;
152 /// Event that occurs when there is an asynchronous error.
154 public event EventHandler<CameraErrorOccurredEventArgs> ErrorOccurred;
155 private Interop.Camera.ErrorCallback _errorCallback;
158 /// Event that occurs when the auto focus state is changed.
160 public event EventHandler<CameraFocusStateChangedEventArgs> FocusStateChanged;
161 private Interop.Camera.FocusStateChangedCallback _focusStateChangedCallback;
164 /// Event that occurs when a face is detected in preview frame.
166 public event EventHandler<FaceDetectedEventArgs> FaceDetected;
167 private Interop.Camera.FaceDetectedCallback _faceDetectedCallback;
170 /// Event that occurs during capture of image.
172 public event EventHandler<CameraCapturingEventArgs> Capturing;
173 private Interop.Camera.CapturingCallback _capturingCallback;
176 /// Event that occurs after the capture of the image.
178 public event EventHandler<EventArgs> CaptureCompleted;
179 private Interop.Camera.CaptureCompletedCallback _captureCompletedCallback;
182 /// Event that occurs when there is change in HDR capture progress.
183 /// Check whether HdrCapture feature is supported or not before add this EventHandler.
185 public event EventHandler<HdrCaptureProgressEventArgs> HdrCaptureProgress;
186 private Interop.Camera.HdrCaptureProgressCallback _hdrCaptureProgressCallback;
189 /// Event that occurs when camera state is changed.
191 public event EventHandler<CameraStateChangedEventArgs> StateChanged;
192 private Interop.Camera.StateChangedCallback _stateChangedCallback;
194 #region DeviceStateChanged callback
195 internal static Interop.Camera.DeviceStateChangedCallback _deviceStateChangedCallback;
196 public static event EventHandler<CameraDeviceStateChangedEventArgs> _deviceStateChanged;
197 public static object _deviceStateChangedEventLock = new object();
200 /// Set the DeviceStateChanged Callback.
201 /// User doesn't need to create camera instance.
202 /// This static EventHandler calls platform function every time because each callback function have to remain its own callbackId.
204 /// <param name="callback">Callback of type <see cref="Interop.Camera.DeviceStateChangedCallback"/>.</param>
205 /// <param name="callbackId">The Id of registered callback.</param>
206 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
207 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
208 /// <exception cref="ArgumentException">In case of invalid parameters</exception>
209 public static event EventHandler<CameraDeviceStateChangedEventArgs> DeviceStateChanged
213 lock (_deviceStateChangedEventLock)
217 _deviceStateChangedCallback = (CameraDevice device, CameraDeviceState state, IntPtr userData) =>
219 _deviceStateChanged?.Invoke(null, new CameraDeviceStateChangedEventArgs(device, state));
221 CameraErrorFactory.ThrowIfError(Interop.Camera.SetDeviceStateChangedCallback(_deviceStateChangedCallback, IntPtr.Zero, out callbackId),
222 "Failed to set interrupt callback");
224 // Keep current callbackId and EventHandler pair to remove EventHandler later.
225 _callbackIdInfo.Add(value, callbackId);
226 Log.Info(CameraLog.Tag, "add callbackId " + callbackId.ToString());
228 _deviceStateChanged += value;
234 lock (_deviceStateChangedEventLock)
236 _deviceStateChanged -= value;
239 _callbackIdInfo.TryGetValue(value, out callbackId);
240 Log.Info(CameraLog.Tag, "remove callbackId " + callbackId.ToString());
242 CameraErrorFactory.ThrowIfError(Interop.Camera.UnsetDeviceStateChangedCallback(callbackId),
243 "Unsetting media packet preview callback failed");
245 _callbackIdInfo.Remove(value);
247 if (_deviceStateChanged == null)
249 _deviceStateChangedCallback = null;
254 #endregion DeviceStateChanged callback
256 #region Preview EventHandler
257 private Interop.Camera.PreviewCallback _previewCallback;
258 private event EventHandler<PreviewEventArgs> _preview;
259 private object _previewEventLock = new object();
261 /// Event that occurs once per frame when previewing.
262 /// Preview callback is registered when user add callback explicitly to avoid useless P/Invoke.
264 public event EventHandler<PreviewEventArgs> Preview
268 lock (_previewEventLock)
270 if (_preview == null)
272 RegisterPreviewCallback();
281 lock (_previewEventLock)
285 if (_preview == null)
287 CameraErrorFactory.ThrowIfError(Interop.Camera.UnsetPreviewCallback(_handle),
288 "Unsetting preview callback failed");
289 _previewCallback = null;
294 #endregion Preview EventHandler
296 #region MediaPacketPreview EventHandler
297 private Interop.Camera.MediaPacketPreviewCallback _mediaPacketPreviewCallback;
298 private EventHandler<MediaPacketPreviewEventArgs> _mediaPacketPreview;
299 private object _mediaPacketPreviewEventLock = new object();
302 /// Event that occurs once per frame when previewing.
303 /// Preview callback is registered when user add callback explicitly to avoid useless P/Invoke.
305 public event EventHandler<MediaPacketPreviewEventArgs> MediaPacketPreview
309 lock (_mediaPacketPreviewEventLock)
311 if (_mediaPacketPreview == null)
313 RegisterMediaPacketPreviewCallback();
316 _mediaPacketPreview += value;
322 lock (_mediaPacketPreviewEventLock)
324 _mediaPacketPreview -= value;
326 if (_mediaPacketPreview == null)
328 CameraErrorFactory.ThrowIfError(Interop.Camera.UnsetMediaPacketPreviewCallback(_handle),
329 "Unsetting media packet preview callback failed");
330 _mediaPacketPreviewCallback = null;
335 #endregion MediaPacketPreview EventHandler
337 #endregion EventHandlers
341 /// Get/Set the various camera settings.
343 public CameraSettings Setting { get; }
346 /// Gets the various camera features.
348 public CameraFeatures Feature { get; }
351 /// Get/set various camera display properties.
353 public CameraDisplay Display { get; }
356 /// Gets the state of the camera.
358 /// <value> None, Created, Preview, Capturing, Captured </value>
359 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
360 public CameraState State
364 ValidateNotDisposed();
366 CameraState val = CameraState.None;
367 CameraErrorFactory.ThrowIfError(Interop.Camera.GetState(_handle, out val),
368 "Failed to get camera state");
375 /// The hint for display reuse.
376 /// If the hint is set to true, the display will be reused when the camera device is changed with
377 /// ChangeDevice method.
379 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
380 /// <exception cref="InvalidOperationException">Invalid state.</exception>
381 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
382 public bool DisplayReuseHint
386 ValidateNotDisposed();
390 CameraErrorFactory.ThrowIfError(Interop.Camera.GetDisplayReuseHint(_handle, out val),
391 "Failed to get camera display reuse hint");
398 ValidateState(CameraState.Preview);
400 CameraErrorFactory.ThrowIfError(Interop.Camera.SetDisplayReuseHint(_handle, value),
401 "Failed to set display reuse hint.");
406 /// Gets the facing direction of camera module.
408 /// <value>A <see cref="CameraFacingDirection"/> that specifies the facing direction of camera device.</value>
409 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
410 public CameraFacingDirection Direction
414 ValidateNotDisposed();
416 CameraFacingDirection val = 0;
418 CameraErrorFactory.ThrowIfError(Interop.Camera.GetFacingDirection(_handle, out val),
419 "Failed to get camera direction");
426 /// Gets the camera device count.
428 /// <value>This returns 2, if the device supports primary and secondary cameras.
429 /// Otherwise 1, if the device only supports primary camera.</value>
430 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
431 public int CameraCount
435 ValidateNotDisposed();
439 CameraErrorFactory.ThrowIfError(Interop.Camera.GetDeviceCount(_handle, out val),
440 "Failed to get camera device count");
445 #endregion Properties
449 /// Changes the camera device.
451 /// <param name="device">The hardware camera to access.</param>
453 /// http://tizen.org/privilege/camera
456 /// If display reuse is set using <see cref="DisplayReuseHint"/>
457 /// before stopping the preview, the display will be reused and last frame on the display
458 /// can be kept even though camera device is changed.
459 /// The camera must be in the <see cref="CameraState.Created"/> or <see cref="CameraState.Preview"/> state.
461 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
462 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
463 /// <exception cref="NotSupportedException">In case of ChangeDevice feature is not supported.</exception>
464 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
465 public void ChangeDevice(CameraDevice device)
467 ValidateState(CameraState.Created, CameraState.Preview);
469 CameraErrorFactory.ThrowIfError(Interop.Camera.ChangeDevice(_handle, (int)device),
470 "Failed to change the camera device");
474 /// Gets the device state.
477 /// http://tizen.org/privilege/camera
479 /// <param name="device">The device to get state.</param>
480 /// <returns>Returns the state of camera device</returns>
481 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
482 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
483 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
484 public CameraDeviceState GetDeviceState(CameraDevice device)
488 CameraErrorFactory.ThrowIfError(Interop.Camera.GetDeviceState(device, out val),
489 "Failed to get the camera device state.");
491 return (CameraDeviceState)val;
495 /// Gets the flash state.
498 /// http://tizen.org/privilege/camera
500 /// <param name="device">The device to get state.</param>
501 /// <returns>Returns the flash state of camera device</returns>
502 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
503 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
504 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
505 public static CameraFlashState GetFlashState(CameraDevice device)
507 CameraFlashState val = CameraFlashState.NotUsed;
509 CameraErrorFactory.ThrowIfError(Interop.Camera.GetFlashState(device, out val),
510 "Failed to get camera flash state");
516 /// Starts capturing and drawing preview frames on the screen.
517 /// The display handle must be set using <see cref="CameraDisplay.SetInfo"/>
518 /// before using this method.
519 /// If needed set fps <see cref="CameraSettings.PreviewFps"/>, preview resolution
520 /// <see cref="CameraSettings.PreviewResolution"/>, or preview format <see cref="CameraSettings.PreviewPixelFormat"/>
521 /// before using this method.
522 /// The camera must be in the <see cref="CameraState.Created"/> or <see cref="CameraState.Captured"/> state.
525 /// http://tizen.org/privilege/camera
527 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
528 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
529 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
530 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
531 public void StartPreview()
533 ValidateState(CameraState.Created, CameraState.Captured);
535 CameraErrorFactory.ThrowIfError(Interop.Camera.StartPreview(_handle),
536 "Failed to start the camera preview.");
538 // Update by StateChangedCallback can be delayed for dozens of milliseconds.
539 SetState(CameraState.Preview);
543 /// Stops capturing and drawing preview frames on the screen.
544 /// The camera must be in the <see cref="CameraState.Preview"/> state.
547 /// http://tizen.org/privilege/camera
549 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
550 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
551 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
552 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
553 public void StopPreview()
555 ValidateState(CameraState.Preview);
557 CameraErrorFactory.ThrowIfError(Interop.Camera.StopPreview(_handle),
558 "Failed to stop the camera preview.");
560 SetState(CameraState.Created);
564 /// Starts capturing of still images.
565 /// EventHandler must be set for capturing using <see cref="Capturing"/>
566 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
567 /// The camera must be in the <see cref="CameraState.Preview"/> state.
570 /// http://tizen.org/privilege/camera
573 /// This function causes the transition of the camera state from Capturing to Captured
574 /// automatically and the corresponding EventHandlers will be invoked.
575 /// The preview should be restarted by calling <see cref="StartPreview"/> method after capture is completed.
577 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
578 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
579 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
580 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
581 public void StartCapture()
583 ValidateState(CameraState.Preview);
585 CameraErrorFactory.ThrowIfError(Interop.Camera.StartCapture(_handle, _capturingCallback, _captureCompletedCallback, IntPtr.Zero),
586 "Failed to start the camera capture.");
588 SetState(CameraState.Capturing);
592 /// Starts continuously capturing still images.
593 /// EventHandler must be set for capturing using <see cref="Capturing"/>
594 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
595 /// The camera must be in the <see cref="CameraState.Preview"/> state.
598 /// http://tizen.org/privilege/camera
600 /// <param name="count">The number of still images.</param>
601 /// <param name="interval">The interval of the capture(milliseconds).</param>
602 /// <param name="cancellationToken">The cancellation token to cancel capturing.</param>
603 /// <seealso cref="System.Threading.CancellationToken"/>
605 /// If this is not supported zero shutter lag occurs. The capture resolution could be
606 /// changed to the preview resolution. This function causes the transition of the camera state
607 /// from Capturing to Captured automatically and the corresponding Eventhandlers will be invoked.
608 /// Each captured image will be delivered through Eventhandler set using <see cref="Capturing"/> event.
609 /// The preview should be restarted by calling <see cref="StartPreview"/> method after capture is completed.
611 /// <exception cref="ArgumentOutOfRangeException">In case of invalid parameters.</exception>
612 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
613 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
614 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
615 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
616 public void StartCapture(int count, int interval, CancellationToken cancellationToken)
618 ValidateState(CameraState.Preview);
622 throw new ArgumentOutOfRangeException(nameof(count), count, $"{nameof(count)} should be greater than one.");
627 throw new ArgumentOutOfRangeException(nameof(interval), interval, $"{nameof(interval)} should be greater than or equal to zero.");
630 //Handle CancellationToken
631 if (cancellationToken != CancellationToken.None)
633 cancellationToken.Register(() =>
635 CameraErrorFactory.ThrowIfError(Interop.Camera.StopContinuousCapture(_handle),
636 "Failed to cancel the continuous capture");
637 SetState(CameraState.Captured);
641 CameraErrorFactory.ThrowIfError(Interop.Camera.StartContinuousCapture(_handle, count, interval,
642 _capturingCallback, _captureCompletedCallback, IntPtr.Zero), "Failed to start the continuous capture.");
644 SetState(CameraState.Capturing);
648 /// Starts camera auto-focusing, asynchronously.
649 /// The camera must be in the <see cref="CameraState.Preview"/> or <see cref="CameraState.Captured"/> state.
651 /// <param name="continuous">Continuous auto focus</param>
653 /// http://tizen.org/privilege/camera
656 /// If continuous status is true, the camera continuously tries to focus.
658 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
659 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
660 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
661 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
662 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
663 public void StartFocusing(bool continuous)
665 ValidateState(CameraState.Preview, CameraState.Captured);
667 CameraErrorFactory.ThrowIfError(Interop.Camera.StartFocusing(_handle, continuous),
668 "Failed to cancel the camera focus.");
672 /// Stops camera auto focusing.
673 /// The camera must be in the <see cref="CameraState.Preview"/> or <see cref="CameraState.Captured"/> state.
676 /// http://tizen.org/privilege/camera
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.</exception>
681 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
682 public void StopFocusing()
684 ValidateState(CameraState.Preview, CameraState.Captured);
686 CameraErrorFactory.ThrowIfError(Interop.Camera.CancelFocusing(_handle),
687 "Failed to cancel the camera focus.");
691 /// Starts face detection.
692 /// The camera must be in the <see cref="CameraState.Preview"/> state.
695 /// http://tizen.org/privilege/camera
698 /// This should be called after <see cref="StartPreview"/> is started.
699 /// The Eventhandler set using <see cref="FaceDetected"/> invoked when the face is detected in preview frame.
700 /// Internally it starts continuous focus and focusing on the detected face.
702 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
703 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
704 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
705 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
706 public void StartFaceDetection()
708 ValidateState(CameraState.Preview);
710 _faceDetectedCallback = (IntPtr faces, int count, IntPtr userData) =>
712 var result = new List<FaceDetectionData>();
713 IntPtr current = faces;
715 for (int i = 0; i < count; i++)
717 result.Add(new FaceDetectionData(current));
718 current = IntPtr.Add(current, Marshal.SizeOf<Interop.Camera.DetectedFaceStruct>());
721 FaceDetected?.Invoke(this, new FaceDetectedEventArgs(result));
723 CameraErrorFactory.ThrowIfError(Interop.Camera.StartFaceDetection(_handle, _faceDetectedCallback, IntPtr.Zero),
724 "Failed to start face detection");
728 /// Stops face detection.
731 /// http://tizen.org/privilege/camera
733 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
734 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
735 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
736 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
737 public void StopFaceDetection()
739 if (_faceDetectedCallback == null)
741 throw new InvalidOperationException("The face detection is not started.");
744 CameraErrorFactory.ThrowIfError(Interop.Camera.StopFaceDetection(_handle),
745 "Failed to stop the face detection.");
747 _faceDetectedCallback = null;
751 #region Callback registrations
752 private void RegisterCallbacks()
754 RegisterErrorCallback();
755 RegisterFocusStateChanged();
756 RegisterHdrCaptureProgress();
757 RegisterInterruptedCallback();
758 RegisterStateChangedCallback();
760 //Define capturing callback
761 _capturingCallback = (IntPtr image, IntPtr postview, IntPtr thumbnail, IntPtr userData) =>
763 Capturing?.Invoke(this, new CameraCapturingEventArgs(new ImageData(image),
764 postview == IntPtr.Zero ? null : new ImageData(postview),
765 thumbnail == IntPtr.Zero ? null : new ImageData(thumbnail)));
768 //Define captureCompleted callback
769 _captureCompletedCallback = _ =>
771 SetState(CameraState.Captured);
772 CaptureCompleted?.Invoke(this, EventArgs.Empty);
776 private void RegisterInterruptedCallback()
778 _interruptedCallback = (CameraPolicy policy, CameraState previous, CameraState current, IntPtr userData) =>
780 Interrupted?.Invoke(this, new CameraInterruptedEventArgs(policy, previous, current));
782 CameraErrorFactory.ThrowIfError(Interop.Camera.SetInterruptedCallback(_handle, _interruptedCallback, IntPtr.Zero),
783 "Failed to set interrupt callback");
786 private void RegisterErrorCallback()
788 _errorCallback = (CameraErrorCode error, CameraState current, IntPtr userData) =>
790 ErrorOccurred?.Invoke(this, new CameraErrorOccurredEventArgs(error, current));
792 CameraErrorFactory.ThrowIfError(Interop.Camera.SetErrorCallback(_handle, _errorCallback, IntPtr.Zero),
793 "Setting error callback failed");
796 private void RegisterStateChangedCallback()
798 _stateChangedCallback = (CameraState previous, CameraState current, bool byPolicy, IntPtr _) =>
801 Log.Info(CameraLog.Tag, "Camera state changed " + previous.ToString() + " -> " + current.ToString());
802 StateChanged?.Invoke(this, new CameraStateChangedEventArgs(previous, current, byPolicy));
804 CameraErrorFactory.ThrowIfError(Interop.Camera.SetStateChangedCallback(_handle, _stateChangedCallback, IntPtr.Zero),
805 "Setting state changed callback failed");
808 private void RegisterFocusStateChanged()
810 _focusStateChangedCallback = (CameraFocusState state, IntPtr userData) =>
812 FocusStateChanged?.Invoke(this, new CameraFocusStateChangedEventArgs(state));
814 CameraErrorFactory.ThrowIfError(Interop.Camera.SetFocusStateChangedCallback(_handle, _focusStateChangedCallback, IntPtr.Zero),
815 "Setting focus changed callback failed");
818 private void RegisterHdrCaptureProgress()
820 //Hdr Capture can not be supported.
821 if (Feature.IsHdrCaptureSupported)
823 _hdrCaptureProgressCallback = (int percent, IntPtr userData) =>
825 HdrCaptureProgress?.Invoke(this, new HdrCaptureProgressEventArgs(percent));
827 CameraErrorFactory.ThrowIfError(Interop.Camera.SetHdrCaptureProgressCallback(_handle, _hdrCaptureProgressCallback, IntPtr.Zero),
828 "Setting Hdr capture progress callback failed");
832 private void RegisterPreviewCallback()
834 _previewCallback = (IntPtr frame, IntPtr userData) =>
836 _preview?.Invoke(this, new PreviewEventArgs(new PreviewData(frame)));
838 CameraErrorFactory.ThrowIfError(Interop.Camera.SetPreviewCallback(_handle, _previewCallback, IntPtr.Zero),
839 "Setting preview callback failed");
842 private void RegisterMediaPacketPreviewCallback()
844 _mediaPacketPreviewCallback = (IntPtr mediaPacket, IntPtr userData) =>
846 MediaPacket packet = MediaPacket.From(mediaPacket);
847 var eventHandler = _mediaPacketPreview;
849 if (eventHandler != null)
851 eventHandler.Invoke(this, new MediaPacketPreviewEventArgs(packet));
858 CameraErrorFactory.ThrowIfError(Interop.Camera.SetMediaPacketPreviewCallback(_handle, _mediaPacketPreviewCallback, IntPtr.Zero),
859 "Setting media packet preview callback failed");
861 #endregion Callback registrations