[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:
Родитель
2ae608f8a3
Коммит
dd06fbb672
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче