{
_previewCallback = (frame, _) =>
{
- _preview?.Invoke(this, new PreviewEventArgs(new PreviewFrame(frame)));
+ _preview?.Invoke(this,
+ new PreviewEventArgs(new PreviewFrame(frame, ref _previewBuffer)));
};
Native.SetPreviewCallback(_handle, _previewCallback).
{
_extraPreviewCallback = (frame, streamId, _) =>
{
- _extraPreview?.Invoke(this, new ExtraPreviewEventArgs(new PreviewFrame(frame), streamId));
+ _extraPreview?.Invoke(this,
+ new ExtraPreviewEventArgs(new PreviewFrame(frame, ref _previewBuffer), streamId));
};
Native.SetExtraPreviewCallback(_handle, _extraPreviewCallback).
private IntPtr _handle = IntPtr.Zero;
private bool _disposed = false;
private CameraState _state = CameraState.None;
+ PinnedPreviewBuffer<byte> _previewBuffer;
/// <summary>
/// Initializes a new instance of the <see cref="Camera"/> class.
if (disposing)
{
// to be used if there are any other disposable objects
+ _previewBuffer.Dispose();
}
if (_handle != IntPtr.Zero)
private int _connectionCallbackId = -1;
private void RegisterDeviceConnectionChangedCallback()
{
- Log.Debug(CameraLog.Tag, "Enter");
-
_deviceConnectionChangedCallback = (ref Native.CameraDeviceStruct device, bool status, IntPtr userData) =>
{
Log.Debug(CameraLog.Tag, "Invoke DeviceConnectionChanged event");
Native.SetDeviceConnectionChangedCallback(Handle, _deviceConnectionChangedCallback, IntPtr.Zero, out _connectionCallbackId).
ThrowIfFailed("Failed to set device connection changed callback");
- Log.Debug(CameraLog.Tag, $"Leave. callbackId[{_connectionCallbackId}]");
+ Log.Debug(CameraLog.Tag, $"callbackId[{_connectionCallbackId}]");
}
private void UnregisterDeviceConnectionChangedCallback()
{
- Log.Debug(CameraLog.Tag, $"Enter. callbackId[{_connectionCallbackId}]");
+ Log.Debug(CameraLog.Tag, $"callbackId[{_connectionCallbackId}]");
if (_connectionCallbackId >= 0)
{
* limitations under the License.
*/
-using System.Runtime.InteropServices;
-using static Interop.Camera;
-
namespace Tizen.Multimedia
{
/// <summary>
/// <since_tizen> 5 </since_tizen>
public class DepthPlane : IPreviewPlane
{
- internal DepthPlane(DepthPlaneStruct unmanagedData)
+ internal DepthPlane(byte[] data)
{
- Data = new byte[unmanagedData.DataLength];
- Marshal.Copy(unmanagedData.Data, Data, 0, (int)unmanagedData.DataLength);
+ Data = data;
}
/// <summary>
* limitations under the License.
*/
-using System.Runtime.InteropServices;
-using static Interop.Camera;
-
namespace Tizen.Multimedia
{
/// <summary>
/// <since_tizen> 3 </since_tizen>
public class DoublePlane : IPreviewPlane
{
- internal DoublePlane(DoublePlaneStruct unmanaged)
+ internal DoublePlane(params byte[][] data)
{
- Y = new byte[unmanaged.YLength];
- UV = new byte[unmanaged.UVLength];
- Marshal.Copy(unmanaged.Y, Y, 0, (int)unmanaged.YLength);
- Marshal.Copy(unmanaged.UV, UV, 0, (int)unmanaged.UVLength);
+ Y = data[0];
+ UV = data[1];
}
/// <summary>
* limitations under the License.
*/
-using System.Runtime.InteropServices;
-using static Interop.Camera;
-
namespace Tizen.Multimedia
{
/// <summary>
/// <since_tizen> 3 </since_tizen>
public class EncodedPlane : IPreviewPlane
{
- internal EncodedPlane(EncodedPlaneStruct unmanagedData)
+ internal EncodedPlane(byte[] data, bool isDeltaFrame)
{
- Data = new byte[unmanagedData.DataLength];
- Marshal.Copy(unmanagedData.Data, Data, 0, (int)unmanagedData.DataLength);
-
- IsDeltaFrame = unmanagedData.IsDeltaFrame;
+ Data = data;
+ IsDeltaFrame = isDeltaFrame;
}
/// <summary>
--- /dev/null
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace Tizen.Multimedia
+{
+ internal class PinnedPreviewBuffer<T> : IDisposable
+ {
+ private readonly GCHandle[] _gcHandles;
+ private readonly T[][] _buffers;
+
+ internal PinnedPreviewBuffer(params uint[] sizes)
+ {
+ _buffers = new T[sizes.Length][];
+ _gcHandles = new GCHandle[sizes.Length];
+
+ for (int i = 0 ; i < sizes.Length; i++)
+ {
+ _buffers[i] = new T[sizes[i]];
+ _gcHandles[i] = GCHandle.Alloc(_buffers[i], GCHandleType.Pinned);
+ }
+ }
+
+ ~PinnedPreviewBuffer()
+ {
+ Dispose(false);
+ }
+
+ internal T[] this[int index] => _buffers[index];
+
+ private bool disposedValue = false;
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposedValue)
+ {
+ foreach (var gcHandle in _gcHandles)
+ {
+ gcHandle.Free();
+ }
+
+ Log.Info(CameraLog.Tag, $"Disposed : {disposing})");
+ disposedValue = true;
+ }
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+ }
+}
/// <since_tizen> 4 </since_tizen>
public class PreviewFrame
{
- internal PreviewFrame(IntPtr ptr)
+ internal PreviewFrame(IntPtr ptr, ref PinnedPreviewBuffer<byte> buffers)
{
var unmanagedStruct = Marshal.PtrToStructure<CameraPreviewDataStruct>(ptr);
Resolution = new Size(unmanagedStruct.Width, unmanagedStruct.Height);
TimeStamp = unmanagedStruct.TimeStamp;
PlaneType = GetPlaneType(unmanagedStruct);
- Plane = ConvertPlane(unmanagedStruct);
+ CreatePlane(unmanagedStruct, ref buffers);
}
private static PlaneType GetPlaneType(CameraPreviewDataStruct unmanagedStruct)
return PlaneType.TriplePlane;
}
- private IPreviewPlane ConvertPlane(CameraPreviewDataStruct unmanagedStruct)
+ internal void CreatePlane(CameraPreviewDataStruct unmanagedStruct, ref PinnedPreviewBuffer<byte> buffers)
{
switch (PlaneType)
{
case PlaneType.SinglePlane:
- return new SinglePlane(unmanagedStruct.Plane.SinglePlane);
+ var singlePlane = unmanagedStruct.Plane.SinglePlane;
+
+ if (buffers == null)
+ {
+ buffers = new PinnedPreviewBuffer<byte>(singlePlane.DataLength);
+ }
+
+ Marshal.Copy(singlePlane.Data, buffers[0], 0, (int)singlePlane.DataLength);
+ Plane = new SinglePlane(buffers[0]);
+
+ break;
+ case PlaneType.DoublePlane:
+ var doublePlane = unmanagedStruct.Plane.DoublePlane;
+
+ doublePlane.YLength = (uint)(Resolution.Width * Resolution.Height);
+ doublePlane.UVLength = (uint)(Resolution.Width * Resolution.Height) / 2;
+
+ if (buffers == null)
+ {
+ buffers = new PinnedPreviewBuffer<byte>(doublePlane.YLength, doublePlane.UVLength);
+ }
+
+ Marshal.Copy(doublePlane.Y, buffers[0], 0, (int)doublePlane.YLength);
+ Marshal.Copy(doublePlane.UV, buffers[1], 0, (int)doublePlane.UVLength);
+ Plane = new DoublePlane(buffers[0], buffers[1]);
+
+ break;
+ case PlaneType.TriplePlane:
+ var triplePlane = unmanagedStruct.Plane.TriplePlane;
+
+ if (buffers == null)
+ {
+ buffers = new PinnedPreviewBuffer<byte>(triplePlane.YLength, triplePlane.ULength, triplePlane.VLength);
+ }
+
+ Marshal.Copy(triplePlane.Y, buffers[0], 0, (int)triplePlane.YLength);
+ Marshal.Copy(triplePlane.U, buffers[1], 0, (int)triplePlane.ULength);
+ Marshal.Copy(triplePlane.V, buffers[2], 0, (int)triplePlane.VLength);
+ Plane = new TriplePlane(buffers[0], buffers[1], buffers[2]);
+
+ break;
+ case PlaneType.EncodedPlane:
+ var encodedPlane = unmanagedStruct.Plane.EncodedPlane;
+
+ if (buffers == null)
+ {
+ buffers = new PinnedPreviewBuffer<byte>(encodedPlane.DataLength * 2);
+ }
+
+ Marshal.Copy(encodedPlane.Data, buffers[0], 0, (int)encodedPlane.DataLength);
+ Plane = new EncodedPlane(buffers[0], encodedPlane.IsDeltaFrame);
+
+ break;
+ case PlaneType.DepthPlane:
+ var depthPlane = unmanagedStruct.Plane.DepthPlane;
+
+ if (buffers == null)
+ {
+ buffers = new PinnedPreviewBuffer<byte>(depthPlane.DataLength);
+ }
+
+ Marshal.Copy(depthPlane.Data, buffers[0], 0, (int)depthPlane.DataLength);
+ Plane = new DepthPlane(buffers[0]);
+
+ break;
+ case PlaneType.RgbPlane:
+ var rgbPlane = unmanagedStruct.Plane.RgbPlane;
+
+ if (buffers == null)
+ {
+ buffers = new PinnedPreviewBuffer<byte>(rgbPlane.DataLength);
+ }
+ Marshal.Copy(rgbPlane.Data, buffers[0], 0, (int)rgbPlane.DataLength);
+
+ Plane = new RgbPlane(buffers[0]);
+ break;
+ default:
+ Debug.Fail("Unknown preview data!");
+ break;
+ }
+ }
+
+ internal static uint GetMaxPreviewPlaneSize(IntPtr ptr)
+ {
+ uint size = 0;
+ var unmanagedStruct = Marshal.PtrToStructure<CameraPreviewDataStruct>(ptr);
+
+ switch (GetPlaneType(unmanagedStruct))
+ {
+ case PlaneType.SinglePlane:
+ size = unmanagedStruct.Plane.SinglePlane.DataLength;
+ break;
case PlaneType.DoublePlane:
- var size = Resolution.Width * Resolution.Height;
- unmanagedStruct.Plane.DoublePlane.YLength = (uint)size;
- unmanagedStruct.Plane.DoublePlane.UVLength = (uint)size / 2;
- return new DoublePlane(unmanagedStruct.Plane.DoublePlane);
+ size = unmanagedStruct.Plane.DoublePlane.UVLength;
+ break;
case PlaneType.TriplePlane:
- return new TriplePlane(unmanagedStruct.Plane.TriplePlane);
+ size = unmanagedStruct.Plane.TriplePlane.YLength;
+ break;
case PlaneType.EncodedPlane:
- return new EncodedPlane(unmanagedStruct.Plane.EncodedPlane);
+ size = unmanagedStruct.Plane.EncodedPlane.DataLength;
+ break;
case PlaneType.DepthPlane:
- return new DepthPlane(unmanagedStruct.Plane.DepthPlane);
+ size = unmanagedStruct.Plane.DepthPlane.DataLength;
+ break;
case PlaneType.RgbPlane:
- return new RgbPlane(unmanagedStruct.Plane.RgbPlane);
+ size = unmanagedStruct.Plane.RgbPlane.DataLength;
+ break;
+ default:
+ Debug.Fail("Unknown preview data!");
+ break;
}
- Debug.Fail("Unknown preview data!");
- return null;
+ return size;
}
/// <summary>
/// The buffer including the preview frame.
/// </summary>
/// <since_tizen> 4 </since_tizen>
- public IPreviewPlane Plane { get; }
+ public IPreviewPlane Plane { get; private set;}
}
}
* limitations under the License.
*/
-using System.Runtime.InteropServices;
-using static Interop.Camera;
-
namespace Tizen.Multimedia
{
/// <summary>
/// <since_tizen> 5 </since_tizen>
public class RgbPlane : IPreviewPlane
{
- internal RgbPlane(RgbPlaneStruct unmanagedData)
+ internal RgbPlane(byte[] data)
{
- Data = new byte[unmanagedData.DataLength];
- Marshal.Copy(unmanagedData.Data, Data, 0, (int)unmanagedData.DataLength);
+ Data = data;
}
/// <summary>
* limitations under the License.
*/
-using System.Runtime.InteropServices;
-using static Interop.Camera;
-
namespace Tizen.Multimedia
{
/// <summary>
/// <since_tizen> 3 </since_tizen>
public class SinglePlane : IPreviewPlane
{
- internal SinglePlane(SinglePlaneStruct unmanaged)
+ internal SinglePlane(byte[] y)
{
- Data = new byte[unmanaged.DataLength];
- Marshal.Copy(unmanaged.Data, Data, 0, (int)unmanaged.DataLength);
+ Data = y;
}
/// <summary>
/// <since_tizen> 3 </since_tizen>
public class TriplePlane : IPreviewPlane
{
- internal TriplePlane(TriplePlaneStruct unmanaged)
+ internal TriplePlane(params byte[][] data)
{
- Y = new byte[unmanaged.YLength];
- U = new byte[unmanaged.ULength];
- V = new byte[unmanaged.VLength];
- Marshal.Copy(unmanaged.Y, Y, 0, (int)unmanaged.YLength);
- Marshal.Copy(unmanaged.U, U, 0, (int)unmanaged.ULength);
- Marshal.Copy(unmanaged.V, V, 0, (int)unmanaged.VLength);
+ Y = data[0];
+ U = data[1];
+ V = data[2];
}
/// <summary>