From 31bae33582c993b4bee5bea479dc441d4e1aab97 Mon Sep 17 00:00:00 2001 From: Haesu Gwon Date: Fri, 11 Feb 2022 14:49:34 +0900 Subject: [PATCH 1/1] [Camera] Support variable buffer size (#3934) --- .../Camera/Camera.Events.cs | 4 + src/Tizen.Multimedia.Camera/Camera/Camera.cs | 2 +- .../Camera/PinnedPreviewBuffer.cs | 2 +- src/Tizen.Multimedia.Camera/Camera/PreviewFrame.cs | 97 ++++++++++++++++++++-- 4 files changed, 96 insertions(+), 9 deletions(-) diff --git a/src/Tizen.Multimedia.Camera/Camera/Camera.Events.cs b/src/Tizen.Multimedia.Camera/Camera/Camera.Events.cs index aae60ca..6567668 100644 --- a/src/Tizen.Multimedia.Camera/Camera/Camera.Events.cs +++ b/src/Tizen.Multimedia.Camera/Camera/Camera.Events.cs @@ -411,6 +411,8 @@ namespace Tizen.Multimedia Native.UnsetPreviewCallback(_handle). ThrowIfFailed("Failed to unset preview callback."); + _previewBuffer?.Dispose(); + _previewBuffer = null; _previewCallback = null; } @@ -459,6 +461,8 @@ namespace Tizen.Multimedia Native.UnsetExtraPreviewCallback(_handle). ThrowIfFailed("Failed to unset extra preview callback."); + _previewBuffer?.Dispose(); + _previewBuffer = null; _extraPreviewCallback = null; } } diff --git a/src/Tizen.Multimedia.Camera/Camera/Camera.cs b/src/Tizen.Multimedia.Camera/Camera/Camera.cs index 780d963..ab55d55 100644 --- a/src/Tizen.Multimedia.Camera/Camera/Camera.cs +++ b/src/Tizen.Multimedia.Camera/Camera/Camera.cs @@ -166,7 +166,7 @@ namespace Tizen.Multimedia if (disposing) { // to be used if there are any other disposable objects - _previewBuffer.Dispose(); + _previewBuffer?.Dispose(); } if (_handle != IntPtr.Zero) diff --git a/src/Tizen.Multimedia.Camera/Camera/PinnedPreviewBuffer.cs b/src/Tizen.Multimedia.Camera/Camera/PinnedPreviewBuffer.cs index a03c4cd..ecb8ccf 100644 --- a/src/Tizen.Multimedia.Camera/Camera/PinnedPreviewBuffer.cs +++ b/src/Tizen.Multimedia.Camera/Camera/PinnedPreviewBuffer.cs @@ -54,7 +54,7 @@ namespace Tizen.Multimedia gcHandle.Free(); } - Log.Info(CameraLog.Tag, $"Disposed : {disposing})"); + Log.Info(CameraLog.Tag, $"Disposed : {disposing}"); disposedValue = true; } } diff --git a/src/Tizen.Multimedia.Camera/Camera/PreviewFrame.cs b/src/Tizen.Multimedia.Camera/Camera/PreviewFrame.cs index 82bcc5e..c6bcd6c 100644 --- a/src/Tizen.Multimedia.Camera/Camera/PreviewFrame.cs +++ b/src/Tizen.Multimedia.Camera/Camera/PreviewFrame.cs @@ -27,6 +27,8 @@ namespace Tizen.Multimedia /// 4 public class PreviewFrame { + private const uint _variableBufferMargin = 2; + internal PreviewFrame(IntPtr ptr, ref PinnedPreviewBuffer buffers) { var unmanagedStruct = Marshal.PtrToStructure(ptr); @@ -74,7 +76,7 @@ namespace Tizen.Multimedia case PlaneType.SinglePlane: var singlePlane = unmanagedStruct.Plane.SinglePlane; - if (buffers == null) + if (buffers == null || CheckReallocation(unmanagedStruct, ref buffers)) { buffers = new PinnedPreviewBuffer(singlePlane.DataLength); } @@ -89,7 +91,7 @@ namespace Tizen.Multimedia doublePlane.YLength = (uint)(Resolution.Width * Resolution.Height); doublePlane.UVLength = (uint)(Resolution.Width * Resolution.Height) / 2; - if (buffers == null) + if (buffers == null || CheckReallocation(unmanagedStruct, ref buffers)) { buffers = new PinnedPreviewBuffer(doublePlane.YLength, doublePlane.UVLength); } @@ -102,7 +104,7 @@ namespace Tizen.Multimedia case PlaneType.TriplePlane: var triplePlane = unmanagedStruct.Plane.TriplePlane; - if (buffers == null) + if (buffers == null || CheckReallocation(unmanagedStruct, ref buffers)) { buffers = new PinnedPreviewBuffer(triplePlane.YLength, triplePlane.ULength, triplePlane.VLength); } @@ -116,9 +118,10 @@ namespace Tizen.Multimedia case PlaneType.EncodedPlane: var encodedPlane = unmanagedStruct.Plane.EncodedPlane; - if (buffers == null) + if (buffers == null || CheckReallocation(unmanagedStruct, ref buffers)) { - buffers = new PinnedPreviewBuffer(encodedPlane.DataLength * 2); + // We take buffer margin to avoid reallocation as much as possible. + buffers = new PinnedPreviewBuffer(encodedPlane.DataLength * _variableBufferMargin); } Marshal.Copy(encodedPlane.Data, buffers[0], 0, (int)encodedPlane.DataLength); @@ -128,7 +131,7 @@ namespace Tizen.Multimedia case PlaneType.DepthPlane: var depthPlane = unmanagedStruct.Plane.DepthPlane; - if (buffers == null) + if (buffers == null || CheckReallocation(unmanagedStruct, ref buffers)) { buffers = new PinnedPreviewBuffer(depthPlane.DataLength); } @@ -140,7 +143,7 @@ namespace Tizen.Multimedia case PlaneType.RgbPlane: var rgbPlane = unmanagedStruct.Plane.RgbPlane; - if (buffers == null) + if (buffers == null || CheckReallocation(unmanagedStruct, ref buffers)) { buffers = new PinnedPreviewBuffer(rgbPlane.DataLength); } @@ -187,6 +190,86 @@ namespace Tizen.Multimedia return size; } + internal bool CheckReallocation(CameraPreviewDataStruct unmanagedStruct, ref PinnedPreviewBuffer buffers) + { + bool isReallocation = false; + + switch (PlaneType) + { + case PlaneType.SinglePlane: + var singlePlane = unmanagedStruct.Plane.SinglePlane; + + if (buffers[0].Length < singlePlane.DataLength) + { + isReallocation = true; + } + + 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[0].Length < doublePlane.YLength || buffers[1].Length < doublePlane.UVLength) + { + isReallocation = true; + } + + break; + case PlaneType.TriplePlane: + var triplePlane = unmanagedStruct.Plane.TriplePlane; + + if (buffers[0].Length < triplePlane.YLength || buffers[1].Length < triplePlane.ULength || buffers[2].Length < triplePlane.VLength) + { + isReallocation = true; + } + + break; + case PlaneType.EncodedPlane: + var encodedPlane = unmanagedStruct.Plane.EncodedPlane; + + if (buffers[0].Length < encodedPlane.DataLength) + { + Log.Debug(CameraLog.Tag, $"Cur size:{buffers[0].Length} -> New size:{encodedPlane.DataLength * _variableBufferMargin}"); + isReallocation = true; + } + + break; + case PlaneType.DepthPlane: + var depthPlane = unmanagedStruct.Plane.DepthPlane; + + if (buffers[0].Length < depthPlane.DataLength) + { + isReallocation = true; + } + + break; + case PlaneType.RgbPlane: + var rgbPlane = unmanagedStruct.Plane.RgbPlane; + + if (buffers[0].Length < rgbPlane.DataLength) + { + isReallocation = true; + } + + break; + default: + Debug.Fail("Unknown preview data!"); + break; + } + + if (isReallocation) + { + Log.Debug(CameraLog.Tag, "Reallocate preview buffer."); + + // Dispose current buffer to free GCHandle. + buffers.Dispose(); + } + + return isReallocation; + } + /// /// The pixel format of the image. /// -- 2.7.4