1
0
mirror of https://github.com/wine-mirror/wine synced 2024-07-05 17:28:47 +00:00
wine/dlls/mfplat/buffer.c

217 lines
5.5 KiB
C
Raw Normal View History

/*
* Copyright 2018 Alistair Leslie-Hughes
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include "mfplat_private.h"
#include "wine/debug.h"
#include "wine/heap.h"
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
struct memory_buffer
{
IMFMediaBuffer IMFMediaBuffer_iface;
LONG refcount;
BYTE *data;
DWORD max_length;
DWORD current_length;
};
static inline struct memory_buffer *impl_from_IMFMediaBuffer(IMFMediaBuffer *iface)
{
return CONTAINING_RECORD(iface, struct memory_buffer, IMFMediaBuffer_iface);
}
static HRESULT WINAPI memory_buffer_QueryInterface(IMFMediaBuffer *iface, REFIID riid, void **out)
{
struct memory_buffer *buffer = impl_from_IMFMediaBuffer(iface);
TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
if (IsEqualIID(riid, &IID_IMFMediaBuffer) ||
IsEqualIID(riid, &IID_IUnknown))
{
*out = &buffer->IMFMediaBuffer_iface;
}
else
{
FIXME("(%s, %p)\n", debugstr_guid(riid), out);
*out = NULL;
return E_NOINTERFACE;
}
IUnknown_AddRef((IUnknown*)*out);
return S_OK;
}
static ULONG WINAPI memory_buffer_AddRef(IMFMediaBuffer *iface)
{
struct memory_buffer *buffer = impl_from_IMFMediaBuffer(iface);
ULONG refcount = InterlockedIncrement(&buffer->refcount);
TRACE("%p, refcount %u.\n", buffer, refcount);
return refcount;
}
static ULONG WINAPI memory_buffer_Release(IMFMediaBuffer *iface)
{
struct memory_buffer *buffer = impl_from_IMFMediaBuffer(iface);
ULONG refcount = InterlockedDecrement(&buffer->refcount);
TRACE("%p, refcount %u.\n", iface, refcount);
if (!refcount)
{
heap_free(buffer->data);
heap_free(buffer);
}
return refcount;
}
static HRESULT WINAPI memory_buffer_Lock(IMFMediaBuffer *iface, BYTE **data, DWORD *max_length, DWORD *current_length)
{
struct memory_buffer *buffer = impl_from_IMFMediaBuffer(iface);
TRACE("%p, %p %p, %p.\n", iface, data, max_length, current_length);
if (!data)
return E_INVALIDARG;
*data = buffer->data;
if (max_length)
*max_length = buffer->max_length;
if (current_length)
*current_length = buffer->current_length;
return S_OK;
}
static HRESULT WINAPI memory_buffer_Unlock(IMFMediaBuffer *iface)
{
TRACE("%p.\n", iface);
return S_OK;
}
static HRESULT WINAPI memory_buffer_GetCurrentLength(IMFMediaBuffer *iface, DWORD *current_length)
{
struct memory_buffer *buffer = impl_from_IMFMediaBuffer(iface);
TRACE("%p.\n", iface);
if (!current_length)
return E_INVALIDARG;
*current_length = buffer->current_length;
return S_OK;
}
static HRESULT WINAPI memory_buffer_SetCurrentLength(IMFMediaBuffer *iface, DWORD current_length)
{
struct memory_buffer *buffer = impl_from_IMFMediaBuffer(iface);
TRACE("%p, %u.\n", iface, current_length);
if (current_length > buffer->max_length)
return E_INVALIDARG;
buffer->current_length = current_length;
return S_OK;
}
static HRESULT WINAPI memory_buffer_GetMaxLength(IMFMediaBuffer *iface, DWORD *max_length)
{
struct memory_buffer *buffer = impl_from_IMFMediaBuffer(iface);
TRACE("%p, %p.\n", iface, max_length);
if (!max_length)
return E_INVALIDARG;
*max_length = buffer->max_length;
return S_OK;
}
static const IMFMediaBufferVtbl memorybuffervtbl =
{
memory_buffer_QueryInterface,
memory_buffer_AddRef,
memory_buffer_Release,
memory_buffer_Lock,
memory_buffer_Unlock,
memory_buffer_GetCurrentLength,
memory_buffer_SetCurrentLength,
memory_buffer_GetMaxLength,
};
static HRESULT create_memory_buffer(DWORD max_length, DWORD alignment, IMFMediaBuffer **buffer)
{
struct memory_buffer *object;
if (!buffer)
return E_INVALIDARG;
object = heap_alloc(sizeof(*object));
if (!object)
return E_OUTOFMEMORY;
object->data = heap_alloc((max_length + alignment) & ~alignment);
if (!object->data)
{
heap_free(object);
return E_OUTOFMEMORY;
}
object->IMFMediaBuffer_iface.lpVtbl = &memorybuffervtbl;
object->refcount = 1;
object->max_length = max_length;
object->current_length = 0;
*buffer = &object->IMFMediaBuffer_iface;
return S_OK;
}
/***********************************************************************
* MFCreateMemoryBuffer (mfplat.@)
*/
HRESULT WINAPI MFCreateMemoryBuffer(DWORD max_length, IMFMediaBuffer **buffer)
{
TRACE("%u, %p.\n", max_length, buffer);
return create_memory_buffer(max_length, MF_1_BYTE_ALIGNMENT, buffer);
}
/***********************************************************************
* MFCreateAlignedMemoryBuffer (mfplat.@)
*/
HRESULT WINAPI MFCreateAlignedMemoryBuffer(DWORD max_length, DWORD alignment, IMFMediaBuffer **buffer)
{
TRACE("%u, %u, %p.\n", max_length, alignment, buffer);
return create_memory_buffer(max_length, alignment, buffer);
}