[CoreMedia] Add convenience byte [] overloads to CMBlockBuffer API (#26)

reference:
https://trello.com/c/RX7BMktQ/591-verify-coremedia-memory-management-of-public-api
This commit is contained in:
Alex Soto 2016-05-04 10:23:26 -05:00 коммит произвёл Sebastien Pouliot
Родитель 2ae608f8a3
Коммит dd06fbb672
2 изменённых файлов: 75 добавлений и 0 удалений

Просмотреть файл

@ -178,9 +178,27 @@ namespace XamCore.CoreMedia {
public CMBlockBufferError CopyDataBytes (nuint offsetToData, nuint dataLength, IntPtr destination)
{
if (Handle == IntPtr.Zero)
throw new ObjectDisposedException ("BlockBuffer");
return CMBlockBufferCopyDataBytes (handle, offsetToData, dataLength, destination);
}
public CMBlockBufferError CopyDataBytes (nuint offsetToData, nuint dataLength, out byte [] destination)
{
if (Handle == IntPtr.Zero)
throw new ObjectDisposedException ("BlockBuffer");
destination = new byte [dataLength];
GCHandle destPinned = GCHandle.Alloc (destination, GCHandleType.Pinned);
IntPtr destPtr = destPinned.AddrOfPinnedObject ();
var error = CMBlockBufferCopyDataBytes (handle, offsetToData, dataLength, destPtr);
if (error != CMBlockBufferError.None)
destination = default (byte []);
destPinned.Free ();
return error;
}
[DllImport(Constants.CoreMediaLibrary)]
extern static /* OSStatus */ CMBlockBufferError CMBlockBufferReplaceDataBytes (
/* void* */ IntPtr sourceBytes,
@ -196,6 +214,21 @@ namespace XamCore.CoreMedia {
return CMBlockBufferReplaceDataBytes (sourceBytes, handle, offsetIntoDestination, dataLength);
}
public CMBlockBufferError ReplaceDataBytes (byte [] sourceBytes, nuint offsetIntoDestination)
{
if (Handle == IntPtr.Zero)
throw new ObjectDisposedException ("BlockBuffer");
if (Handle == IntPtr.Zero)
throw new ArgumentNullException (nameof (sourceBytes));
GCHandle replacePinned = GCHandle.Alloc (sourceBytes, GCHandleType.Pinned);
IntPtr replacePtr = replacePinned.AddrOfPinnedObject ();
var error = ReplaceDataBytes (replacePtr, offsetIntoDestination, (nuint) sourceBytes.Length);
replacePinned.Free ();
return error;
}
[DllImport(Constants.CoreMediaLibrary)]
extern static /* OSStatus */ CMBlockBufferError CMBlockBufferFillDataBytes (
/* char */ byte fillByte,
@ -307,6 +340,15 @@ namespace XamCore.CoreMedia {
return block;
}
public static CMBlockBuffer FromMemoryBlock (byte [] data, nuint offsetToData, CMBlockBufferFlags flags, out CMBlockBufferError error)
{
if (data == null)
throw new ArgumentNullException (nameof (data));
var allocator = new CMManagedArrayBlockAllocator (data);
return FromMemoryBlock (IntPtr.Zero, (uint) data.Length, allocator, offsetToData, (uint) data.Length, flags, out error);
}
[DllImport(Constants.CoreMediaLibrary)]
extern static /* OSStatus */ CMBlockBufferError CMBlockBufferCreateContiguous (
/* CFAllocatorRef */ IntPtr structureAllocator,
@ -381,5 +423,16 @@ namespace XamCore.CoreMedia {
else
return CMBlockBufferAppendMemoryBlock (Handle, memoryBlock, blockLength, blockAllocator, ref customBlockSource.Cblock, offsetToData, dataLength, flags);
}
public CMBlockBufferError AppendMemoryBlock (byte [] data, nuint offsetToData, CMBlockBufferFlags flags)
{
if (Handle == IntPtr.Zero)
throw new ObjectDisposedException ("BlockBuffer");
if (data == null)
throw new ArgumentNullException (nameof (data));
var allocator = new CMManagedArrayBlockAllocator (data);
return AppendMemoryBlock (IntPtr.Zero, (uint) data.Length, allocator, offsetToData, (uint) data.Length, flags);
}
}
}

Просмотреть файл

@ -90,5 +90,27 @@ namespace XamCore.CoreMedia {
gch.Free();
}
}
// This class is used internally by a couple of CMBlockBuffer methods
// that take a managed array as input parameter
internal class CMManagedArrayBlockAllocator : CMCustomBlockAllocator {
GCHandle dataHandle;
public CMManagedArrayBlockAllocator (byte [] data)
{
dataHandle = GCHandle.Alloc (data, GCHandleType.Pinned);
}
public override IntPtr Allocate (nuint sizeInBytes)
{
return dataHandle.AddrOfPinnedObject ();
}
public override void Free (IntPtr doomedMemoryBlock, nuint sizeInBytes)
{
if (dataHandle.IsAllocated)
dataHandle.Free ();
}
}
}