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.Runtime.InteropServices;
20 using Tizen.Internals.Errors;
21 using Tizen.Multimedia;
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 Interop.Camera.CapturingCallback _capturingCallback;
45 private Interop.Camera.CaptureCompletedCallback _captureCompletedCallback;
46 private Interop.Camera.FaceDetectedCallback _faceDetectedCallback;
47 private EventHandler<CameraErrorOccurredEventArgs> _cameraErrorOccurred;
48 private EventHandler<CameraStateChangedEventArgs> _cameraStateChanged;
49 private EventHandler<PreviewEventArgs> _preview;
50 private EventHandler<CameraFocusChangedEventArgs> _cameraFocusChanged;
51 private EventHandler<CameraInterruptedEventArgs> _cameraInterrupted;
52 private EventHandler<HdrCaptureProgressEventArgs> _hdrProgress;
53 private EventHandler<MediaPacketPreviewEventArgs> _mediaPacketPreview;
54 private readonly CameraFeature _cameraFeature;
55 private readonly CameraSetting _cameraSetting;
56 private readonly CameraDisplay _cameraDisplay;
57 private readonly List<FaceDetectedData> _faces = new List<FaceDetectedData>();
58 private Interop.Camera.PreviewCallback _previewCallback;
59 Interop.Camera.MediaPacketPreviewCallback _mediaPacketCallback;
60 private Interop.Camera.FocusChangedCallback _focusCallback;
61 private Interop.Camera.HdrCaptureProgressCallback _hdrProgressCallback;
62 private Interop.Camera.StateChangedCallback _stateChangedCallback;
63 private Interop.Camera.InterruptedCallback _interruptedCallback;
64 private Interop.Camera.ErrorCallback _errorCallback;
67 /// Initializes a new instance of the <see cref="Tizen.Multimedia.Camera"/> Class.
69 /// <param name="device">Device.</param>
70 public Camera(CameraDevice device)
72 int ret = Interop.Camera.Create((int)device, out _handle);
73 if (ret != (int)CameraError.None)
75 CameraErrorFactory.ThrowException(ret, "Failed to create camera instance");
78 _cameraFeature = new CameraFeature(_handle);
79 _cameraSetting = new CameraSetting(_handle);
80 _cameraDisplay = new CameraDisplay(_handle);
84 /// Destructor of the camera class.
91 internal IntPtr GetHandle()
93 ValidateNotDisposed();
98 /// Event that occurs when there is change in HDR capture progress.
100 public event EventHandler<HdrCaptureProgressEventArgs> HdrCaptureProgress
104 if (_hdrProgress == null)
106 _hdrProgressCallback = (int percent, IntPtr userData) =>
108 HdrCaptureProgressEventArgs eventArgs = new HdrCaptureProgressEventArgs(percent);
109 _hdrProgress?.Invoke(this, eventArgs);
111 int ret = Interop.Camera.SetHdrCaptureProgressCallback(_handle, _hdrProgressCallback, IntPtr.Zero);
112 if (ret != (int)CameraError.None)
114 CameraErrorFactory.ThrowException(ret, "Setting hdr progress callback failed");
118 _hdrProgress += value;
123 _hdrProgress -= value;
124 if (_hdrProgress == null)
126 int ret = Interop.Camera.UnsetHdrCaptureProgressCallback(_handle);
127 if (ret != (int)CameraError.None)
129 CameraErrorFactory.ThrowException(ret, "Unsetting hdr progress callback failed");
136 /// Event that occurs during capture of image.
138 public event EventHandler<CapturingEventArgs> Capturing;
141 /// Event that occurs after the capture of the image.
143 public event EventHandler<EventArgs> CaptureCompleted;
146 /// Event that occurs when camera state is changed.
148 public event EventHandler<CameraStateChangedEventArgs> CameraStateChanged
152 if (_cameraStateChanged == null)
154 _stateChangedCallback = (CameraState previous, CameraState current, bool byPolicy, IntPtr userData) =>
156 CameraStateChangedEventArgs eventArgs = new CameraStateChangedEventArgs(previous, current, byPolicy);
157 _cameraStateChanged?.Invoke(this, eventArgs);
159 int ret = Interop.Camera.SetStateChangedCallback(_handle, _stateChangedCallback, IntPtr.Zero);
160 if (ret != (int)CameraError.None)
162 CameraErrorFactory.ThrowException(ret, "Setting state changed callback failed");
166 _cameraStateChanged += value;
171 _cameraStateChanged -= value;
172 if (_cameraStateChanged == null)
174 int ret = Interop.Camera.UnsetStateChangedCallback(_handle);
175 if (ret != (int)CameraError.None)
177 CameraErrorFactory.ThrowException(ret, "Unsetting state changed callback failed");
184 /// Event that occurs when the auto-focus state of camera changes.
186 public event EventHandler<CameraFocusChangedEventArgs> CameraFocusChanged
190 if (_cameraFocusChanged == null)
192 _focusCallback = (CameraFocusState state, IntPtr userData) =>
194 CameraFocusChangedEventArgs eventArgs = new CameraFocusChangedEventArgs(state);
195 _cameraFocusChanged?.Invoke(this, eventArgs);
197 int ret = Interop.Camera.SetFocusChangedCallback(_handle, _focusCallback, IntPtr.Zero);
198 if (ret != (int)CameraError.None)
200 CameraErrorFactory.ThrowException(ret, "Setting focus changed callback failed");
204 _cameraFocusChanged += value;
209 _cameraFocusChanged -= value;
210 if (_cameraFocusChanged == null)
212 int ret = Interop.Camera.UnsetFocusChangedCallback(_handle);
213 if (ret != (int)CameraError.None)
215 CameraErrorFactory.ThrowException(ret, "Unsetting focus changed callback failed");
222 /// Event that occurs when an camera is interrupted by policy.
224 public event EventHandler<CameraInterruptedEventArgs> CameraInterrupted
228 if (_cameraInterrupted == null)
230 _interruptedCallback = (CameraPolicy policy, CameraState previous, CameraState current, IntPtr userData) =>
232 CameraInterruptedEventArgs eventArgs = new CameraInterruptedEventArgs(policy, previous, current);
233 _cameraInterrupted?.Invoke(this, eventArgs);
235 int ret = Interop.Camera.SetInterruptedCallback(_handle, _interruptedCallback, IntPtr.Zero);
236 if (ret != (int)CameraError.None)
238 CameraErrorFactory.ThrowException(ret, "Setting interrupt callback failed");
242 _cameraInterrupted += value;
247 _cameraInterrupted -= value;
248 if (_cameraInterrupted == null)
250 int ret = Interop.Camera.UnsetInterruptedCallback(_handle);
251 if (ret != (int)CameraError.None)
253 CameraErrorFactory.ThrowException(ret, "Unsetting interrupt callback failed");
260 /// Event that occurs when there is an asynchronous error.
262 public event EventHandler<CameraErrorOccurredEventArgs> CameraErrorOccurred
266 if (_cameraErrorOccurred == null)
268 _errorCallback = (CameraErrorCode error, CameraState current, IntPtr userData) =>
270 CameraErrorOccurredEventArgs eventArgs = new CameraErrorOccurredEventArgs(error, current);
271 _cameraErrorOccurred?.Invoke(this, eventArgs);
273 int ret = Interop.Camera.SetErrorCallback(_handle, _errorCallback, IntPtr.Zero);
274 if (ret != (int)CameraError.None)
276 CameraErrorFactory.ThrowException(ret, "Setting error callback failed");
280 _cameraErrorOccurred += value;
285 _cameraErrorOccurred -= value;
286 if (_cameraErrorOccurred == null)
288 int ret = Interop.Camera.UnsetErrorCallback(_handle);
289 if (ret != (int)CameraError.None)
291 CameraErrorFactory.ThrowException(ret, "Unsetting error callback failed");
298 /// Event that occurs when a face is detected in preview frame.
300 public event EventHandler<FaceDetectedEventArgs> FaceDetected;
303 /// Event that occurs once per frame when previewing.
305 public event EventHandler<PreviewEventArgs> Preview
309 if (_preview == null)
311 CreatePreviewCallback();
320 if (_preview == null)
322 int ret = Interop.Camera.UnsetPreviewCallback(_handle);
323 if (ret != (int)CameraError.None)
325 CameraErrorFactory.ThrowException(ret, "Unsetting preview callback failed");
332 /// Event that occurs once per frame when previewing.
334 public event EventHandler<MediaPacketPreviewEventArgs> MediaPacketPreview
338 if (_mediaPacketPreview == null)
340 CreateMediaPacketPreviewCallback();
343 _mediaPacketPreview += value;
348 _mediaPacketPreview -= value;
349 if (_mediaPacketPreview == null)
351 int ret = Interop.Camera.UnsetMediaPacketPreviewCallback(_handle);
352 if (ret != (int)CameraError.None)
354 CameraErrorFactory.ThrowException(ret, "Unsetting media packet preview callback failed");
361 /// Get/Set the various camera settings.
363 public CameraSetting Setting
367 return _cameraSetting;
372 /// Gets the various camera features.
374 public CameraFeature Feature
378 return _cameraFeature;
383 /// Get/set various camera display properties.
385 public CameraDisplay Display
389 return _cameraDisplay;
394 /// Gets the state of the camera.
396 public CameraState State
402 int ret = Interop.Camera.GetState(_handle, out val);
403 if ((CameraError)ret != CameraError.None)
405 Log.Error(CameraLog.Tag, "Failed to get camera state, " + (CameraError)ret);
408 return (CameraState)val;
413 /// The hint for display reuse.
414 /// If the hint is set to true, the display will be reused when the camera device is changed with
415 /// ChangeDevice method.
417 /// <exception cref="ArgumentException">In case of invalid parameters</exception>
418 public bool DisplayReuseHint
424 int ret = Interop.Camera.GetDisplayReuseHint(_handle, out val);
425 if ((CameraError)ret != CameraError.None)
427 Log.Error(CameraLog.Tag, "Failed to get camera display reuse hint, " + (CameraError)ret);
435 int ret = Interop.Camera.SetDisplayReuseHint(_handle, value);
436 if ((CameraError)ret != CameraError.None)
438 Log.Error(CameraLog.Tag, "Failed to set display reuse hint, " + (CameraError)ret);
439 CameraErrorFactory.ThrowException(ret, "Failed to set display reuse hint.");
445 /// Resolution of the preview.
448 /// http://tizen.org/privilege/camera
450 /// <exception cref="ArgumentException">In case of invalid parameters</exception>
451 public CameraResolution PreviewResolution
457 int ret = Interop.Camera.GetPreviewResolution(_handle, out width, out height);
458 if ((CameraError)ret != CameraError.None)
460 Log.Error(CameraLog.Tag, "Failed to get camera preview resolution, " + (CameraError)ret);
463 CameraResolution res = new CameraResolution(width, height);
469 CameraResolution res = value;
470 int ret = Interop.Camera.SetPreviewResolution(_handle, res.Width, res.Height);
471 if ((CameraError)ret != CameraError.None)
473 Log.Error(CameraLog.Tag, "Failed to set preview resolution, " + (CameraError)ret);
474 CameraErrorFactory.ThrowException(ret, "Failed to set preview resolution.");
480 /// Gets the recommended preview resolution.
483 /// Depending on the capture resolution aspect ratio and display resolution,
484 /// the recommended preview resolution is determined.
486 public CameraResolution RecommendedPreviewResolution
492 int ret = Interop.Camera.GetRecommendedPreviewResolution(_handle, out width, out height);
493 if ((CameraError)ret != CameraError.None)
495 Log.Error(CameraLog.Tag, "Failed to get recommended preview resolution, " + (CameraError)ret);
498 CameraResolution res = new CameraResolution(width, height);
504 /// Resolution of the captured image.
507 /// http://tizen.org/privilege/camera
509 /// <exception cref="ArgumentException">In case of invalid parameters</exception>
510 public CameraResolution CaptureResolution
516 int ret = Interop.Camera.GetCaptureResolution(_handle, out width, out height);
517 if ((CameraError)ret != CameraError.None)
519 Log.Error(CameraLog.Tag, "Failed to get camera capture resolution, " + (CameraError)ret);
522 CameraResolution res = new CameraResolution(width, height);
528 CameraResolution res = value;
529 int ret = Interop.Camera.SetCaptureResolution(_handle, res.Width, res.Height);
530 if ((CameraError)ret != CameraError.None)
532 Log.Error(CameraLog.Tag, "Failed to set capture resolution, " + (CameraError)ret);
533 CameraErrorFactory.ThrowException(ret, "Failed to set capture resolution.");
539 /// Format of an image to be captured.
541 /// <exception cref="ArgumentException">In case of invalid parameters</exception>
542 public CameraPixelFormat CaptureFormat
547 int ret = Interop.Camera.GetCaptureFormat(_handle, out val);
548 if ((CameraError)ret != CameraError.None)
550 Log.Error(CameraLog.Tag, "Failed to get camera capture format, " + (CameraError)ret);
553 return (CameraPixelFormat)val;
558 int ret = Interop.Camera.SetCaptureFormat(_handle, (int)value);
559 if ((CameraError)ret != CameraError.None)
561 Log.Error(CameraLog.Tag, "Failed to set capture format, " + (CameraError)ret);
562 CameraErrorFactory.ThrowException(ret, "Failed to set capture format.");
568 /// The preview data format.
570 /// <exception cref="ArgumentException">In case of invalid parameters</exception>
571 public CameraPixelFormat PreviewFormat
576 int ret = Interop.Camera.GetPreviewFormat(_handle, out val);
577 if ((CameraError)ret != CameraError.None)
579 Log.Error(CameraLog.Tag, "Failed to get preview format, " + (CameraError)ret);
582 return (CameraPixelFormat)val;
587 int ret = Interop.Camera.SetPreviewFormat(_handle, (int)value);
588 if ((CameraError)ret != CameraError.None)
590 Log.Error(CameraLog.Tag, "Failed to set preview format, " + (CameraError)ret);
591 CameraErrorFactory.ThrowException(ret, "Failed to set preview format.");
597 /// Gets the facing direction of camera module.
599 public CameraFacingDirection Direction
604 int ret = Interop.Camera.GetFacingDirection(_handle, out val);
605 if ((CameraError)ret != CameraError.None)
607 Log.Error(CameraLog.Tag, "Failed to get camera direction, " + (CameraError)ret);
610 return (CameraFacingDirection)val;
615 /// Gets the camera's flash state.
617 public CameraFlashState FlashState
622 int ret = Interop.Camera.GetFlashState(_handle, out val);
623 if ((CameraError)ret != CameraError.None)
625 Log.Error(CameraLog.Tag, "Failed to get camera flash state, " + (CameraError)ret);
628 return (CameraFlashState)val;
633 /// Gets the camera device count.
636 /// If the device supports primary and secondary camera, this returns 2.
637 /// If 1 is returned, the device only supports primary camera.
639 public int CameraCount
644 int ret = Interop.Camera.GetDeviceCount(_handle, out val);
645 if ((CameraError)ret != CameraError.None)
647 Log.Error(CameraLog.Tag, "Failed to get camera device count, " + (CameraError)ret);
655 /// Changes the camera device.
657 /// <param name="device">The hardware camera to access.</param>
659 /// http://tizen.org/privilege/camera
662 /// This method can be used to change camera device without using destory and create method.
663 /// If display reuse is set using <see cref="Tizen.Multimedia.Camera.DisplayReuseHint"/>
664 /// before stopping the preview, display handle will be reused and last frame on display
665 /// can be kept even though cameradevice is changed.
667 /// <exception cref="ArgumentException">In case of invalid parameters</exception>
668 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
669 /// <exception cref="NotSupportedException">In case of ChangeDevice feature is not supported</exception>
670 public void ChangeDevice(CameraDevice device)
672 int ret = Interop.Camera.ChangeDevice(_handle, (int)device);
673 if (ret != (int)CameraError.None)
675 CameraErrorFactory.ThrowException(ret, "Failed to change the camera device");
680 /// Gets the device state.
683 /// http://tizen.org/privilege/camera
685 /// <param name="device">The device to get state.</param>
686 /// <returns>Returns the state of camera device</returns>
687 /// <exception cref="ArgumentException">In case of invalid parameters</exception>
688 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
689 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
690 public CameraDeviceState GetDeviceState(CameraDevice device)
693 int ret = Interop.Camera.GetDeviceState(device, out val);
694 if (ret != (int)CameraError.None)
696 CameraErrorFactory.ThrowException(ret, "Failed to get the camera device state.");
699 return (CameraDeviceState)val;
703 /// Starts capturing and drawing preview frames on the screen.
704 /// The display handle must be set using <see cref="Tizen.Multimedia.Camera.SetDisplay"/>
705 /// before using this method.
706 /// If needed set fps <see cref="Tizen.Multimedia.CameraSetting.PreviewFps"/>, preview resolution
707 /// <see cref="Tizen.Multimedia.Camera.PreviewResolution"/>, or preview format <see cref="Tizen.Multimedia.Camera.PreviewFormat"/>
708 /// before using this method.
711 /// http://tizen.org/privilege/camera
713 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
714 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
715 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
716 public void StartPreview()
718 int ret = Interop.Camera.StartPreview(_handle);
719 if (ret != (int)CameraError.None)
721 CameraErrorFactory.ThrowException(ret, "Failed to start the camera preview.");
726 /// Stops capturing and drawing preview frames on the screen.
729 /// http://tizen.org/privilege/camera
731 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
732 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
733 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
734 public void StopPreview()
736 int ret = Interop.Camera.StopPreview(_handle);
737 if (ret != (int)CameraError.None)
739 CameraErrorFactory.ThrowException(ret, "Failed to stop the camera preview.");
744 /// Starts capturing of still images.
745 /// EventHandler must be set for capturing using <see cref="Tizen.Multimedia.Camera.Capturing"/>
746 /// and for completed using <see cref="Tizen.Multimedia.Camera.CaptureCompleted"/> before
747 /// calling this method.
750 /// http://tizen.org/privilege/camera
753 /// This function causes the transition of the camera state from Capturing to Captured
754 /// automatically and the corresponding EventHandlers will be invoked.
755 /// The camera's preview should be restarted by calling <see cref="Tizen.Multimedia.Camera.StartPreview"/>
758 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
759 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
760 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
761 public void StartCapture()
763 Log.Info(CameraLog.Tag, "StartCapture API starting");
765 _capturingCallback = (IntPtr image, IntPtr postview, IntPtr thumbnail, IntPtr userData) =>
767 Interop.Camera.ImageDataStruct _img = new Interop.Camera.ImageDataStruct();
768 Interop.Camera.ImageDataStruct _post = new Interop.Camera.ImageDataStruct();
769 Interop.Camera.ImageDataStruct _thumb = new Interop.Camera.ImageDataStruct();
770 ImageData img = new ImageData();
771 ImageData post = new ImageData();
772 ImageData thumb = new ImageData();
774 if (image != IntPtr.Zero)
776 _img = Interop.Camera.IntPtrToImageDataStruct(image);
777 CopyImageData(img, _img);
779 if (postview != IntPtr.Zero)
781 _post = Interop.Camera.IntPtrToImageDataStruct(postview);
782 CopyImageData(post, _post);
784 if (thumbnail != IntPtr.Zero)
786 _thumb = Interop.Camera.IntPtrToImageDataStruct(thumbnail);
787 CopyImageData(thumb, _thumb);
790 CapturingEventArgs eventArgs = new CapturingEventArgs(img, post, thumb);
791 Capturing?.Invoke(this, eventArgs);
794 _captureCompletedCallback = (IntPtr userData) =>
796 EventArgs eventArgs = new EventArgs();
797 CaptureCompleted?.Invoke(this, eventArgs);
800 int ret = Interop.Camera.StartCapture(_handle, _capturingCallback, _captureCompletedCallback, IntPtr.Zero);
801 if (ret != (int)CameraError.None)
803 CameraErrorFactory.ThrowException(ret, "Failed to start the camera capture.");
805 Log.Info(CameraLog.Tag, "StartCapture API finished");
809 /// Aborts continuous capturing.
812 /// http://tizen.org/privilege/camera
814 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
815 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
816 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
817 public void StopContinuousCapture()
819 int ret = Interop.Camera.StopContinuousCapture(_handle);
820 if (ret != (int)CameraError.None)
822 CameraErrorFactory.ThrowException(ret, "Failed to stop the continuous capture.");
827 /// Starts continuously capturing still images.
828 /// EventHandler must be set for capturing using <see cref="Tizen.Multimedia.Camera.Capturing"/>
829 /// and for completed using <see cref="Tizen.Multimedia.Camera.CaptureCompleted"/> before
830 /// calling this method.
833 /// http://tizen.org/privilege/camera
835 /// <param name="count">The number of still images.</param>
836 /// <param name="interval">The interval of the capture(milliseconds).</param>
838 /// If this is not supported zero shutter lag occurs. The capture resolution could be
839 /// changed to the preview resolution. This function causes the transition of the camera state
840 /// from Capturing to Captured automatically and the corresponding Eventhandlers will be invoked.
841 /// Each captured image will be delivered through Eventhandler set using <see cref="Tizen.Multimedia.Camera.Capturing"/> event.
842 /// The camera's preview should be restarted by calling <see cref="Tizen.Multimedia.Camera.StartPreview"/> method.
844 /// <exception cref="ArgumentException">In case of invalid parameters</exception>
845 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
846 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
847 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
848 public void StartContinuousCapture(int count, int interval)
850 _capturingCallback = (IntPtr image, IntPtr postview, IntPtr thumbnail, IntPtr userData) =>
852 Interop.Camera.ImageDataStruct _img = new Interop.Camera.ImageDataStruct();
853 Interop.Camera.ImageDataStruct _post = new Interop.Camera.ImageDataStruct();
854 Interop.Camera.ImageDataStruct _thumb = new Interop.Camera.ImageDataStruct();
855 ImageData img = new ImageData();
856 ImageData post = new ImageData();
857 ImageData thumb = new ImageData();
859 if (image != IntPtr.Zero)
861 _img = Interop.Camera.IntPtrToImageDataStruct(image);
862 CopyImageData(img, _img);
864 if (postview != IntPtr.Zero)
866 _post = Interop.Camera.IntPtrToImageDataStruct(postview);
867 CopyImageData(post, _post);
869 if (thumbnail != IntPtr.Zero)
871 _thumb = Interop.Camera.IntPtrToImageDataStruct(thumbnail);
872 CopyImageData(thumb, _thumb);
875 CapturingEventArgs eventArgs = new CapturingEventArgs(img, post, thumb);
876 Capturing?.Invoke(this, eventArgs);
879 _captureCompletedCallback = (IntPtr userData) =>
881 EventArgs eventArgs = new EventArgs();
882 CaptureCompleted?.Invoke(this, eventArgs);
885 int ret = Interop.Camera.StartContinuousCapture(_handle, count, interval, _capturingCallback, _captureCompletedCallback, IntPtr.Zero);
886 if (ret != (int)CameraError.None)
888 CameraErrorFactory.ThrowException(ret, "Failed to start the continuous capture.");
893 /// Sets the display handle to show preview images.
895 /// <param name="displayType">Display type.</param>
896 /// <param name="preview">MediaView object to display preview.</param>
898 /// This method must be called before StartPreview() method.
899 /// In Custom ROI display mode, DisplayRoiArea property must be set before calling this method.
901 /// <exception cref="ArgumentException">In case of invalid parameters</exception>
902 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
903 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
904 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
905 public void SetDisplay(CameraDisplayType displayType, MediaView preview)
907 int ret = Interop.Camera.SetDisplay(_handle, (int)displayType, preview);
908 if (ret != (int)CameraError.None)
910 CameraErrorFactory.ThrowException(ret, "Failed to set the camera display.");
915 /// Starts camera auto-focusing, asynchronously.
917 /// <param name="continuous">Continuous.</param>
919 /// http://tizen.org/privilege/camera
922 /// If continuous status is true, the camera continuously tries to focus.
924 /// <exception cref="ArgumentException">In case of invalid parameters</exception>
925 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
926 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
927 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
928 public void StartFocusing(bool continuous)
930 int ret = Interop.Camera.StartFocusing(_handle, continuous);
931 if (ret != (int)CameraError.None)
933 CameraErrorFactory.ThrowException(ret, "Failed to cancel the camera focus.");
938 /// Stops camera auto focusing.
941 /// http://tizen.org/privilege/camera
943 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
944 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
945 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
946 public void CancelFocusing()
948 int ret = Interop.Camera.CancelFocusing(_handle);
949 if (ret != (int)CameraError.None)
951 CameraErrorFactory.ThrowException(ret, "Failed to cancel the camera focus.");
956 /// Starts face detection.
959 /// http://tizen.org/privilege/camera
962 /// This should be called after <see cref="Tizen.Multimedia.Camera.StartPreview"/> is started.
963 /// The Eventhandler set using <see cref="Tizen.Multimedia.Camera.FaceDetected"/> invoked when the face is detected in preview frame.
964 /// Internally it starts continuous focus and focusing on the detected face.
966 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
967 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
968 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
969 public void StartFaceDetection()
971 _faceDetectedCallback = (IntPtr faces, int count, IntPtr userData) =>
973 Interop.Camera.DetectedFaceStruct[] faceStruct = new Interop.Camera.DetectedFaceStruct[count];
974 IntPtr current = faces;
975 for (int i = 0; i < count; i++)
977 faceStruct[i] = Marshal.PtrToStructure<Interop.Camera.DetectedFaceStruct>(current);
978 FaceDetectedData face = new FaceDetectedData(faceStruct[i].id, faceStruct[i].score, faceStruct[i].x, faceStruct[i].y, faceStruct[i].width, faceStruct[i].height);
980 current = (IntPtr)((long)current + Marshal.SizeOf(faceStruct[i]));
983 FaceDetectedEventArgs eventArgs = new FaceDetectedEventArgs(_faces);
984 FaceDetected?.Invoke(this, eventArgs);
987 int ret = Interop.Camera.StartFaceDetection(_handle, _faceDetectedCallback, IntPtr.Zero);
988 if (ret != (int)CameraError.None)
990 CameraErrorFactory.ThrowException(ret, "Failed to start the face detection.");
995 /// Stops face detection.
998 /// http://tizen.org/privilege/camera
1000 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
1001 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
1002 /// <exception cref="UnauthorizedAccessException">In case of access to the resources cannot be granted</exception>
1003 public void StopFaceDetection()
1005 int ret = Interop.Camera.StopFaceDetection(_handle);
1006 if (ret != (int)CameraError.None)
1008 CameraErrorFactory.ThrowException(ret, "Failed to stop the face detection.");
1013 /// DeviceChangedCallback delegate.
1015 public delegate void DeviceChangedCallback(CameraDevice device, CameraDeviceState state, IntPtr userData);
1018 /// set the DeviceStateChanged Callback.
1020 /// <param name="callback">Callback of type <see cref="Tizen.Multimedia.Camera.DeviceChangedCallback"/>.</param>
1021 /// <param name="callbackId">The Id of registered callback.</param>
1022 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
1023 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
1024 /// <exception cref="ArgumentException">In case of invalid parameters</exception>
1025 public static void SetDeviceStateChangedCallback(DeviceChangedCallback callback, out int callbackId)
1027 int ret = Camera.AddDeviceChangedCallback(callback, IntPtr.Zero, out callbackId);
1028 if (ret != (int)CameraError.None)
1030 CameraErrorFactory.ThrowException(ret, "Setting device state changed callback failed");
1035 /// Unset the DeviceStateChanged Callback.
1037 /// <param name="callbackId">Registered callbackId to be deleted.</param>
1038 /// <exception cref="InvalidOperationException">In case of any invalid operations</exception>
1039 /// <exception cref="NotSupportedException">In case of this feature is not supported</exception>
1040 /// <exception cref="ArgumentException">In case of invalid parameters</exception>
1041 public static void UnsetDeviceStateChangedCallback(int callbackId)
1043 int ret = Interop.Camera.UnsetDeviceStateChangedCallback(callbackId);
1044 if (ret != (int)CameraError.None)
1046 CameraErrorFactory.ThrowException(ret, "Unsetting device state changed callback failed");
1051 /// Release any unmanaged resources used by this object.
1053 public void Dispose()
1056 GC.SuppressFinalize(this);
1059 protected virtual void Dispose(bool disposing)
1065 // to be used if there are any other disposable objects
1068 if (_handle != IntPtr.Zero)
1070 Interop.Camera.Destroy(_handle);
1071 _handle = IntPtr.Zero;
1078 internal void ValidateNotDisposed()
1082 throw new ObjectDisposedException(nameof(Camera));
1086 [DllImport(Interop.Libraries.Camera, EntryPoint = "camera_add_device_state_changed_cb")]
1087 internal static extern int AddDeviceChangedCallback(DeviceChangedCallback callback, IntPtr userData, out int callbackId);
1089 internal static void CopyImageData(ImageData image, Interop.Camera.ImageDataStruct img)
1091 image._data = new byte[img.size];
1092 if(img.data != IntPtr.Zero)
1093 Marshal.Copy(img.data, image._data, 0, (int)img.size);
1094 image._width = img.width;
1095 image._height = img.height;
1096 image._format = img.format;
1097 image._exif = new byte[img.exifSize];
1098 if (img.exif != IntPtr.Zero)
1099 Marshal.Copy(img.exif, image._exif, 0, (int)img.exifSize);
1102 internal static PreviewData CopyPreviewData(Interop.Camera.CameraPreviewDataStruct previewStruct, PlaneType type)
1104 Log.Info(CameraLog.Tag, "plane type " + type.ToString());
1105 if (type == PlaneType.SinglePlane)
1107 SinglePlaneData singleData = new SinglePlaneData();
1108 singleData.Format = previewStruct.format;
1109 singleData.Height = previewStruct.height;
1110 singleData.TimeStamp = previewStruct.timestamp;
1111 singleData.Width = previewStruct.width;
1112 Interop.Camera.SinglePlane singlePlane = previewStruct.frameData.singlePlane;
1113 singleData.YUVData = new byte[singlePlane.yuvsize];
1115 if (singlePlane.yuvsize > 0)
1116 Marshal.Copy(singlePlane.yuv, singleData.YUVData, 0, (int)singlePlane.yuvsize);
1120 else if (type == PlaneType.DoublePlane)
1122 DoublePlaneData doubleData = new DoublePlaneData();
1123 doubleData.Format = previewStruct.format;
1124 doubleData.Height = previewStruct.height;
1125 doubleData.TimeStamp = previewStruct.timestamp;
1126 doubleData.Width = previewStruct.width;
1127 Interop.Camera.DoublePlane doublePlane = previewStruct.frameData.doublePlane;
1128 doubleData.YData = new byte[doublePlane.ysize];
1129 doubleData.UVData = new byte[doublePlane.uvsize];
1130 Log.Info(CameraLog.Tag, "ysize " + doublePlane.ysize);
1131 Log.Info(CameraLog.Tag, "uv size " + doublePlane.uvsize);
1133 if (doublePlane.ysize > 0)
1134 Marshal.Copy(doublePlane.y, doubleData.YData, 0, (int)doublePlane.ysize);
1136 if (doublePlane.uvsize > 0)
1137 Marshal.Copy(doublePlane.uv, doubleData.UVData, 0, (int)doublePlane.uvsize);
1141 else if (type == PlaneType.TriplePlane)
1143 TriplePlaneData tripleData = new TriplePlaneData();
1144 tripleData.Format = previewStruct.format;
1145 tripleData.Height = previewStruct.height;
1146 tripleData.TimeStamp = previewStruct.timestamp;
1147 tripleData.Width = previewStruct.width;
1148 Interop.Camera.TriplePlane triplePlane = previewStruct.frameData.triplePlane;
1149 tripleData.YData = new byte[triplePlane.ysize];
1150 tripleData.UData = new byte[triplePlane.usize];
1151 tripleData.VData = new byte[triplePlane.vsize];
1153 if (triplePlane.ysize > 0)
1154 Marshal.Copy(triplePlane.y, tripleData.YData, 0, (int)triplePlane.ysize);
1156 if (triplePlane.usize > 0)
1157 Marshal.Copy(triplePlane.u, tripleData.UData, 0, (int)triplePlane.usize);
1159 if (triplePlane.vsize > 0)
1160 Marshal.Copy(triplePlane.v, tripleData.VData, 0, (int)triplePlane.vsize);
1166 EncodedPlaneData encodedData = new EncodedPlaneData();
1167 encodedData.Format = previewStruct.format;
1168 encodedData.Height = previewStruct.height;
1169 encodedData.TimeStamp = previewStruct.timestamp;
1170 encodedData.Width = previewStruct.width;
1171 Interop.Camera.EncodedPlane encodedPlane = previewStruct.frameData.encodedPlane;
1172 encodedData.Data = new byte[encodedPlane.size];
1174 if (encodedPlane.size > 0)
1175 Marshal.Copy(encodedPlane.data, encodedData.Data, 0, (int)encodedPlane.size);
1181 private void CreatePreviewCallback()
1183 Log.Info(CameraLog.Tag, "Create preview callback.");
1185 _previewCallback = (IntPtr frame, IntPtr userData) =>
1187 Interop.Camera.CameraPreviewDataStruct _previewStruct = Interop.Camera.IntPtrToCameraPreviewDataStruct(frame);
1188 PlaneType _type = PlaneType.SinglePlane;
1189 PreviewData _previewData = new PreviewData();
1191 if (_previewStruct.format == CameraPixelFormat.H264 || _previewStruct.format == CameraPixelFormat.Jpeg)
1193 _type = PlaneType.EncodedPlane;
1194 _previewData = CopyPreviewData(_previewStruct, _type);
1198 Log.Info(CameraLog.Tag, "Number of plane " + _previewStruct.numOfPlanes);
1199 if (_previewStruct.numOfPlanes == 1)
1201 _type = PlaneType.SinglePlane;
1202 _previewData = CopyPreviewData(_previewStruct, _type);
1204 else if (_previewStruct.numOfPlanes == 2)
1206 _type = PlaneType.DoublePlane;
1207 _previewData = CopyPreviewData(_previewStruct, _type);
1209 else if (_previewStruct.numOfPlanes == 3)
1211 _type = PlaneType.TriplePlane;
1212 _previewData = CopyPreviewData(_previewStruct, _type);
1216 PreviewEventArgs eventArgs = new PreviewEventArgs(_previewData, _type);
1218 _preview?.Invoke(this, eventArgs);
1221 int ret = Interop.Camera.SetPreviewCallback(_handle, _previewCallback, IntPtr.Zero);
1222 if (ret != (int)CameraError.None)
1224 CameraErrorFactory.ThrowException(ret, "Setting preview callback failed");
1228 private void CreateMediaPacketPreviewCallback()
1230 _mediaPacketCallback = (IntPtr mediaPacket, IntPtr userData) =>
1232 MediaPacket packet = MediaPacket.From(mediaPacket);
1234 MediaPacketPreviewEventArgs eventArgs = new MediaPacketPreviewEventArgs(packet);
1235 _mediaPacketPreview?.Invoke(this, eventArgs);
1238 int ret = Interop.Camera.SetMediaPacketPreviewCallback(_handle, _mediaPacketCallback, IntPtr.Zero);
1239 if (ret != (int)CameraError.None)
1241 CameraErrorFactory.ThrowException(ret, "Setting media packet preview callback failed");