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.ComponentModel;
19 using Native = Interop.Camera;
21 namespace Tizen.Multimedia
24 /// This camera class provides methods to capture photos and supports setting up notifications
25 /// for state changes of capturing, previewing, focusing, and informing about the resolution and the binary format,
26 /// and functions for picture manipulations like sepia, negative, and many more.
27 /// It also notifies you when a significant picture parameter changes, (For example, focus).
29 /// <since_tizen> 3 </since_tizen>
30 /// <feature> http://tizen.org/feature/camera </feature>
31 public partial class Camera : IDisposable, IDisplayable<CameraError>
34 /// An event that occurs when the camera interrupt is started by the policy.
36 /// <since_tizen> 4 </since_tizen>
37 public event EventHandler<CameraInterruptStartedEventArgs> InterruptStarted;
38 private Native.InterruptStartedCallback _interruptStartedCallback;
41 /// An event that occurs when an camera is interrupted by the policy.
43 /// <since_tizen> 3 </since_tizen>
44 public event EventHandler<CameraInterruptedEventArgs> Interrupted;
45 private Native.InterruptedCallback _interruptedCallback;
48 /// An event that occurs when there is an asynchronous error.
50 /// <since_tizen> 3 </since_tizen>
51 public event EventHandler<CameraErrorOccurredEventArgs> ErrorOccurred;
52 private Native.ErrorCallback _errorCallback;
55 /// An event that occurs when the auto focus state is changed.
57 /// <since_tizen> 3 </since_tizen>
58 public event EventHandler<CameraFocusStateChangedEventArgs> FocusStateChanged;
59 private Native.FocusStateChangedCallback _focusStateChangedCallback;
62 /// An event that occurs when a face is detected in the preview frame.
64 /// <since_tizen> 3 </since_tizen>
65 public event EventHandler<FaceDetectedEventArgs> FaceDetected;
66 private Native.FaceDetectedCallback _faceDetectedCallback;
69 /// An event that occurs during capture of an image.
71 /// <since_tizen> 3 </since_tizen>
72 public event EventHandler<CameraCapturingEventArgs> Capturing;
73 private Native.CapturingCallback _capturingCallback;
76 /// An event that occurs after the capture of the image.
78 /// <since_tizen> 3 </since_tizen>
79 public event EventHandler<EventArgs> CaptureCompleted;
80 private Native.CaptureCompletedCallback _captureCompletedCallback;
82 private Native.HdrCaptureProgressCallback _hdrCaptureProgressCallback;
83 private event EventHandler<HdrCaptureProgressEventArgs> _hdrCaptureProgress;
84 private object _hdrCaptureProgressEventLock = new object();
87 /// An event that occurs when there is a change in the HDR capture progress.
88 /// Checks whether the <see cref="CameraCapabilities.IsHdrCaptureSupported"/> is supported or not before adding this EventHandler.
90 /// <since_tizen> 3 </since_tizen>
91 /// <exception cref="NotSupportedException">In case of HDR feature is not supported.</exception>
92 public event EventHandler<HdrCaptureProgressEventArgs> HdrCaptureProgress
96 lock (_hdrCaptureProgressEventLock)
98 if (_hdrCaptureProgress == null)
100 RegisterHdrCaptureProgress();
103 _hdrCaptureProgress += value;
109 lock (_hdrCaptureProgressEventLock)
111 _hdrCaptureProgress -= value;
113 if (_hdrCaptureProgress == null)
115 UnregisterHdrCaptureProgress();
122 /// An event that occurs when the camera state is changed.
124 /// <since_tizen> 3 </since_tizen>
125 public event EventHandler<CameraStateChangedEventArgs> StateChanged;
126 private Native.StateChangedCallback _stateChangedCallback;
128 private static Native.DeviceStateChangedCallback _deviceStateChangedCallback;
129 private static event EventHandler<CameraDeviceStateChangedEventArgs> _deviceStateChanged;
130 private static object _deviceStateChangedEventLock = new object();
131 private static int _deviceStateCallbackId;
134 /// An event that occurs after the <see cref="CameraDeviceState"/> is changed.
136 /// <since_tizen> 3 </since_tizen>
137 /// <exception cref="InvalidOperationException">In case of any invalid operations.</exception>
138 /// <exception cref="NotSupportedException">In case of this feature is not supported.</exception>
139 /// <exception cref="ArgumentException">In case of invalid parameters.</exception>
140 public static event EventHandler<CameraDeviceStateChangedEventArgs> DeviceStateChanged
144 lock (_deviceStateChangedEventLock)
146 if (_deviceStateChanged == null)
148 RegisterDeviceStateChangedCallback();
151 _deviceStateChanged += value;
157 lock (_deviceStateChangedEventLock)
159 _deviceStateChanged -= value;
161 if (_deviceStateChanged == null)
163 UnregisterDeviceStateChangedCallback();
169 private Native.PreviewCallback _previewCallback;
170 private event EventHandler<PreviewEventArgs> _preview;
171 private object _previewEventLock = new object();
173 /// An event that occurs once per frame when previewing.
174 /// Preview callback is registered when an user adds a callback explicitly to avoid useless P/Invoke.
176 /// <since_tizen> 3 </since_tizen>
177 public event EventHandler<PreviewEventArgs> Preview
181 lock (_previewEventLock)
183 if (_preview == null)
185 RegisterPreviewCallback();
194 lock (_previewEventLock)
198 if (_preview == null)
200 UnregisterPreviewCallback();
206 private Native.MediaPacketPreviewCallback _mediaPacketPreviewCallback;
207 private EventHandler<MediaPacketPreviewEventArgs> _mediaPacketPreview;
208 private object _mediaPacketPreviewEventLock = new object();
211 /// An event that occurs once per frame when previewing.
212 /// Preview callback is registered when an user adds a callback explicitly to avoid useless P/Invoke.
214 /// <since_tizen> 3 </since_tizen>
215 public event EventHandler<MediaPacketPreviewEventArgs> MediaPacketPreview
219 lock (_mediaPacketPreviewEventLock)
221 if (_mediaPacketPreview == null)
223 RegisterMediaPacketPreviewCallback();
226 _mediaPacketPreview += value;
232 lock (_mediaPacketPreviewEventLock)
234 _mediaPacketPreview -= value;
236 if (_mediaPacketPreview == null)
238 UnregisterMediaPacketPreviewCallback();
244 private Native.ExtraPreviewCallback _extraPreviewCallback;
245 private event EventHandler<ExtraPreviewEventArgs> _extraPreview;
247 /// An event that occurs once per frame when previewing.
248 /// Preview callback is registered when an user adds a callback explicitly to avoid useless P/Invoke.
250 /// <since_tizen> 9 </since_tizen>
251 [EditorBrowsable(EditorBrowsableState.Never)]
252 public event EventHandler<ExtraPreviewEventArgs> ExtraPreview
256 if (_extraPreview == null)
258 RegisterExtraPreviewCallback();
261 _extraPreview += value;
266 _extraPreview -= value;
268 if (_extraPreview == null)
270 UnregisterExtraPreviewCallback();
275 private void RegisterCallbacks()
277 RegisterErrorCallback();
278 RegisterFocusStateChanged();
279 RegisterInterruptStartedCallback();
280 RegisterInterruptedCallback();
281 RegisterStateChangedCallback();
283 //Define capturing callback
284 _capturingCallback = (main, postview, thumbnail, userData) =>
286 Capturing?.Invoke(this, new CameraCapturingEventArgs(new StillImage(main),
287 postview == IntPtr.Zero ? null : new StillImage(postview),
288 thumbnail == IntPtr.Zero ? null : new StillImage(thumbnail)));
291 //Define captureCompleted callback
292 _captureCompletedCallback = _ =>
294 SetState(CameraState.Captured);
295 CaptureCompleted?.Invoke(this, EventArgs.Empty);
299 private void RegisterInterruptStartedCallback()
301 _interruptStartedCallback = (policy, state, _) =>
303 InterruptStarted?.Invoke(this, new CameraInterruptStartedEventArgs(policy, state));
306 Native.SetInterruptStartedCallback(_handle, _interruptStartedCallback).
307 ThrowIfFailed("Failed to set interrupt callback.");
310 private void RegisterInterruptedCallback()
312 _interruptedCallback = (policy, previous, current, _) =>
314 Interrupted?.Invoke(this, new CameraInterruptedEventArgs(policy, previous, current));
317 Native.SetInterruptedCallback(_handle, _interruptedCallback).
318 ThrowIfFailed("Failed to set interrupt callback.");
321 private void RegisterErrorCallback()
323 _errorCallback = (error, current, _) =>
325 ErrorOccurred?.Invoke(this, new CameraErrorOccurredEventArgs(error, current));
328 Native.SetErrorCallback(_handle, _errorCallback).
329 ThrowIfFailed("Setting error callback failed");
332 private void RegisterStateChangedCallback()
334 _stateChangedCallback = (previous, current, byPolicy, _) =>
337 Log.Info(CameraLog.Tag, "Camera state changed " + previous.ToString() + " -> " + current.ToString());
338 StateChanged?.Invoke(this, new CameraStateChangedEventArgs(previous, current, byPolicy));
341 Native.SetStateChangedCallback(_handle, _stateChangedCallback).
342 ThrowIfFailed("Failed to set state changed callback.");
345 private static void RegisterDeviceStateChangedCallback()
347 _deviceStateChangedCallback = (device, state, _) =>
349 _deviceStateChanged?.Invoke(null, new CameraDeviceStateChangedEventArgs(device, state));
352 Native.SetDeviceStateChangedCallback(_deviceStateChangedCallback, IntPtr.Zero, out _deviceStateCallbackId).
353 ThrowIfFailed("Failed to set device state changed callback.");
355 Log.Info(CameraLog.Tag, "add callbackId " + _deviceStateCallbackId.ToString());
358 private static void UnregisterDeviceStateChangedCallback()
360 Native.UnsetDeviceStateChangedCallback(_deviceStateCallbackId).
361 ThrowIfFailed("Failed to unset device state changed callback.");
363 _deviceStateChangedCallback = null;
364 _deviceStateCallbackId = 0;
367 private void RegisterFocusStateChanged()
369 _focusStateChangedCallback = (state, _) =>
371 FocusStateChanged?.Invoke(this, new CameraFocusStateChangedEventArgs(state));
374 Native.SetFocusStateChangedCallback(_handle, _focusStateChangedCallback).
375 ThrowIfFailed("Failed to set focus changed callback.");
378 private void RegisterHdrCaptureProgress()
380 _hdrCaptureProgressCallback = (percent, _) =>
382 _hdrCaptureProgress?.Invoke(this, new HdrCaptureProgressEventArgs(percent));
385 Native.SetHdrCaptureProgressCallback(_handle, _hdrCaptureProgressCallback).
386 ThrowIfFailed("Failed to set Hdr capture progress callback.");
389 private void UnregisterHdrCaptureProgress()
391 Native.UnsetHdrCaptureProgressCallback(_handle).
392 ThrowIfFailed("Failed to unset hdr capture progres callback.");
394 _hdrCaptureProgressCallback = null;
397 private void RegisterPreviewCallback()
399 _previewCallback = (frame, _) =>
401 _preview?.Invoke(this,
402 new PreviewEventArgs(new PreviewFrame(frame, ref _previewBuffer)));
405 Native.SetPreviewCallback(_handle, _previewCallback).
406 ThrowIfFailed("Failed to set preview callback.");
409 private void UnregisterPreviewCallback()
411 Native.UnsetPreviewCallback(_handle).
412 ThrowIfFailed("Failed to unset preview callback.");
414 _previewBuffer?.Dispose();
415 _previewBuffer = null;
416 _previewCallback = null;
419 private void RegisterMediaPacketPreviewCallback()
421 _mediaPacketPreviewCallback = (mediaPacket, _) =>
423 MediaPacket packet = MediaPacket.From(mediaPacket);
425 var eventHandler = _mediaPacketPreview;
427 if (eventHandler != null)
429 eventHandler.Invoke(this, new MediaPacketPreviewEventArgs(packet));
435 Native.SetMediaPacketPreviewCallback(_handle, _mediaPacketPreviewCallback).
436 ThrowIfFailed("Failed to set media packet preview callback.");
439 private void UnregisterMediaPacketPreviewCallback()
441 Native.UnsetMediaPacketPreviewCallback(_handle).
442 ThrowIfFailed("Failed to unset media packet preview callback.");
444 _mediaPacketPreviewCallback = null;
447 private void RegisterExtraPreviewCallback()
449 _extraPreviewCallback = (frame, streamId, _) =>
451 _extraPreview?.Invoke(this,
452 new ExtraPreviewEventArgs(new PreviewFrame(frame, ref _previewBuffer), streamId));
455 Native.SetExtraPreviewCallback(_handle, _extraPreviewCallback).
456 ThrowIfFailed("Failed to set extra preview callback.");
459 private void UnregisterExtraPreviewCallback()
461 Native.UnsetExtraPreviewCallback(_handle).
462 ThrowIfFailed("Failed to unset extra preview callback.");
464 _previewBuffer?.Dispose();
465 _previewBuffer = null;
466 _extraPreviewCallback = null;