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";
32 /// The camera class provides methods to capture photos and support setting up notifications
33 /// for state changes of capturing, previewing, focusing, information about resolution and binary format
34 /// and functions for picture manipulations like sepia negative and many more.
35 /// It also notifies you when a significant picture parameter changes e.g. focus.
38 /// http://tizen.org/privilege/camera
40 public class Camera : IDisposable
42 private IntPtr _handle = IntPtr.Zero;
43 private bool _disposed = false;
44 private CameraState _state = CameraState.None;
45 private static Dictionary<object, int> _callbackIdInfo = new Dictionary<object, int>();
48 /// Initializes a new instance of the <see cref="Camera"/> Class.
50 /// <param name="device">The camera device to access</param>
51 public Camera(CameraDevice device)
53 CameraErrorFactory.ThrowIfError(Interop.Camera.Create((int)device, out _handle),
54 "Failed to create camera instance");
56 Feature = new CameraFeatures(this);
57 Setting = new CameraSettings(this);
58 Display = new CameraDisplay(this);
62 _state = CameraState.Created;
66 /// Destructor of the camera class.
73 internal IntPtr GetHandle()
75 ValidateNotDisposed();
79 #region Dispose support
81 /// Release any unmanaged resources used by this object.
86 GC.SuppressFinalize(this);
89 protected virtual void Dispose(bool disposing)
95 // to be used if there are any other disposable objects
98 if (_handle != IntPtr.Zero)
100 Interop.Camera.Destroy(_handle);
101 _handle = IntPtr.Zero;
108 internal void ValidateNotDisposed()
112 throw new ObjectDisposedException(nameof(Camera));
115 #endregion Dispose support
117 #region Check camera state
118 internal void ValidateState(params CameraState[] required)
120 ValidateNotDisposed();
122 Debug.Assert(required.Length > 0);
124 var curState = _state;
125 if (!required.Contains(curState))
127 throw new InvalidOperationException($"The camera is not in a valid state. " +
128 $"Current State : { curState }, Valid State : { string.Join(", ", required) }.");
132 internal void SetState(CameraState state)
136 #endregion Check camera state
138 #region EventHandlers
140 /// Event that occurs when an camera is interrupted by policy.
142 public event EventHandler<CameraInterruptedEventArgs> Interrupted;
143 private Interop.Camera.InterruptedCallback _interruptedCallback;
146 /// Event that occurs when there is an asynchronous error.
148 public event EventHandler<CameraErrorOccurredEventArgs> ErrorOccurred;
149 private Interop.Camera.ErrorCallback _errorCallback;
152 /// Event that occurs when the auto focus state is changed.
154 public event EventHandler<CameraFocusStateChangedEventArgs> FocusStateChanged;
155 private Interop.Camera.FocusStateChangedCallback _focusStateChangedCallback;
158 /// Event that occurs when a face is detected in preview frame.
160 public event EventHandler<FaceDetectedEventArgs> FaceDetected;
161 private Interop.Camera.FaceDetectedCallback _faceDetectedCallback;
164 /// Event that occurs during capture of image.
166 public event EventHandler<CameraCapturingEventArgs> Capturing;
167 private Interop.Camera.CapturingCallback _capturingCallback;
170 /// Event that occurs after the capture of the image.
172 public event EventHandler<EventArgs> CaptureCompleted;
173 private Interop.Camera.CaptureCompletedCallback _captureCompletedCallback;
176 /// Event that occurs when there is change in HDR capture progress.
177 /// Check whether HdrCapture feature is supported or not before add this EventHandler.
179 public event EventHandler<HdrCaptureProgressEventArgs> HdrCaptureProgress;
180 private Interop.Camera.HdrCaptureProgressCallback _hdrCaptureProgressCallback;
183 /// Event that occurs when camera state is changed.
185 public event EventHandler<CameraStateChangedEventArgs> StateChanged;
186 private Interop.Camera.StateChangedCallback _stateChangedCallback;
188 #region DeviceStateChanged callback
189 internal static Interop.Camera.DeviceStateChangedCallback _deviceStateChangedCallback;
190 public static event EventHandler<CameraDeviceStateChangedEventArgs> _deviceStateChanged;
191 public static object _deviceStateChangedEventLock = new object();
194 /// Set the DeviceStateChanged Callback.
195 /// User doesn't need to create camera instance.
196 /// This static EventHandler calls platform function every time because each callback function have to remain its own callbackId.
198 /// <param name="callback">Callback of type <see cref="Interop.Camera.DeviceStateChangedCallback"/>.</param>
199 /// <param name="callbackId">The Id of registered callback.</param>
200 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
201 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
202 /// <exception cref="ArgumentException">In case of invalid parameters</exception>
203 public static event EventHandler<CameraDeviceStateChangedEventArgs> DeviceStateChanged
207 lock (_deviceStateChangedEventLock)
211 _deviceStateChangedCallback = (CameraDevice device, CameraDeviceState state, IntPtr userData) =>
213 _deviceStateChanged?.Invoke(null, new CameraDeviceStateChangedEventArgs(device, state));
215 CameraErrorFactory.ThrowIfError(Interop.Camera.SetDeviceStateChangedCallback(_deviceStateChangedCallback, IntPtr.Zero, out callbackId),
216 "Failed to set interrupt callback");
218 // Keep current callbackId and EventHandler pair to remove EventHandler later.
219 _callbackIdInfo.Add(value, callbackId);
220 Log.Info(CameraLog.Tag, "add callbackId " + callbackId.ToString());
222 _deviceStateChanged += value;
228 lock (_deviceStateChangedEventLock)
230 _deviceStateChanged -= value;
233 _callbackIdInfo.TryGetValue(value, out callbackId);
234 Log.Info(CameraLog.Tag, "remove callbackId " + callbackId.ToString());
236 CameraErrorFactory.ThrowIfError(Interop.Camera.UnsetDeviceStateChangedCallback(callbackId),
237 "Unsetting media packet preview callback failed");
239 _callbackIdInfo.Remove(value);
241 if (_deviceStateChanged == null)
243 _deviceStateChangedCallback = null;
248 #endregion DeviceStateChanged callback
250 #region Preview EventHandler
251 private Interop.Camera.PreviewCallback _previewCallback;
252 private event EventHandler<PreviewEventArgs> _preview;
253 private object _previewEventLock = new object();
255 /// Event that occurs once per frame when previewing.
256 /// Preview callback is registered when user add callback explicitly to avoid useless P/Invoke.
258 public event EventHandler<PreviewEventArgs> Preview
262 lock (_previewEventLock)
264 if (_preview == null)
266 RegisterPreviewCallback();
275 lock (_previewEventLock)
279 if (_preview == null)
281 CameraErrorFactory.ThrowIfError(Interop.Camera.UnsetPreviewCallback(_handle),
282 "Unsetting preview callback failed");
283 _previewCallback = null;
288 #endregion Preview EventHandler
290 #region MediaPacketPreview EventHandler
291 private Interop.Camera.MediaPacketPreviewCallback _mediaPacketPreviewCallback;
292 private EventHandler<MediaPacketPreviewEventArgs> _mediaPacketPreview;
293 private object _mediaPacketPreviewEventLock = new object();
296 /// Event that occurs once per frame when previewing.
297 /// Preview callback is registered when user add callback explicitly to avoid useless P/Invoke.
299 public event EventHandler<MediaPacketPreviewEventArgs> MediaPacketPreview
303 lock (_mediaPacketPreviewEventLock)
305 if (_mediaPacketPreview == null)
307 RegisterMediaPacketPreviewCallback();
310 _mediaPacketPreview += value;
316 lock (_mediaPacketPreviewEventLock)
318 _mediaPacketPreview -= value;
320 if (_mediaPacketPreview == null)
322 CameraErrorFactory.ThrowIfError(Interop.Camera.UnsetMediaPacketPreviewCallback(_handle),
323 "Unsetting media packet preview callback failed");
324 _mediaPacketPreviewCallback = null;
329 #endregion MediaPacketPreview EventHandler
331 #endregion EventHandlers
335 /// Get/Set the various camera settings.
337 public CameraSettings Setting { get; }
340 /// Gets the various camera features.
342 public CameraFeatures Feature { get; }
345 /// Get/set various camera display properties.
347 public CameraDisplay Display { get; }
350 /// Gets the state of the camera.
352 public CameraState State
356 CameraState val = CameraState.None;
357 CameraErrorFactory.ThrowIfError(Interop.Camera.GetState(_handle, out val),
358 "Failed to get camera state");
365 /// The hint for display reuse.
366 /// If the hint is set to true, the display will be reused when the camera device is changed with
367 /// ChangeDevice method.
369 /// <exception cref="ArgumentException">In case of invalid parameters</exception>
370 public bool DisplayReuseHint
376 CameraErrorFactory.ThrowIfError(Interop.Camera.GetDisplayReuseHint(_handle, out val),
377 "Failed to get camera display reuse hint");
384 CameraErrorFactory.ThrowIfError(Interop.Camera.SetDisplayReuseHint(_handle, value),
385 "Failed to set display reuse hint.");
390 /// Gets the facing direction of camera module.
392 public CameraFacingDirection Direction
396 CameraFacingDirection val = 0;
398 CameraErrorFactory.ThrowIfError(Interop.Camera.GetFacingDirection(_handle, out val),
399 "Failed to get camera direction");
406 /// Gets the camera device count.
409 /// This returns 2, if the device supports primary and secondary cameras.
410 /// Otherwise 1, if the device only supports primary camera.
412 public int CameraCount
418 CameraErrorFactory.ThrowIfError(Interop.Camera.GetDeviceCount(_handle, out val),
419 "Failed to get camera device count");
424 #endregion Properties
428 /// Changes the camera device.
430 /// <param name="device">The hardware camera to access.</param>
432 /// http://tizen.org/privilege/camera
435 /// If display reuse is set using <see cref="DisplayReuseHint"/>
436 /// before stopping the preview, the display will be reused and last frame on the display
437 /// can be kept even though camera device is changed.
438 /// The camera must be in the <see cref="CameraState.Created"/> or <see cref="CameraState.Preview"/> state.
440 /// <exception cref="ArgumentException">In case of invalid parameters</exception>
441 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
442 /// <exception cref="NotSupportedException">In case of ChangeDevice feature is not supported</exception>
443 public void ChangeDevice(CameraDevice device)
445 ValidateState(CameraState.Created, CameraState.Preview);
447 CameraErrorFactory.ThrowIfError(Interop.Camera.ChangeDevice(_handle, (int)device),
448 "Failed to change the camera device");
452 /// Gets the device state.
455 /// http://tizen.org/privilege/camera
457 /// <param name="device">The device to get state.</param>
458 /// <returns>Returns the state of camera device</returns>
459 /// <exception cref="ArgumentException">In case of invalid parameters</exception>
460 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
461 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
462 public CameraDeviceState GetDeviceState(CameraDevice device)
466 CameraErrorFactory.ThrowIfError(Interop.Camera.GetDeviceState(device, out val),
467 "Failed to get the camera device state.");
469 return (CameraDeviceState)val;
472 public static CameraFlashState GetFlashState(CameraDevice device)
474 CameraFlashState val = CameraFlashState.NotUsed;
476 CameraErrorFactory.ThrowIfError(Interop.Camera.GetFlashState(device, out val),
477 "Failed to get camera flash state");
483 /// Starts capturing and drawing preview frames on the screen.
484 /// The display handle must be set using <see cref="Tizen.Multimedia.Camera.SetDisplay"/>
485 /// before using this method.
486 /// If needed set fps <see cref="Tizen.Multimedia.CameraSetting.PreviewFps"/>, preview resolution
487 /// <see cref="Tizen.Multimedia.Camera.PreviewResolution"/>, or preview format <see cref="Tizen.Multimedia.Camera.PreviewFormat"/>
488 /// before using this method.
491 /// http://tizen.org/privilege/camera
493 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
494 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
495 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
496 public void StartPreview()
498 ValidateState(CameraState.Created, CameraState.Captured);
500 CameraErrorFactory.ThrowIfError(Interop.Camera.StartPreview(_handle),
501 "Failed to start the camera preview.");
503 // Update by StateChangedCallback can be delayed for dozens of milliseconds.
504 SetState(CameraState.Preview);
508 /// Stops capturing and drawing preview frames on the screen.
511 /// http://tizen.org/privilege/camera
513 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
514 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
515 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
516 public void StopPreview()
518 CameraErrorFactory.ThrowIfError(Interop.Camera.StopPreview(_handle),
519 "Failed to stop the camera preview.");
521 SetState(CameraState.Created);
525 /// Starts capturing of still images.
526 /// EventHandler must be set for capturing using <see cref="Tizen.Multimedia.Camera.Capturing"/>
527 /// and for completed using <see cref="Tizen.Multimedia.Camera.CaptureCompleted"/> before
528 /// calling this method.
531 /// http://tizen.org/privilege/camera
534 /// This function causes the transition of the camera state from Capturing to Captured
535 /// automatically and the corresponding EventHandlers will be invoked.
536 /// The camera's preview should be restarted by calling <see cref="Tizen.Multimedia.Camera.StartPreview"/>
539 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
540 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
541 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
542 public void StartCapture()
544 ValidateState(CameraState.Preview);
546 CameraErrorFactory.ThrowIfError(Interop.Camera.StartCapture(_handle, _capturingCallback, _captureCompletedCallback, IntPtr.Zero),
547 "Failed to start the camera capture.");
549 SetState(CameraState.Capturing);
553 /// Starts continuously capturing still images.
554 /// EventHandler must be set for capturing using <see cref="Tizen.Multimedia.Camera.Capturing"/>
555 /// and for completed using <see cref="Tizen.Multimedia.Camera.CaptureCompleted"/> before
556 /// calling this method.
559 /// http://tizen.org/privilege/camera
561 /// <param name="count">The number of still images.</param>
562 /// <param name="interval">The interval of the capture(milliseconds).</param>
564 /// If this is not supported zero shutter lag occurs. The capture resolution could be
565 /// changed to the preview resolution. This function causes the transition of the camera state
566 /// from Capturing to Captured automatically and the corresponding Eventhandlers will be invoked.
567 /// Each captured image will be delivered through Eventhandler set using <see cref="Tizen.Multimedia.Camera.Capturing"/> event.
568 /// The camera's preview should be restarted by calling <see cref="Tizen.Multimedia.Camera.StartPreview"/> method.
570 /// <exception cref="ArgumentException">In case of invalid parameters</exception>
571 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
572 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
573 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
574 public void StartCapture(int count, int interval, CancellationToken cancellationToken)
576 ValidateState(CameraState.Preview);
580 throw new ArgumentOutOfRangeException(nameof(count), count, $"{nameof(count)} should be greater than one.");
585 throw new ArgumentOutOfRangeException(nameof(interval), interval, $"{nameof(interval)} should be greater than or equal to zero.");
588 //Handle CancellationToken
589 if (cancellationToken != CancellationToken.None)
591 cancellationToken.Register(() =>
593 CameraErrorFactory.ThrowIfError(Interop.Camera.StopContinuousCapture(_handle),
594 "Failed to cancel the continuous capture");
595 SetState(CameraState.Captured);
599 CameraErrorFactory.ThrowIfError(Interop.Camera.StartContinuousCapture(_handle, count, interval,
600 _capturingCallback, _captureCompletedCallback, IntPtr.Zero), "Failed to start the continuous capture.");
602 SetState(CameraState.Capturing);
606 /// Starts camera auto-focusing, asynchronously.
608 /// <param name="continuous">Continuous.</param>
610 /// http://tizen.org/privilege/camera
613 /// If continuous status is true, the camera continuously tries to focus.
615 /// <exception cref="ArgumentException">In case of invalid parameters</exception>
616 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
617 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
618 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
619 public void StartFocusing(bool continuous)
621 ValidateState(CameraState.Preview, CameraState.Captured);
623 CameraErrorFactory.ThrowIfError(Interop.Camera.StartFocusing(_handle, continuous),
624 "Failed to cancel the camera focus.");
628 /// Stops camera auto focusing.
631 /// http://tizen.org/privilege/camera
633 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
634 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
635 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
636 public void StopFocusing()
638 ValidateState(CameraState.Preview, CameraState.Captured);
640 CameraErrorFactory.ThrowIfError(Interop.Camera.CancelFocusing(_handle),
641 "Failed to cancel the camera focus.");
645 /// Starts face detection.
648 /// http://tizen.org/privilege/camera
651 /// This should be called after <see cref="Tizen.Multimedia.Camera.StartPreview"/> is started.
652 /// The Eventhandler set using <see cref="Tizen.Multimedia.Camera.FaceDetected"/> invoked when the face is detected in preview frame.
653 /// Internally it starts continuous focus and focusing on the detected face.
655 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
656 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
657 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
658 public void StartFaceDetection()
660 ValidateState(CameraState.Preview);
662 _faceDetectedCallback = (IntPtr faces, int count, IntPtr userData) =>
664 var result = new List<FaceDetectionData>();
665 IntPtr current = faces;
667 for (int i = 0; i < count; i++)
669 result.Add(new FaceDetectionData(current));
670 current = IntPtr.Add(current, Marshal.SizeOf<Interop.Camera.DetectedFaceStruct>());
673 FaceDetected?.Invoke(this, new FaceDetectedEventArgs(result));
675 CameraErrorFactory.ThrowIfError(Interop.Camera.StartFaceDetection(_handle, _faceDetectedCallback, IntPtr.Zero),
676 "Failed to start face detection");
680 /// Stops face detection.
683 /// http://tizen.org/privilege/camera
685 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
686 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
687 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
688 public void StopFaceDetection()
690 if (_faceDetectedCallback == null)
692 throw new InvalidOperationException("The face detection is not started.");
695 CameraErrorFactory.ThrowIfError(Interop.Camera.StopFaceDetection(_handle),
696 "Failed to stop the face detection.");
698 _faceDetectedCallback = null;
702 #region Callback registrations
703 private void RegisterCallbacks()
705 RegisterErrorCallback();
706 RegisterFocusStateChanged();
707 RegisterHdrCaptureProgress();
708 RegisterInterruptedCallback();
709 RegisterStateChangedCallback();
711 //Define capturing callback
712 _capturingCallback = (IntPtr image, IntPtr postview, IntPtr thumbnail, IntPtr userData) =>
714 Capturing?.Invoke(this, new CameraCapturingEventArgs(new ImageData(image),
715 postview == IntPtr.Zero ? null : new ImageData(postview),
716 thumbnail == IntPtr.Zero ? null : new ImageData(thumbnail)));
719 //Define captureCompleted callback
720 _captureCompletedCallback = _ =>
722 SetState(CameraState.Captured);
723 CaptureCompleted?.Invoke(this, EventArgs.Empty);
727 private void RegisterInterruptedCallback()
729 _interruptedCallback = (CameraPolicy policy, CameraState previous, CameraState current, IntPtr userData) =>
731 Interrupted?.Invoke(this, new CameraInterruptedEventArgs(policy, previous, current));
733 CameraErrorFactory.ThrowIfError(Interop.Camera.SetInterruptedCallback(_handle, _interruptedCallback, IntPtr.Zero),
734 "Failed to set interrupt callback");
737 private void RegisterErrorCallback()
739 _errorCallback = (CameraErrorCode error, CameraState current, IntPtr userData) =>
741 ErrorOccurred?.Invoke(this, new CameraErrorOccurredEventArgs(error, current));
743 CameraErrorFactory.ThrowIfError(Interop.Camera.SetErrorCallback(_handle, _errorCallback, IntPtr.Zero),
744 "Setting error callback failed");
747 private void RegisterStateChangedCallback()
749 _stateChangedCallback = (CameraState previous, CameraState current, bool byPolicy, IntPtr _) =>
752 Log.Info(CameraLog.Tag, "Camera state changed " + previous.ToString() + " -> " + current.ToString());
753 StateChanged?.Invoke(this, new CameraStateChangedEventArgs(previous, current, byPolicy));
755 CameraErrorFactory.ThrowIfError(Interop.Camera.SetStateChangedCallback(_handle, _stateChangedCallback, IntPtr.Zero),
756 "Setting state changed callback failed");
759 private void RegisterFocusStateChanged()
761 _focusStateChangedCallback = (CameraFocusState state, IntPtr userData) =>
763 FocusStateChanged?.Invoke(this, new CameraFocusStateChangedEventArgs(state));
765 CameraErrorFactory.ThrowIfError(Interop.Camera.SetFocusStateChangedCallback(_handle, _focusStateChangedCallback, IntPtr.Zero),
766 "Setting focus changed callback failed");
769 private void RegisterHdrCaptureProgress()
771 //Hdr Capture can not be supported.
772 if (Feature.IsHdrCaptureSupported)
774 _hdrCaptureProgressCallback = (int percent, IntPtr userData) =>
776 HdrCaptureProgress?.Invoke(this, new HdrCaptureProgressEventArgs(percent));
778 CameraErrorFactory.ThrowIfError(Interop.Camera.SetHdrCaptureProgressCallback(_handle, _hdrCaptureProgressCallback, IntPtr.Zero),
779 "Setting Hdr capture progress callback failed");
783 private void RegisterPreviewCallback()
785 _previewCallback = (IntPtr frame, IntPtr userData) =>
787 _preview?.Invoke(this, new PreviewEventArgs(new PreviewData(frame)));
789 CameraErrorFactory.ThrowIfError(Interop.Camera.SetPreviewCallback(_handle, _previewCallback, IntPtr.Zero),
790 "Setting preview callback failed");
793 private void RegisterMediaPacketPreviewCallback()
795 _mediaPacketPreviewCallback = (IntPtr mediaPacket, IntPtr userData) =>
797 MediaPacket packet = MediaPacket.From(mediaPacket);
798 var eventHandler = _mediaPacketPreview;
800 if (eventHandler != null)
802 eventHandler.Invoke(this, new MediaPacketPreviewEventArgs(packet));
809 CameraErrorFactory.ThrowIfError(Interop.Camera.SetMediaPacketPreviewCallback(_handle, _mediaPacketPreviewCallback, IntPtr.Zero),
810 "Setting media packet preview callback failed");
812 #endregion Callback registrations