Skip to content

Instantly share code, notes, and snippets.

@rolfbjarne
Last active Oct 13, 2017
Embed
What would you like to do?
using System;
using System.Runtime.InteropServices;
using CoreVideo;
using ObjCRuntime;
public static class PixelBufferCreate
{
/* CVPixelBufferCreateWithPlanarBytes */
class PlaneData
{
public GCHandle[] dataHandles;
}
delegate void CVPixelBufferReleasePlanarBytesCallback (
/* void* */ IntPtr releaseRefCon,
/* const void*/ IntPtr dataPtr,
/* size_t */ nint dataSize,
/* size_t */ nint numberOfPlanes,
/* const void* */IntPtr planeAddresses);
static CVPixelBufferReleasePlanarBytesCallback releasePlanarBytesCallback = new CVPixelBufferReleasePlanarBytesCallback (ReleasePlanarBytesCallback);
[MonoPInvokeCallbackAttribute (typeof (CVPixelBufferReleasePlanarBytesCallback))]
static void ReleasePlanarBytesCallback (IntPtr releaseRefCon, IntPtr dataPtr, nint dataSize, nint numberOfPlanes, IntPtr planeAddresses)
{
GCHandle handle = GCHandle.FromIntPtr (releaseRefCon);
PlaneData data = (PlaneData) handle.Target;
for (int i = 0; i < data.dataHandles.Length; i++)
data.dataHandles[i].Free ();
handle.Free ();
}
[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,
/* 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);
public static CVPixelBuffer Create (nint width, nint height, CVPixelFormatType pixelFormatType, byte[][] planes, nint[] planeWidths, nint[] planeHeights, nint[] planeBytesPerRow, CVPixelBufferAttributes pixelBufferAttributes)
{
IntPtr handle;
IntPtr[] addresses;
PlaneData data;
GCHandle data_handle;
if (planes == null)
throw new ArgumentNullException (nameof (planes));
if (planeWidths == null)
throw new ArgumentNullException (nameof (planeWidths));
if (planeHeights == null)
throw new ArgumentNullException (nameof (planeHeights));
if (planeBytesPerRow == null)
throw new ArgumentNullException (nameof (planeBytesPerRow));
var planeCount = planes.Length;
if (planeWidths.Length != planeCount)
throw new ArgumentOutOfRangeException (nameof (planeWidths), "The length of planeWidths does not match the number of planes");
if (planeHeights.Length != planeCount)
throw new ArgumentOutOfRangeException (nameof (planeWidths), "The length of planeHeights does not match the number of planes");
if (planeBytesPerRow.Length != planeCount)
throw new ArgumentOutOfRangeException (nameof (planeWidths), "The length of planeBytesPerRow does not match the number of planes");
addresses = new IntPtr [planeCount];
data = new PlaneData ();
data.dataHandles = new GCHandle [planeCount];
for (int i = 0; i < planeCount; i++) {
data.dataHandles[i] = GCHandle.Alloc (planes [i], GCHandleType.Pinned);
addresses[i] = data.dataHandles[i].AddrOfPinnedObject ();
}
data_handle = GCHandle.Alloc (data);
var status = CVPixelBufferCreateWithPlanarBytes (IntPtr.Zero,
width, height, pixelFormatType, IntPtr.Zero, 0,
planeCount, addresses, planeWidths, planeHeights, planeBytesPerRow,
releasePlanarBytesCallback, GCHandle.ToIntPtr (data_handle),
pixelBufferAttributes.Dictionary.Handle, out handle);
if (status != CVReturn.Success) {
data_handle.Free ();
return null;
}
return Runtime.GetINativeObject<CVPixelBuffer> (handle, true);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment