2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using System.Collections.Generic;
19 using System.Diagnostics;
21 using System.Runtime.InteropServices;
22 using System.Threading;
24 using Native = Interop.Camera;
26 namespace Tizen.Multimedia
28 static internal class CameraLog
30 internal const string Tag = "Tizen.Multimedia.Camera";
31 internal const string Enter = "[Enter]";
32 internal const string Leave = "[Leave]";
36 /// The camera class provides methods to capture photos and support setting up notifications
37 /// for state changes of capturing, previewing, focusing, information about resolution and binary format
38 /// and functions for picture manipulations like sepia negative and many more.
39 /// It also notifies you when a significant picture parameter changes e.g. focus.
41 public class Camera : IDisposable, IDisplayable<CameraError>
43 private IntPtr _handle = IntPtr.Zero;
44 private bool _disposed = false;
45 private CameraState _state = CameraState.None;
46 private static Dictionary<object, int> _callbackIdInfo = new Dictionary<object, int>();
49 /// Initializes a new instance of the <see cref="Camera"/> Class.
51 /// <param name="device">The camera device to access</param>
52 public Camera(CameraDevice device)
54 CameraErrorFactory.ThrowIfError(Native.Create((int)device, out _handle),
55 "Failed to create camera instance");
57 Feature = new CameraFeatures(this);
58 Setting = new CameraSettings(this);
59 DisplaySettings = new CameraDisplaySettings(this);
63 SetState(CameraState.Created);
67 /// Destructor of the camera class.
74 public IntPtr Handle => GetHandle();
76 internal IntPtr GetHandle()
78 ValidateNotDisposed();
82 #region Dispose support
84 /// Release any unmanaged resources used by this object.
89 GC.SuppressFinalize(this);
92 protected virtual void Dispose(bool disposing)
98 // to be used if there are any other disposable objects
101 if (_handle != IntPtr.Zero)
103 Native.Destroy(_handle);
104 _handle = IntPtr.Zero;
111 internal void ValidateNotDisposed()
115 Log.Error(CameraLog.Tag, "Camera handle is disposed.");
116 throw new ObjectDisposedException(nameof(Camera));
119 #endregion Dispose support
121 #region Check camera state
122 internal void ValidateState(params CameraState[] required)
124 ValidateNotDisposed();
126 Debug.Assert(required.Length > 0);
128 var curState = _state;
129 if (!required.Contains(curState))
131 throw new InvalidOperationException($"The camera is not in a valid state. " +
132 $"Current State : { curState }, Valid State : { string.Join(", ", required) }.");
136 internal void SetState(CameraState state)
140 #endregion Check camera state
142 #region EventHandlers
144 /// Event that occurs when an camera is interrupted by policy.
146 public event EventHandler<CameraInterruptedEventArgs> Interrupted;
147 private Native.InterruptedCallback _interruptedCallback;
150 /// Event that occurs when there is an asynchronous error.
152 public event EventHandler<CameraErrorOccurredEventArgs> ErrorOccurred;
153 private Native.ErrorCallback _errorCallback;
156 /// Event that occurs when the auto focus state is changed.
158 public event EventHandler<CameraFocusStateChangedEventArgs> FocusStateChanged;
159 private Native.FocusStateChangedCallback _focusStateChangedCallback;
162 /// Event that occurs when a face is detected in preview frame.
164 public event EventHandler<FaceDetectedEventArgs> FaceDetected;
165 private Native.FaceDetectedCallback _faceDetectedCallback;
168 /// Event that occurs during capture of image.
170 public event EventHandler<CameraCapturingEventArgs> Capturing;
171 private Native.CapturingCallback _capturingCallback;
174 /// Event that occurs after the capture of the image.
176 public event EventHandler<EventArgs> CaptureCompleted;
177 private Native.CaptureCompletedCallback _captureCompletedCallback;
180 /// Event that occurs when there is change in HDR capture progress.
181 /// Check whether HdrCapture feature is supported or not before add this EventHandler.
183 public event EventHandler<HdrCaptureProgressEventArgs> HdrCaptureProgress;
184 private Native.HdrCaptureProgressCallback _hdrCaptureProgressCallback;
187 /// Event that occurs when camera state is changed.
189 public event EventHandler<CameraStateChangedEventArgs> StateChanged;
190 private Native.StateChangedCallback _stateChangedCallback;
192 #region DeviceStateChanged callback
193 internal static Native.DeviceStateChangedCallback _deviceStateChangedCallback;
194 private static event EventHandler<CameraDeviceStateChangedEventArgs> _deviceStateChanged;
195 private static object _deviceStateChangedEventLock = new object();
198 /// Set the DeviceStateChanged Callback.
199 /// User doesn't need to create camera instance.
200 /// This static EventHandler calls platform function every time because each callback function have to remain its own callbackId.
202 /// <param name="callback">Callback of type <see cref="Native.DeviceStateChangedCallback"/>.</param>
203 /// <param name="callbackId">The Id of registered callback.</param>
204 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
205 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
206 /// <exception cref="ArgumentException">In case of invalid parameters</exception>
207 public static event EventHandler<CameraDeviceStateChangedEventArgs> DeviceStateChanged
211 lock (_deviceStateChangedEventLock)
215 _deviceStateChangedCallback = (CameraDevice device, CameraDeviceState state, IntPtr userData) =>
217 _deviceStateChanged?.Invoke(null, new CameraDeviceStateChangedEventArgs(device, state));
219 CameraErrorFactory.ThrowIfError(Native.SetDeviceStateChangedCallback(_deviceStateChangedCallback, IntPtr.Zero, out callbackId),
220 "Failed to set interrupt callback");
222 // Keep current callbackId and EventHandler pair to remove EventHandler later.
223 _callbackIdInfo.Add(value, callbackId);
224 Log.Info(CameraLog.Tag, "add callbackId " + callbackId.ToString());
226 _deviceStateChanged += value;
232 lock (_deviceStateChangedEventLock)
234 _deviceStateChanged -= value;
237 _callbackIdInfo.TryGetValue(value, out callbackId);
238 Log.Info(CameraLog.Tag, "remove callbackId " + callbackId.ToString());
240 CameraErrorFactory.ThrowIfError(Native.UnsetDeviceStateChangedCallback(callbackId),
241 "Unsetting media packet preview callback failed");
243 _callbackIdInfo.Remove(value);
245 if (_deviceStateChanged == null)
247 _deviceStateChangedCallback = null;
252 #endregion DeviceStateChanged callback
254 #region Preview EventHandler
255 private Native.PreviewCallback _previewCallback;
256 private event EventHandler<PreviewEventArgs> _preview;
257 private object _previewEventLock = new object();
259 /// Event that occurs once per frame when previewing.
260 /// Preview callback is registered when user add callback explicitly to avoid useless P/Invoke.
262 public event EventHandler<PreviewEventArgs> Preview
266 lock (_previewEventLock)
268 if (_preview == null)
270 RegisterPreviewCallback();
279 lock (_previewEventLock)
283 if (_preview == null)
285 CameraErrorFactory.ThrowIfError(Native.UnsetPreviewCallback(_handle),
286 "Unsetting preview callback failed");
287 _previewCallback = null;
292 #endregion Preview EventHandler
294 #region MediaPacketPreview EventHandler
295 private Native.MediaPacketPreviewCallback _mediaPacketPreviewCallback;
296 private EventHandler<MediaPacketPreviewEventArgs> _mediaPacketPreview;
297 private object _mediaPacketPreviewEventLock = new object();
300 /// Event that occurs once per frame when previewing.
301 /// Preview callback is registered when user add callback explicitly to avoid useless P/Invoke.
303 public event EventHandler<MediaPacketPreviewEventArgs> MediaPacketPreview
307 lock (_mediaPacketPreviewEventLock)
309 if (_mediaPacketPreview == null)
311 RegisterMediaPacketPreviewCallback();
314 _mediaPacketPreview += value;
320 lock (_mediaPacketPreviewEventLock)
322 _mediaPacketPreview -= value;
324 if (_mediaPacketPreview == null)
326 CameraErrorFactory.ThrowIfError(Native.UnsetMediaPacketPreviewCallback(_handle),
327 "Unsetting media packet preview callback failed");
328 _mediaPacketPreviewCallback = null;
333 #endregion MediaPacketPreview EventHandler
335 #endregion EventHandlers
339 /// Get/Set the various camera settings.
341 public CameraSettings Setting { get; }
344 /// Gets the various camera features.
346 public CameraFeatures Feature { get; }
349 /// Get/set various camera display properties.
351 public CameraDisplaySettings DisplaySettings{ get; }
353 private Display _display;
355 private CameraError SetDisplay(Display display)
359 return CameraDisplay.SetTarget(GetHandle(), DisplayType.None, IntPtr.Zero);
362 return display.ApplyTo(this);
365 private void ReplaceDisplay(Display newDisplay)
367 if (_display != null)
369 _display.Owner = null;
371 _display = newDisplay;
372 if (_display != null)
374 _display.Owner = this;
379 /// Sets or gets the display type and handle to show preview images.
380 /// The camera must be in the <see cref="CameraState.Created"/> state.
383 /// This must be set before StartPreview() method.
384 /// In Custom ROI display mode, DisplayRoiArea property must be set before calling this method.
386 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
387 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
388 /// <exception cref="ObjectDisposedException" > The camera already has been disposed.</exception>
389 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
390 public Display Display
398 ValidateState(CameraState.Created);
400 if (value != null && value.Owner != null)
402 if (ReferenceEquals(this, value.Owner))
408 throw new ArgumentException("The display has already been assigned to another.");
411 CameraErrorFactory.ThrowIfError(SetDisplay(value), "Failed to set the camera display");
413 ReplaceDisplay(value);
417 CameraError IDisplayable<CameraError>.ApplyEvasDisplay(DisplayType type, ElmSharp.EvasObject evasObject)
419 Debug.Assert(_disposed == false);
421 Debug.Assert(Enum.IsDefined(typeof(DisplayType), type));
423 return CameraDisplay.SetTarget(GetHandle(), type, evasObject);
427 /// Gets the state of the camera.
429 /// <value> None, Created, Preview, Capturing, Captured </value>
430 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
431 public CameraState State
435 ValidateNotDisposed();
437 CameraState val = CameraState.None;
438 CameraErrorFactory.ThrowIfError(Native.GetState(_handle, out val),
439 "Failed to get camera state");
446 /// The hint for display reuse.
447 /// If the hint is set to true, the display will be reused when the camera device is changed with
448 /// ChangeDevice method.
450 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
451 /// <exception cref="InvalidOperationException">Invalid state.</exception>
452 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
453 public bool DisplayReuseHint
457 ValidateNotDisposed();
461 CameraErrorFactory.ThrowIfError(Native.GetDisplayReuseHint(_handle, out val),
462 "Failed to get camera display reuse hint");
469 ValidateState(CameraState.Preview);
471 CameraErrorFactory.ThrowIfError(Native.SetDisplayReuseHint(_handle, value),
472 "Failed to set display reuse hint.");
477 /// Gets the facing direction of camera module.
479 /// <value>A <see cref="CameraFacingDirection"/> that specifies the facing direction of camera device.</value>
480 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
481 public CameraFacingDirection Direction
485 ValidateNotDisposed();
487 CameraFacingDirection val = 0;
489 CameraErrorFactory.ThrowIfError(Native.GetFacingDirection(_handle, out val),
490 "Failed to get camera direction");
497 /// Gets the camera device count.
499 /// <value>This returns 2, if the device supports primary and secondary cameras.
500 /// Otherwise 1, if the device only supports primary camera.</value>
501 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
502 public int CameraCount
506 ValidateNotDisposed();
510 CameraErrorFactory.ThrowIfError(Native.GetDeviceCount(_handle, out val),
511 "Failed to get camera device count");
516 #endregion Properties
520 /// Changes the camera device.
522 /// <param name="device">The hardware camera to access.</param>
524 /// If display reuse is set using <see cref="DisplayReuseHint"/>
525 /// before stopping the preview, the display will be reused and last frame on the display
526 /// can be kept even though camera device is changed.
527 /// The camera must be in the <see cref="CameraState.Created"/> or <see cref="CameraState.Preview"/> state.
529 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
530 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
531 /// <exception cref="NotSupportedException">In case of ChangeDevice feature is not supported.</exception>
532 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
533 public void ChangeDevice(CameraDevice device)
535 ValidateState(CameraState.Created, CameraState.Preview);
537 CameraErrorFactory.ThrowIfError(Native.ChangeDevice(_handle, (int)device),
538 "Failed to change the camera device");
542 /// Gets the device state.
544 /// <param name="device">The device to get state.</param>
545 /// <returns>Returns the state of camera device</returns>
546 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
547 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
548 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
549 public CameraDeviceState GetDeviceState(CameraDevice device)
553 CameraErrorFactory.ThrowIfError(Native.GetDeviceState(device, out val),
554 "Failed to get the camera device state.");
556 return (CameraDeviceState)val;
560 /// Gets the flash state.
562 /// <param name="device">The device to get state.</param>
563 /// <returns>Returns the flash state of camera device</returns>
564 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
565 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
566 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
567 public static CameraFlashState GetFlashState(CameraDevice device)
569 CameraFlashState val = CameraFlashState.NotUsed;
571 CameraErrorFactory.ThrowIfError(Native.GetFlashState(device, out val),
572 "Failed to get camera flash state");
578 /// Starts capturing and drawing preview frames on the screen.
579 /// The display handle must be set using <see cref="CameraDisplaySettings.SetInfo"/>
580 /// before using this method.
581 /// If needed set fps <see cref="CameraSettings.PreviewFps"/>, preview resolution
582 /// <see cref="CameraSettings.PreviewResolution"/>, or preview format <see cref="CameraSettings.PreviewPixelFormat"/>
583 /// before using this method.
584 /// The camera must be in the <see cref="CameraState.Created"/> or <see cref="CameraState.Captured"/> state.
587 /// http://tizen.org/privilege/camera
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 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
592 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
593 public void StartPreview()
595 ValidateState(CameraState.Created, CameraState.Captured);
597 CameraErrorFactory.ThrowIfError(Native.StartPreview(_handle),
598 "Failed to start the camera preview.");
600 // Update by StateChangedCallback can be delayed for dozens of milliseconds.
601 SetState(CameraState.Preview);
605 /// Stops capturing and drawing preview frames on the screen.
606 /// The camera must be in the <see cref="CameraState.Preview"/> state.
609 /// http://tizen.org/privilege/camera
611 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
612 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
613 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
614 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
615 public void StopPreview()
617 ValidateState(CameraState.Preview);
619 CameraErrorFactory.ThrowIfError(Native.StopPreview(_handle),
620 "Failed to stop the camera preview.");
622 SetState(CameraState.Created);
626 /// Starts capturing of still images.
627 /// EventHandler must be set for capturing using <see cref="Capturing"/>
628 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
629 /// The camera must be in the <see cref="CameraState.Preview"/> state.
632 /// http://tizen.org/privilege/camera
635 /// This function causes the transition of the camera state from Capturing to Captured
636 /// automatically and the corresponding EventHandlers will be invoked.
637 /// The preview should be restarted by calling <see cref="StartPreview"/> method after capture is completed.
639 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
640 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
641 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
642 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
643 public void StartCapture()
645 ValidateState(CameraState.Preview);
647 CameraErrorFactory.ThrowIfError(Native.StartCapture(_handle, _capturingCallback, _captureCompletedCallback, IntPtr.Zero),
648 "Failed to start the camera capture.");
650 SetState(CameraState.Capturing);
654 /// Starts continuously capturing still images.
655 /// EventHandler must be set for capturing using <see cref="Capturing"/>
656 /// and for completed using <see cref="CaptureCompleted"/> before calling this method.
657 /// The camera must be in the <see cref="CameraState.Preview"/> state.
660 /// http://tizen.org/privilege/camera
662 /// <param name="count">The number of still images.</param>
663 /// <param name="interval">The interval of the capture(milliseconds).</param>
664 /// <param name="cancellationToken">The cancellation token to cancel capturing.</param>
665 /// <seealso cref="System.Threading.CancellationToken"/>
667 /// If this is not supported zero shutter lag occurs. The capture resolution could be
668 /// changed to the preview resolution. This function causes the transition of the camera state
669 /// from Capturing to Captured automatically and the corresponding Eventhandlers will be invoked.
670 /// Each captured image will be delivered through Eventhandler set using <see cref="Capturing"/> event.
671 /// The preview should be restarted by calling <see cref="StartPreview"/> method after capture is completed.
673 /// <exception cref="ArgumentOutOfRangeException">In case of invalid parameters.</exception>
674 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
675 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
676 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
677 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
678 public void StartCapture(int count, int interval, CancellationToken cancellationToken)
680 ValidateState(CameraState.Preview);
684 throw new ArgumentOutOfRangeException(nameof(count), count, $"{nameof(count)} should be greater than one.");
689 throw new ArgumentOutOfRangeException(nameof(interval), interval, $"{nameof(interval)} should be greater than or equal to zero.");
692 //Handle CancellationToken
693 if (cancellationToken != CancellationToken.None)
695 cancellationToken.Register(() =>
697 CameraErrorFactory.ThrowIfError(Native.StopContinuousCapture(_handle),
698 "Failed to cancel the continuous capture");
699 SetState(CameraState.Captured);
703 CameraErrorFactory.ThrowIfError(Native.StartContinuousCapture(_handle, count, interval,
704 _capturingCallback, _captureCompletedCallback, IntPtr.Zero), "Failed to start the continuous capture.");
706 SetState(CameraState.Capturing);
710 /// Starts camera auto-focusing, asynchronously.
711 /// The camera must be in the <see cref="CameraState.Preview"/> or <see cref="CameraState.Captured"/> state.
713 /// <param name="continuous">Continuous auto focus</param>
715 /// http://tizen.org/privilege/camera
718 /// If continuous status is true, the camera continuously tries to focus.
720 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
721 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
722 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
723 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
724 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
725 public void StartFocusing(bool continuous)
727 ValidateState(CameraState.Preview, CameraState.Captured);
729 CameraErrorFactory.ThrowIfError(Native.StartFocusing(_handle, continuous),
730 "Failed to cancel the camera focus.");
734 /// Stops camera auto focusing.
735 /// The camera must be in the <see cref="CameraState.Preview"/> or <see cref="CameraState.Captured"/> state.
738 /// http://tizen.org/privilege/camera
740 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
741 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
742 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
743 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
744 public void StopFocusing()
746 ValidateState(CameraState.Preview, CameraState.Captured);
748 CameraErrorFactory.ThrowIfError(Native.CancelFocusing(_handle),
749 "Failed to cancel the camera focus.");
753 /// Starts face detection.
754 /// The camera must be in the <see cref="CameraState.Preview"/> state.
757 /// http://tizen.org/privilege/camera
760 /// This should be called after <see cref="StartPreview"/> is started.
761 /// The Eventhandler set using <see cref="FaceDetected"/> invoked when the face is detected in preview frame.
762 /// Internally it starts continuous focus and focusing on the detected face.
764 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
765 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
766 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
767 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted.</exception>
768 public void StartFaceDetection()
770 ValidateState(CameraState.Preview);
772 _faceDetectedCallback = (IntPtr faces, int count, IntPtr userData) =>
774 var result = new List<FaceDetectionData>();
775 IntPtr current = faces;
777 for (int i = 0; i < count; i++)
779 result.Add(new FaceDetectionData(current));
780 current = IntPtr.Add(current, Marshal.SizeOf<Native.DetectedFaceStruct>());
783 FaceDetected?.Invoke(this, new FaceDetectedEventArgs(result));
785 CameraErrorFactory.ThrowIfError(Native.StartFaceDetection(_handle, _faceDetectedCallback, IntPtr.Zero),
786 "Failed to start face detection");
790 /// Stops face detection.
793 /// http://tizen.org/privilege/camera
795 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
796 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
797 /// <exception cref="ObjectDisposedException">The camera already has been disposed.</exception>
798 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
799 public void StopFaceDetection()
801 if (_faceDetectedCallback == null)
803 throw new InvalidOperationException("The face detection is not started.");
806 CameraErrorFactory.ThrowIfError(Native.StopFaceDetection(_handle),
807 "Failed to stop the face detection.");
809 _faceDetectedCallback = null;
813 #region Callback registrations
814 private void RegisterCallbacks()
816 RegisterErrorCallback();
817 RegisterFocusStateChanged();
818 RegisterHdrCaptureProgress();
819 RegisterInterruptedCallback();
820 RegisterStateChangedCallback();
822 //Define capturing callback
823 _capturingCallback = (IntPtr image, IntPtr postview, IntPtr thumbnail, IntPtr userData) =>
825 Capturing?.Invoke(this, new CameraCapturingEventArgs(new ImageData(image),
826 postview == IntPtr.Zero ? null : new ImageData(postview),
827 thumbnail == IntPtr.Zero ? null : new ImageData(thumbnail)));
830 //Define captureCompleted callback
831 _captureCompletedCallback = _ =>
833 SetState(CameraState.Captured);
834 CaptureCompleted?.Invoke(this, EventArgs.Empty);
838 private void RegisterInterruptedCallback()
840 _interruptedCallback = (CameraPolicy policy, CameraState previous, CameraState current, IntPtr userData) =>
842 Interrupted?.Invoke(this, new CameraInterruptedEventArgs(policy, previous, current));
844 CameraErrorFactory.ThrowIfError(Native.SetInterruptedCallback(_handle, _interruptedCallback, IntPtr.Zero),
845 "Failed to set interrupt callback");
848 private void RegisterErrorCallback()
850 _errorCallback = (CameraErrorCode error, CameraState current, IntPtr userData) =>
852 ErrorOccurred?.Invoke(this, new CameraErrorOccurredEventArgs(error, current));
854 CameraErrorFactory.ThrowIfError(Native.SetErrorCallback(_handle, _errorCallback, IntPtr.Zero),
855 "Setting error callback failed");
858 private void RegisterStateChangedCallback()
860 _stateChangedCallback = (CameraState previous, CameraState current, bool byPolicy, IntPtr _) =>
863 Log.Info(CameraLog.Tag, "Camera state changed " + previous.ToString() + " -> " + current.ToString());
864 StateChanged?.Invoke(this, new CameraStateChangedEventArgs(previous, current, byPolicy));
866 CameraErrorFactory.ThrowIfError(Native.SetStateChangedCallback(_handle, _stateChangedCallback, IntPtr.Zero),
867 "Setting state changed callback failed");
870 private void RegisterFocusStateChanged()
872 _focusStateChangedCallback = (CameraFocusState state, IntPtr userData) =>
874 FocusStateChanged?.Invoke(this, new CameraFocusStateChangedEventArgs(state));
876 CameraErrorFactory.ThrowIfError(Native.SetFocusStateChangedCallback(_handle, _focusStateChangedCallback, IntPtr.Zero),
877 "Setting focus changed callback failed");
880 private void RegisterHdrCaptureProgress()
882 //Hdr Capture can not be supported.
883 if (Feature.IsHdrCaptureSupported)
885 _hdrCaptureProgressCallback = (int percent, IntPtr userData) =>
887 HdrCaptureProgress?.Invoke(this, new HdrCaptureProgressEventArgs(percent));
889 CameraErrorFactory.ThrowIfError(Native.SetHdrCaptureProgressCallback(_handle, _hdrCaptureProgressCallback, IntPtr.Zero),
890 "Setting Hdr capture progress callback failed");
894 private void RegisterPreviewCallback()
896 _previewCallback = (IntPtr frame, IntPtr userData) =>
898 _preview?.Invoke(this, new PreviewEventArgs(new PreviewData(frame)));
900 CameraErrorFactory.ThrowIfError(Native.SetPreviewCallback(_handle, _previewCallback, IntPtr.Zero),
901 "Setting preview callback failed");
904 private void RegisterMediaPacketPreviewCallback()
906 _mediaPacketPreviewCallback = (IntPtr mediaPacket, IntPtr userData) =>
908 MediaPacket packet = MediaPacket.From(mediaPacket);
909 var eventHandler = _mediaPacketPreview;
911 if (eventHandler != null)
913 eventHandler.Invoke(this, new MediaPacketPreviewEventArgs(packet));
920 CameraErrorFactory.ThrowIfError(Native.SetMediaPacketPreviewCallback(_handle, _mediaPacketPreviewCallback, IntPtr.Zero),
921 "Setting media packet preview callback failed");
923 #endregion Callback registrations