Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CoreVideo] Make P/Invokes in CVPixel related types have blittable signatures. #20510

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 73 additions & 73 deletions src/CoreVideo/CVPixelBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
// Copyright 2011-2014 Xamarin Inc
//
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using CoreFoundation;
using ObjCRuntime;
Expand Down Expand Up @@ -41,11 +42,11 @@ internal CVPixelBuffer (NativeHandle handle, bool owns) : base (handle, owns)

#if !COREBUILD
[DllImport (Constants.CoreVideoLibrary)]
extern static CVReturn CVPixelBufferCreate (
unsafe extern static CVReturn CVPixelBufferCreate (
/* CFAllocatorRef __nullable */ IntPtr allocator, /* size_t */ nint width, /* size_t */ nint height,
/* OSType */ CVPixelFormatType pixelFormatType,
/* CFDictionaryRef __nullable */ IntPtr pixelBufferAttributes,
/* CVPixelBufferRef __nullable * __nonnull */ out IntPtr pixelBufferOut);
/* CVPixelBufferRef __nullable * __nonnull */ IntPtr* pixelBufferOut);

public CVPixelBuffer (nint width, nint height, CVPixelFormatType pixelFormat)
: this (width, height, pixelFormat, (NSDictionary?) null)
Expand All @@ -65,7 +66,11 @@ static IntPtr Create (nint width, nint height, CVPixelFormatType pixelFormatType
if (height <= 0)
throw new ArgumentOutOfRangeException (nameof (height));

var ret = CVPixelBufferCreate (IntPtr.Zero, width, height, pixelFormatType, pixelBufferAttributes.GetHandle (), out var handle);
CVReturn ret;
IntPtr handle;
unsafe {
ret = CVPixelBufferCreate (IntPtr.Zero, width, height, pixelFormatType, pixelBufferAttributes.GetHandle (), &handle);
}

if (ret != CVReturn.Success)
throw new ArgumentException (ret.ToString ());
Expand All @@ -80,22 +85,20 @@ static IntPtr Create (nint width, nint height, CVPixelFormatType pixelFormatType
}

[DllImport (Constants.CoreVideoLibrary)]
extern static CVReturn CVPixelBufferCreateResolvedAttributesDictionary (
unsafe extern static CVReturn CVPixelBufferCreateResolvedAttributesDictionary (
/* CFAllocatorRef __nullable */ IntPtr allocator,
/* CFArrayRef __nullable */ IntPtr attributes,
/* CFDictionaryRef __nullable * __nonnull */ out IntPtr resolvedDictionaryOut);
/* CFDictionaryRef __nullable * __nonnull */ IntPtr* resolvedDictionaryOut);

public NSDictionary? GetAttributes (NSDictionary []? attributes)
{
CVReturn ret;
IntPtr resolvedDictionaryOut;
if (attributes is null) {
ret = CVPixelBufferCreateResolvedAttributesDictionary (IntPtr.Zero, IntPtr.Zero, out resolvedDictionaryOut);
} else {
using (var array = NSArray.FromNSObjects (attributes)) {
ret = CVPixelBufferCreateResolvedAttributesDictionary (IntPtr.Zero, array!.Handle, out resolvedDictionaryOut);
}
var nsarray = NSArray.FromNSObjects (attributes);
unsafe {
ret = CVPixelBufferCreateResolvedAttributesDictionary (IntPtr.Zero, nsarray.GetHandle (), &resolvedDictionaryOut);
}
GC.KeepAlive (nsarray);
if (ret != CVReturn.Success)
throw new ArgumentException (ret.ToString ());
return Runtime.GetNSObject<NSDictionary> (resolvedDictionaryOut);
Expand Down Expand Up @@ -158,7 +161,6 @@ static void ReleaseBytesCallback (IntPtr releaseRefCon, IntPtr baseAddress)
handle.Free ();
}

#if NET
[DllImport (Constants.CoreVideoLibrary)]
static unsafe extern CVReturn CVPixelBufferCreateWithBytes (
/* CFAllocatorRef CV_NULLABLE */ IntPtr allocator,
Expand All @@ -167,24 +169,15 @@ static unsafe extern CVReturn CVPixelBufferCreateWithBytes (
/* OSType */ CVPixelFormatType pixelFormatType,
/* void * CV_NONNULL */ IntPtr baseAddress,
/* size_t */ nint bytesPerRow,
#if NET
delegate* unmanaged<IntPtr, IntPtr, void> releaseCallback,
/* void * CV_NULLABLE */ IntPtr releaseRefCon,
/* CFDictionaryRef CV_NULLABLE */ IntPtr pixelBufferAttributes,
/* CV_RETURNS_RETAINED_PARAMETER CVPixelBufferRef CV_NULLABLE * CV_NONNULL */ out IntPtr pixelBufferOut);// __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_4_0);
#else
[DllImport (Constants.CoreVideoLibrary)]
static extern CVReturn CVPixelBufferCreateWithBytes (
/* CFAllocatorRef CV_NULLABLE */ IntPtr allocator,
/* size_t */ nint width,
/* size_t */ nint height,
/* OSType */ CVPixelFormatType pixelFormatType,
/* void * CV_NONNULL */ IntPtr baseAddress,
/* size_t */ nint bytesPerRow,
CVPixelBufferReleaseBytesCallback /* CV_NULLABLE */ releaseCallback,
#endif
/* void * CV_NULLABLE */ IntPtr releaseRefCon,
/* CFDictionaryRef CV_NULLABLE */ IntPtr pixelBufferAttributes,
/* CV_RETURNS_RETAINED_PARAMETER CVPixelBufferRef CV_NULLABLE * CV_NONNULL */ out IntPtr pixelBufferOut);// __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_4_0);
#endif
/* CV_RETURNS_RETAINED_PARAMETER CVPixelBufferRef CV_NULLABLE * CV_NONNULL */ IntPtr* pixelBufferOut);// __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_4_0);

public static CVPixelBuffer? Create (nint width, nint height, CVPixelFormatType pixelFormatType, byte [] data, nint bytesPerRow, CVPixelBufferAttributes pixelBufferAttributes)
{
CVReturn status;
Expand All @@ -204,13 +197,22 @@ static extern CVReturn CVPixelBufferCreateWithBytes (

gchandle = GCHandle.Alloc (data, GCHandleType.Pinned); // This requires a pinned GCHandle, because unsafe code is scoped to the current block, and the address of the byte array will be used after this function returns.

#if NET
unsafe {
status = CVPixelBufferCreateWithBytes (IntPtr.Zero, width, height, pixelFormatType, gchandle.AddrOfPinnedObject (), bytesPerRow, &ReleaseBytesCallback, GCHandle.ToIntPtr (gchandle), DictionaryContainerHelper.GetHandle (pixelBufferAttributes), out handle);
}
status = CVPixelBufferCreateWithBytes (
IntPtr.Zero,
width, height,
pixelFormatType,
gchandle.AddrOfPinnedObject (),
bytesPerRow,
#if NET
&ReleaseBytesCallback,
#else
status = CVPixelBufferCreateWithBytes (IntPtr.Zero, width, height, pixelFormatType, gchandle.AddrOfPinnedObject (), bytesPerRow, releaseBytesCallback, GCHandle.ToIntPtr (gchandle), DictionaryContainerHelper.GetHandle (pixelBufferAttributes), out handle);
releaseBytesCallback,
#endif
GCHandle.ToIntPtr (gchandle),
DictionaryContainerHelper.GetHandle (pixelBufferAttributes),
&handle);
}

if (status != CVReturn.Success) {
gchandle.Free ();
Expand Down Expand Up @@ -254,7 +256,6 @@ static void ReleasePlanarBytesCallback (IntPtr releaseRefCon, IntPtr dataPtr, ni
ReleasePlanarBytesCallbackImpl (releaseRefCon, dataPtr, dataSize, numberOfPlanes, planeAddresses);
}

#if NET
[DllImport (Constants.CoreVideoLibrary)]
static unsafe extern CVReturn CVPixelBufferCreateWithPlanarBytes (
/* CFAllocatorRef CV_NULLABLE */ IntPtr allocator,
Expand All @@ -264,34 +265,18 @@ static unsafe extern CVReturn CVPixelBufferCreateWithPlanarBytes (
/* void * CV_NULLABLE */ IntPtr dataPtr, /* pass a pointer to a plane descriptor block, or NULL /*
/* size_t */ nint dataSize, /* pass size if planes are contiguous, NULL if not */
/* size_t */ nint numberOfPlanes,
/* void *[] CV_NULLABLE */ IntPtr[] planeBaseAddress,
/* size_t[] */ nint [] planeWidth,
/* size_t[] */ nint [] planeHeight,
/* size_t[] */ nint [] planeBytesPerRow,
/* void *[] CV_NULLABLE */ IntPtr* planeBaseAddress,
/* size_t[] */ nint* planeWidth,
/* size_t[] */ nint* planeHeight,
/* size_t[] */ nint* planeBytesPerRow,
#if NET
delegate* unmanaged<IntPtr, IntPtr, nint, nint, IntPtr, void>/* CV_NULLABLE */ releaseCallback,
/* void * CV_NULLABLE */ IntPtr releaseRefCon,
/* CFDictionaryRef CV_NULLABLE */ IntPtr pixelBufferAttributes,
/* CV_RETURNS_RETAINED_PARAMETER CVPixelBufferRef CV_NULLABLE * CV_NONNULL */ out IntPtr pixelBufferOut); // __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_4_0);

#else
[DllImport (Constants.CoreVideoLibrary)]
static extern CVReturn CVPixelBufferCreateWithPlanarBytes (
/* CFAllocatorRef CV_NULLABLE */ IntPtr allocator,
/* size_t */ nint width,
/* size_t */ nint height,
/* OSType */ CVPixelFormatType pixelFormatType,
/* void * CV_NULLABLE */ IntPtr dataPtr, /* pass a pointer to a plane descriptor block, or NULL /*
/* size_t */ nint dataSize, /* pass size if planes are contiguous, NULL if not */
/* size_t */ nint numberOfPlanes,
/* void *[] CV_NULLABLE */ IntPtr [] planeBaseAddress,
/* size_t[] */ nint [] planeWidth,
/* size_t[] */ nint [] planeHeight,
/* size_t[] */ nint [] planeBytesPerRow,
CVPixelBufferReleasePlanarBytesCallback /* CV_NULLABLE */ releaseCallback,
#endif
/* void * CV_NULLABLE */ IntPtr releaseRefCon,
/* CFDictionaryRef CV_NULLABLE */ IntPtr pixelBufferAttributes,
/* CV_RETURNS_RETAINED_PARAMETER CVPixelBufferRef CV_NULLABLE * CV_NONNULL */ out IntPtr pixelBufferOut); // __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_4_0);
#endif
/* CV_RETURNS_RETAINED_PARAMETER CVPixelBufferRef CV_NULLABLE * CV_NONNULL */ IntPtr* pixelBufferOut); // __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_4_0);

public static CVPixelBuffer? Create (nint width, nint height, CVPixelFormatType pixelFormatType, byte [] [] planes, nint [] planeWidths, nint [] planeHeights, nint [] planeBytesPerRow, CVPixelBufferAttributes pixelBufferAttributes)
{
Expand Down Expand Up @@ -339,21 +324,32 @@ static extern CVReturn CVPixelBufferCreateWithPlanarBytes (
data_handle = GCHandle.Alloc (data);

IntPtr data_handle_ptr = GCHandle.ToIntPtr (data_handle);
#if NET
unsafe {
status = CVPixelBufferCreateWithPlanarBytes (IntPtr.Zero,
width, height, pixelFormatType, IntPtr.Zero, 0,
planeCount, addresses, planeWidths, planeHeights, planeBytesPerRow,
&ReleasePlanarBytesCallback, data_handle_ptr,
DictionaryContainerHelper.GetHandle (pixelBufferAttributes), out handle);
}
fixed (IntPtr* addressesPtr = addresses) {
fixed (nint* planeWidthsPtr = planeWidths) {
fixed (nint* planeHeightsPtr = planeHeights) {
fixed (nint* planeBytesPerRowPtr = planeBytesPerRow) {
status = CVPixelBufferCreateWithPlanarBytes (
IntPtr.Zero,
width, height, pixelFormatType, IntPtr.Zero, 0,
planeCount,
addressesPtr,
planeWidthsPtr,
planeHeightsPtr,
planeBytesPerRowPtr,
#if NET
&ReleasePlanarBytesCallback,
#else
status = CVPixelBufferCreateWithPlanarBytes (IntPtr.Zero,
width, height, pixelFormatType, IntPtr.Zero, 0,
planeCount, addresses, planeWidths, planeHeights, planeBytesPerRow,
releasePlanarBytesCallback, data_handle_ptr,
DictionaryContainerHelper.GetHandle (pixelBufferAttributes), out handle);
releasePlanarBytesCallback,
#endif
data_handle_ptr,
DictionaryContainerHelper.GetHandle (pixelBufferAttributes),
&handle);
}
}
}
}
}

if (status != CVReturn.Success) {
ReleasePlanarBytesCallbackImpl (data_handle_ptr, IntPtr.Zero, 0, 0, IntPtr.Zero);
Expand All @@ -364,15 +360,20 @@ static extern CVReturn CVPixelBufferCreateWithPlanarBytes (
}

[DllImport (Constants.CoreVideoLibrary)]
static extern void CVPixelBufferGetExtendedPixels (/* CVPixelBufferRef __nonnull */ IntPtr pixelBuffer,
/* size_t* */ ref nuint extraColumnsOnLeft, /* size_t* */ ref nuint extraColumnsOnRight,
/* size_t* */ ref nuint extraRowsOnTop, /* size_t* */ ref nuint extraRowsOnBottom);
unsafe static extern void CVPixelBufferGetExtendedPixels (/* CVPixelBufferRef __nonnull */ IntPtr pixelBuffer,
/* size_t* */ nuint* extraColumnsOnLeft, /* size_t* */ nuint* extraColumnsOnRight,
/* size_t* */ nuint* extraRowsOnTop, /* size_t* */ nuint* extraRowsOnBottom);

public void GetExtendedPixels (ref nuint extraColumnsOnLeft, ref nuint extraColumnsOnRight,
ref nuint extraRowsOnTop, ref nuint extraRowsOnBottom)
{
CVPixelBufferGetExtendedPixels (Handle, ref extraColumnsOnLeft, ref extraColumnsOnRight,
ref extraRowsOnTop, ref extraRowsOnBottom);
unsafe {
CVPixelBufferGetExtendedPixels (Handle,
(nuint*) Unsafe.AsPointer<nuint> (ref extraColumnsOnLeft),
(nuint*) Unsafe.AsPointer<nuint> (ref extraColumnsOnRight),
(nuint*) Unsafe.AsPointer<nuint> (ref extraRowsOnTop),
(nuint*) Unsafe.AsPointer<nuint> (ref extraRowsOnBottom));
}
}

[DllImport (Constants.CoreVideoLibrary)]
Expand Down Expand Up @@ -442,12 +443,11 @@ public nint PlaneCount {
}

[DllImport (Constants.CoreVideoLibrary)]
[return: MarshalAs (UnmanagedType.I1)]
extern static /* Boolean */ bool CVPixelBufferIsPlanar (/* CVPixelBufferRef __nonnull */ IntPtr pixelBuffer);
extern static /* Boolean */ byte CVPixelBufferIsPlanar (/* CVPixelBufferRef __nonnull */ IntPtr pixelBuffer);

public bool IsPlanar {
get {
return CVPixelBufferIsPlanar (Handle);
return CVPixelBufferIsPlanar (Handle) != 0;
}
}

Expand Down
18 changes: 10 additions & 8 deletions src/CoreVideo/CVPixelBufferIOSurface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@ public partial class CVPixelBuffer : CVImageBuffer {
[NoWatch]
#endif
[DllImport (Constants.CoreVideoLibrary)]
extern static CVReturn /* IOSurfaceRef */ CVPixelBufferCreateWithIOSurface (
unsafe extern static CVReturn /* IOSurfaceRef */ CVPixelBufferCreateWithIOSurface (
/* CFAllocatorRef CV_NULLABLE */ IntPtr allocator,
/* IOSurfaceRef CV_NONNULL */ IntPtr surface,
/* CFDictionaryRef CV_NULLABLE */ IntPtr pixelBufferAttributes,
/* CVPixelBufferRef CV_NULLABLE * CV_NONNULL */ out IntPtr pixelBufferOut
/* CVPixelBufferRef CV_NULLABLE * CV_NONNULL */ IntPtr* pixelBufferOut
);

#if NET
Expand All @@ -81,12 +81,14 @@ public partial class CVPixelBuffer : CVImageBuffer {
ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (surface));

IntPtr pixelBufferPtr;
result = CVPixelBufferCreateWithIOSurface (
allocator: IntPtr.Zero,
surface: surface.Handle,
pixelBufferAttributes: pixelBufferAttributes?.Dictionary.Handle ?? IntPtr.Zero,
pixelBufferOut: out pixelBufferPtr
);
unsafe {
result = CVPixelBufferCreateWithIOSurface (
allocator: IntPtr.Zero,
surface: surface.Handle,
pixelBufferAttributes: pixelBufferAttributes?.Dictionary.Handle ?? IntPtr.Zero,
pixelBufferOut: &pixelBufferPtr
);
}

if (result != CVReturn.Success)
return null;
Expand Down
29 changes: 20 additions & 9 deletions src/CoreVideo/CVPixelBufferPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,18 @@ public CVPixelBufferPoolSettings? Settings {
}

[DllImport (Constants.CoreVideoLibrary)]
extern static CVReturn CVPixelBufferPoolCreatePixelBuffer (
unsafe extern static CVReturn CVPixelBufferPoolCreatePixelBuffer (
/* CFAllocatorRef __nullable */ IntPtr allocator,
/* CVPixelBufferPoolRef __nonnull */ IntPtr pixelBufferPool,
/* CVPixelBufferRef __nullable * __nonnull */ out IntPtr pixelBufferOut);
/* CVPixelBufferRef __nullable * __nonnull */ IntPtr* pixelBufferOut);

public CVPixelBuffer CreatePixelBuffer ()
{
var ret = CVPixelBufferPoolCreatePixelBuffer (IntPtr.Zero, Handle, out var pixelBufferOut);
CVReturn ret;
IntPtr pixelBufferOut;
unsafe {
ret = CVPixelBufferPoolCreatePixelBuffer (IntPtr.Zero, Handle, &pixelBufferOut);
}

if (ret != CVReturn.Success)
throw new Exception ("CVPixelBufferPoolCreatePixelBuffer returned " + ret.ToString ());
Expand All @@ -109,30 +113,37 @@ public CVPixelBuffer CreatePixelBuffer ()
}

[DllImport (Constants.CoreVideoLibrary)]
extern static CVReturn CVPixelBufferPoolCreatePixelBufferWithAuxAttributes (
unsafe extern static CVReturn CVPixelBufferPoolCreatePixelBufferWithAuxAttributes (
/* CFAllocatorRef __nullable */ IntPtr allocator,
/* CVPixelBufferPoolRef __nonnull */ IntPtr pixelBufferPool,
/* CFDictionaryRef __nullable */ IntPtr auxAttributes,
/* CVPixelBufferRef __nullable * __nonnull */ out IntPtr pixelBufferOut);
/* CVPixelBufferRef __nullable * __nonnull */ IntPtr* pixelBufferOut);

public CVPixelBuffer? CreatePixelBuffer (CVPixelBufferPoolAllocationSettings? allocationSettings, out CVReturn error)
{
error = CVPixelBufferPoolCreatePixelBufferWithAuxAttributes (IntPtr.Zero, Handle, allocationSettings.GetHandle (), out var pb);
IntPtr pb;
unsafe {
error = CVPixelBufferPoolCreatePixelBufferWithAuxAttributes (IntPtr.Zero, Handle, allocationSettings.GetHandle (), &pb);
}
if (error != CVReturn.Success)
return null;

return new CVPixelBuffer (pb, true);
}

[DllImport (Constants.CoreVideoLibrary)]
extern static CVReturn CVPixelBufferPoolCreate (/* CFAllocatorRef __nullable */ IntPtr allocator,
unsafe extern static CVReturn CVPixelBufferPoolCreate (/* CFAllocatorRef __nullable */ IntPtr allocator,
/* CFDictionaryRef __nullable */ IntPtr poolAttributes,
/* CFDictionaryRef __nullable */ IntPtr pixelBufferAttributes,
/* CVPixelBufferPoolRef __nullable * __nonnull */ out IntPtr poolOut);
/* CVPixelBufferPoolRef __nullable * __nonnull */ IntPtr* poolOut);

static IntPtr Create (NSDictionary? poolAttributes, NSDictionary? pixelBufferAttributes)
{
var ret = CVPixelBufferPoolCreate (IntPtr.Zero, poolAttributes.GetHandle (), pixelBufferAttributes.GetHandle (), out var handle);
CVReturn ret;
IntPtr handle;
unsafe {
ret = CVPixelBufferPoolCreate (IntPtr.Zero, poolAttributes.GetHandle (), pixelBufferAttributes.GetHandle (), &handle);
}

if (ret != CVReturn.Success)
throw new Exception ("CVPixelBufferPoolCreate returned " + ret.ToString ());
Expand Down
5 changes: 2 additions & 3 deletions src/CoreVideo/CVPixelFormatType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,7 @@ public static class CVPixelFormatTypeExtensions {
[MacCatalyst (15, 0)]
#endif
[DllImport (Constants.CoreVideoLibrary)]
[return: MarshalAs (UnmanagedType.I1)]
static extern bool CVIsCompressedPixelFormatAvailable (uint pixelFormatType);
static extern byte CVIsCompressedPixelFormatAvailable (uint pixelFormatType);

#if NET
[SupportedOSPlatform ("tvos15.0")]
Expand All @@ -162,7 +161,7 @@ public static class CVPixelFormatTypeExtensions {
[MacCatalyst (15, 0)]
#endif
public static bool IsCompressedPixelFormatAvailable (this CVPixelFormatType type)
=> CVIsCompressedPixelFormatAvailable ((uint) type);
=> CVIsCompressedPixelFormatAvailable ((uint) type) != 0;
}
#endif
}
Loading
Loading