mfplat: Add a stub for 2D system memory buffer object.
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
36543adbe7
commit
1fb20f67d8
|
@ -24,9 +24,12 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
|
||||
|
||||
#define ALIGN_SIZE(size, alignment) (((size) + (alignment - 1)) & ~((alignment - 1)))
|
||||
|
||||
struct memory_buffer
|
||||
{
|
||||
IMFMediaBuffer IMFMediaBuffer_iface;
|
||||
IMF2DBuffer2 IMF2DBuffer2_iface;
|
||||
LONG refcount;
|
||||
|
||||
BYTE *data;
|
||||
|
@ -59,6 +62,11 @@ static inline struct memory_buffer *impl_from_IMFMediaBuffer(IMFMediaBuffer *ifa
|
|||
return CONTAINING_RECORD(iface, struct memory_buffer, IMFMediaBuffer_iface);
|
||||
}
|
||||
|
||||
static struct memory_buffer *impl_from_IMF2DBuffer2(IMF2DBuffer2 *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, struct memory_buffer, IMF2DBuffer2_iface);
|
||||
}
|
||||
|
||||
static inline struct sample *impl_from_IMFSample(IMFSample *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, struct sample, IMFSample_iface);
|
||||
|
@ -179,7 +187,7 @@ static HRESULT WINAPI memory_buffer_GetMaxLength(IMFMediaBuffer *iface, DWORD *m
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static const IMFMediaBufferVtbl memorybuffervtbl =
|
||||
static const IMFMediaBufferVtbl memory_1d_buffer_vtbl =
|
||||
{
|
||||
memory_buffer_QueryInterface,
|
||||
memory_buffer_AddRef,
|
||||
|
@ -191,28 +199,222 @@ static const IMFMediaBufferVtbl memorybuffervtbl =
|
|||
memory_buffer_GetMaxLength,
|
||||
};
|
||||
|
||||
static HRESULT create_memory_buffer(DWORD max_length, DWORD alignment, IMFMediaBuffer **buffer)
|
||||
static HRESULT WINAPI memory_1d_2d_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 if (IsEqualIID(riid, &IID_IMF2DBuffer2) ||
|
||||
IsEqualIID(riid, &IID_IMF2DBuffer))
|
||||
{
|
||||
*out = &buffer->IMF2DBuffer2_iface;
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN("Unsupported interface %s.\n", debugstr_guid(riid));
|
||||
*out = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
IUnknown_AddRef((IUnknown*)*out);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static const IMFMediaBufferVtbl memory_1d_2d_buffer_vtbl =
|
||||
{
|
||||
memory_1d_2d_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 WINAPI memory_2d_buffer_QueryInterface(IMF2DBuffer2 *iface, REFIID riid, void **obj)
|
||||
{
|
||||
struct memory_buffer *buffer = impl_from_IMF2DBuffer2(iface);
|
||||
return IMFMediaBuffer_QueryInterface(&buffer->IMFMediaBuffer_iface, riid, obj);
|
||||
}
|
||||
|
||||
static ULONG WINAPI memory_2d_buffer_AddRef(IMF2DBuffer2 *iface)
|
||||
{
|
||||
struct memory_buffer *buffer = impl_from_IMF2DBuffer2(iface);
|
||||
return IMFMediaBuffer_AddRef(&buffer->IMFMediaBuffer_iface);
|
||||
}
|
||||
|
||||
static ULONG WINAPI memory_2d_buffer_Release(IMF2DBuffer2 *iface)
|
||||
{
|
||||
struct memory_buffer *buffer = impl_from_IMF2DBuffer2(iface);
|
||||
return IMFMediaBuffer_Release(&buffer->IMFMediaBuffer_iface);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI memory_2d_buffer_Lock2D(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
|
||||
{
|
||||
FIXME("%p, %p, %p.\n", iface, scanline0, pitch);
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI memory_2d_buffer_Unlock2D(IMF2DBuffer2 *iface)
|
||||
{
|
||||
FIXME("%p.\n", iface);
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI memory_2d_buffer_GetScanline0AndPitch(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
|
||||
{
|
||||
FIXME("%p, %p, %p.\n", iface, scanline0, pitch);
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI memory_2d_buffer_IsContiguousFormat(IMF2DBuffer2 *iface, BOOL *is_contiguous)
|
||||
{
|
||||
FIXME("%p, %p.\n", iface, is_contiguous);
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI memory_2d_buffer_GetContiguousLength(IMF2DBuffer2 *iface, DWORD *length)
|
||||
{
|
||||
FIXME("%p, %p.\n", iface, length);
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI memory_2d_buffer_ContiguousCopyTo(IMF2DBuffer2 *iface, BYTE *dest_buffer, DWORD dest_length)
|
||||
{
|
||||
FIXME("%p, %p, %u.\n", iface, dest_buffer, dest_length);
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI memory_2d_buffer_ContiguousCopyFrom(IMF2DBuffer2 *iface, const BYTE *src_buffer, DWORD src_length)
|
||||
{
|
||||
FIXME("%p, %p, %u.\n", iface, src_buffer, src_length);
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI memory_2d_buffer_Lock2DSize(IMF2DBuffer2 *iface, MF2DBuffer_LockFlags flags, BYTE **scanline0,
|
||||
LONG *pitch, BYTE **buffer_start, DWORD *buffer_length)
|
||||
{
|
||||
FIXME("%p, %#x, %p, %p, %p, %p.\n", iface, flags, scanline0, pitch, buffer_start, buffer_length);
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI memory_2d_buffer_Copy2DTo(IMF2DBuffer2 *iface, IMF2DBuffer2 *dest_buffer)
|
||||
{
|
||||
FIXME("%p, %p.\n", iface, dest_buffer);
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static const IMF2DBuffer2Vtbl memory_2d_buffer_vtbl =
|
||||
{
|
||||
memory_2d_buffer_QueryInterface,
|
||||
memory_2d_buffer_AddRef,
|
||||
memory_2d_buffer_Release,
|
||||
memory_2d_buffer_Lock2D,
|
||||
memory_2d_buffer_Unlock2D,
|
||||
memory_2d_buffer_GetScanline0AndPitch,
|
||||
memory_2d_buffer_IsContiguousFormat,
|
||||
memory_2d_buffer_GetContiguousLength,
|
||||
memory_2d_buffer_ContiguousCopyTo,
|
||||
memory_2d_buffer_ContiguousCopyFrom,
|
||||
memory_2d_buffer_Lock2DSize,
|
||||
memory_2d_buffer_Copy2DTo,
|
||||
};
|
||||
|
||||
static HRESULT memory_buffer_init(struct memory_buffer *buffer, DWORD max_length, DWORD alignment,
|
||||
const IMFMediaBufferVtbl *vtbl)
|
||||
{
|
||||
buffer->data = heap_alloc(ALIGN_SIZE(max_length, alignment));
|
||||
if (!buffer->data)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
buffer->IMFMediaBuffer_iface.lpVtbl = vtbl;
|
||||
buffer->refcount = 1;
|
||||
buffer->max_length = max_length;
|
||||
buffer->current_length = 0;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT create_1d_buffer(DWORD max_length, DWORD alignment, IMFMediaBuffer **buffer)
|
||||
{
|
||||
struct memory_buffer *object;
|
||||
HRESULT hr;
|
||||
|
||||
if (!buffer)
|
||||
return E_INVALIDARG;
|
||||
return E_POINTER;
|
||||
|
||||
object = heap_alloc(sizeof(*object));
|
||||
*buffer = NULL;
|
||||
|
||||
object = heap_alloc_zero(sizeof(*object));
|
||||
if (!object)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
object->data = heap_alloc((max_length + alignment) & ~alignment);
|
||||
if (!object->data)
|
||||
hr = memory_buffer_init(object, max_length, alignment, &memory_1d_buffer_vtbl);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
heap_free(object);
|
||||
return E_OUTOFMEMORY;
|
||||
return hr;
|
||||
}
|
||||
|
||||
object->IMFMediaBuffer_iface.lpVtbl = &memorybuffervtbl;
|
||||
object->refcount = 1;
|
||||
object->max_length = max_length;
|
||||
object->current_length = 0;
|
||||
*buffer = &object->IMFMediaBuffer_iface;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT create_2d_buffer(DWORD width, DWORD height, DWORD fourcc, IMFMediaBuffer **buffer)
|
||||
{
|
||||
struct memory_buffer *object;
|
||||
unsigned int bpp, max_length;
|
||||
GUID subtype;
|
||||
HRESULT hr;
|
||||
|
||||
if (!buffer)
|
||||
return E_POINTER;
|
||||
|
||||
*buffer = NULL;
|
||||
|
||||
memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
|
||||
subtype.Data1 = fourcc;
|
||||
|
||||
if (!(bpp = mf_format_get_bpp(&subtype)))
|
||||
return MF_E_INVALIDMEDIATYPE;
|
||||
|
||||
object = heap_alloc_zero(sizeof(*object));
|
||||
if (!object)
|
||||
return E_OUTOFMEMORY;
|
||||
|
||||
switch (fourcc)
|
||||
{
|
||||
case MAKEFOURCC('N','V','1','2'):
|
||||
max_length = ALIGN_SIZE(width * bpp, 64) * height * 3 / 2;
|
||||
break;
|
||||
default:
|
||||
max_length = ALIGN_SIZE(width * bpp, 64) * height;
|
||||
}
|
||||
|
||||
hr = memory_buffer_init(object, max_length, MF_1_BYTE_ALIGNMENT, &memory_1d_2d_buffer_vtbl);
|
||||
object->IMF2DBuffer2_iface.lpVtbl = &memory_2d_buffer_vtbl;
|
||||
if (FAILED(hr))
|
||||
{
|
||||
heap_free(object);
|
||||
return hr;
|
||||
}
|
||||
|
||||
*buffer = &object->IMFMediaBuffer_iface;
|
||||
|
||||
|
@ -226,7 +428,7 @@ 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);
|
||||
return create_1d_buffer(max_length, MF_1_BYTE_ALIGNMENT, buffer);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -236,7 +438,14 @@ HRESULT WINAPI MFCreateAlignedMemoryBuffer(DWORD max_length, DWORD alignment, IM
|
|||
{
|
||||
TRACE("%u, %u, %p.\n", max_length, alignment, buffer);
|
||||
|
||||
return create_memory_buffer(max_length, alignment, buffer);
|
||||
return create_1d_buffer(max_length, alignment, buffer);
|
||||
}
|
||||
|
||||
HRESULT WINAPI MFCreate2DMediaBuffer(DWORD width, DWORD height, DWORD fourcc, BOOL bottom_up, IMFMediaBuffer **buffer)
|
||||
{
|
||||
TRACE("%u, %u, %#x, %d, %p.\n", width, height, fourcc, bottom_up, buffer);
|
||||
|
||||
return create_2d_buffer(width, height, fourcc, buffer);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI sample_QueryInterface(IMFSample *iface, REFIID riid, void **out)
|
||||
|
|
|
@ -1802,6 +1802,12 @@ static unsigned int mf_get_stride_for_format(const struct uncompressed_video_for
|
|||
return (width * format->bytes_per_pixel + format->alignment) & ~format->alignment;
|
||||
}
|
||||
|
||||
unsigned int mf_format_get_bpp(const GUID *subtype)
|
||||
{
|
||||
struct uncompressed_video_format *format = mf_get_video_format(subtype);
|
||||
return format ? format->bytes_per_pixel : 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* MFGetStrideForBitmapInfoHeader (mfplat.@)
|
||||
*/
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
@ stub MFConvertFromFP16Array
|
||||
@ stub MFConvertToFP16Array
|
||||
@ stdcall MFCopyImage(ptr long ptr long long long)
|
||||
@ stdcall MFCreate2DMediaBuffer(long long long long ptr)
|
||||
@ stub MFCreateAMMediaTypeFromMFMediaType
|
||||
@ stdcall MFCreateAlignedMemoryBuffer(long long ptr)
|
||||
@ stdcall MFCreateAsyncResult(ptr ptr ptr ptr)
|
||||
|
|
|
@ -114,6 +114,8 @@ static inline BOOL mf_array_reserve(void **elements, size_t *capacity, size_t co
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
extern unsigned int mf_format_get_bpp(const GUID *subtype) DECLSPEC_HIDDEN;
|
||||
|
||||
static inline const char *debugstr_propvar(const PROPVARIANT *v)
|
||||
{
|
||||
if (!v)
|
||||
|
|
|
@ -93,6 +93,8 @@ static HRESULT (WINAPI *pMFTEnumEx)(GUID category, UINT32 flags, const MFT_REGIS
|
|||
const MFT_REGISTER_TYPE_INFO *output_type, IMFActivate ***activate, UINT32 *count);
|
||||
static HRESULT (WINAPI *pMFGetPlaneSize)(DWORD format, DWORD width, DWORD height, DWORD *size);
|
||||
static HRESULT (WINAPI *pMFGetStrideForBitmapInfoHeader)(DWORD format, DWORD width, LONG *stride);
|
||||
static HRESULT (WINAPI *pMFCreate2DMediaBuffer)(DWORD width, DWORD height, DWORD fourcc, BOOL bottom_up,
|
||||
IMFMediaBuffer **buffer);
|
||||
|
||||
static const WCHAR fileschemeW[] = L"file://";
|
||||
|
||||
|
@ -660,6 +662,7 @@ static void init_functions(void)
|
|||
X(MFAllocateSerialWorkQueue);
|
||||
X(MFAllocateWorkQueueEx);
|
||||
X(MFCopyImage);
|
||||
X(MFCreate2DMediaBuffer);
|
||||
X(MFCreateDXGIDeviceManager);
|
||||
X(MFCreateSourceResolver);
|
||||
X(MFCreateMFByteStreamOnStream);
|
||||
|
@ -1726,6 +1729,9 @@ static void test_system_memory_buffer(void)
|
|||
IMFMediaBuffer_Release(buffer);
|
||||
|
||||
/* Aligned buffer. */
|
||||
hr = MFCreateAlignedMemoryBuffer(16, MF_8_BYTE_ALIGNMENT, NULL);
|
||||
ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = MFCreateAlignedMemoryBuffer(201, MF_8_BYTE_ALIGNMENT, &buffer);
|
||||
ok(hr == S_OK, "Failed to create memory buffer, hr %#x.\n", hr);
|
||||
|
||||
|
@ -4539,6 +4545,48 @@ static void test_MFGetStrideForBitmapInfoHeader(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void test_MFCreate2DMediaBuffer(void)
|
||||
{
|
||||
IMF2DBuffer2 *_2dbuffer2;
|
||||
IMF2DBuffer *_2dbuffer;
|
||||
IMFMediaBuffer *buffer;
|
||||
DWORD length;
|
||||
HRESULT hr;
|
||||
|
||||
if (!pMFCreate2DMediaBuffer)
|
||||
{
|
||||
win_skip("MFCreate2DMediaBuffer() is not available.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
hr = pMFCreate2DMediaBuffer(2, 3, MAKEFOURCC('H','2','6','4'), FALSE, &buffer);
|
||||
ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = pMFCreate2DMediaBuffer(2, 3, MAKEFOURCC('N','V','1','2'), FALSE, NULL);
|
||||
ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
|
||||
|
||||
hr = pMFCreate2DMediaBuffer(2, 3, MAKEFOURCC('N','V','1','2'), FALSE, &buffer);
|
||||
ok(hr == S_OK, "Failed to create a buffer, hr %#x.\n", hr);
|
||||
|
||||
hr = IMFMediaBuffer_GetMaxLength(buffer, &length);
|
||||
ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr);
|
||||
ok(length > 0, "Unexpected length.\n");
|
||||
|
||||
hr = IMFMediaBuffer_QueryInterface(buffer, &IID_IMF2DBuffer, (void **)&_2dbuffer);
|
||||
ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
|
||||
IMF2DBuffer_Release(_2dbuffer);
|
||||
|
||||
hr = IMFMediaBuffer_QueryInterface(buffer, &IID_IMF2DBuffer2, (void **)&_2dbuffer2);
|
||||
ok(hr == S_OK || broken(hr == E_NOINTERFACE), "Failed to get interface, hr %#x.\n", hr);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
IMF2DBuffer2_Release(_2dbuffer2);
|
||||
else
|
||||
win_skip("IMF2DBuffer2 is not supported.\n");
|
||||
|
||||
IMFMediaBuffer_Release(buffer);
|
||||
}
|
||||
|
||||
START_TEST(mfplat)
|
||||
{
|
||||
char **argv;
|
||||
|
@ -4591,6 +4639,7 @@ START_TEST(mfplat)
|
|||
test_MFTRegisterLocal();
|
||||
test_queue_com();
|
||||
test_MFGetStrideForBitmapInfoHeader();
|
||||
test_MFCreate2DMediaBuffer();
|
||||
|
||||
CoUninitialize();
|
||||
}
|
||||
|
|
|
@ -402,6 +402,7 @@ HRESULT WINAPI MFCancelCreateFile(IUnknown *cancel_cookie);
|
|||
HRESULT WINAPI MFCancelWorkItem(MFWORKITEM_KEY key);
|
||||
BOOL WINAPI MFCompareFullToPartialMediaType(IMFMediaType *full_type, IMFMediaType *partial_type);
|
||||
HRESULT WINAPI MFCopyImage(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride, DWORD width, DWORD lines);
|
||||
HRESULT WINAPI MFCreate2DMediaBuffer(DWORD width, DWORD height, DWORD fourcc, BOOL bottom_up, IMFMediaBuffer **buffer);
|
||||
HRESULT WINAPI MFCreateAlignedMemoryBuffer(DWORD max_length, DWORD alignment, IMFMediaBuffer **buffer);
|
||||
HRESULT WINAPI MFCreateAttributes(IMFAttributes **attributes, UINT32 size);
|
||||
HRESULT WINAPI MFCreateAsyncResult(IUnknown *object, IMFAsyncCallback *callback, IUnknown *state, IMFAsyncResult **result);
|
||||
|
|
|
@ -141,6 +141,32 @@ interface IMF2DBuffer : IUnknown
|
|||
HRESULT ContiguousCopyFrom([in, size_is(cbSrcBuffer)] const BYTE *pbSrcBuffer, [in] DWORD cbSrcBuffer);
|
||||
}
|
||||
|
||||
typedef enum _MF2DBuffer_LockFlags
|
||||
{
|
||||
MF2DBuffer_LockFlags_LockTypeMask = 0x1 | 0x2 | 0x3,
|
||||
MF2DBuffer_LockFlags_Read = 0x1,
|
||||
MF2DBuffer_LockFlags_Write = 0x2,
|
||||
MF2DBuffer_LockFlags_ReadWrite = 0x3,
|
||||
MF2DBuffer_LockFlags_ForceDWORD = 0x7fffffff
|
||||
} MF2DBuffer_LockFlags;
|
||||
|
||||
[
|
||||
object,
|
||||
uuid(33ae5ea6-4316-436f-8ddd-d73d22f829ec),
|
||||
local
|
||||
]
|
||||
interface IMF2DBuffer2 : IMF2DBuffer
|
||||
{
|
||||
HRESULT Lock2DSize(
|
||||
[in] MF2DBuffer_LockFlags flags,
|
||||
[out] BYTE **scanline0,
|
||||
[out] LONG *pitch,
|
||||
[out] BYTE **buffer_start,
|
||||
[out] DWORD *buffer_length);
|
||||
|
||||
HRESULT Copy2DTo([in] IMF2DBuffer2 *dest_buffer);
|
||||
}
|
||||
|
||||
[
|
||||
object,
|
||||
uuid(44ae0fa8-ea31-4109-8d2e-4cae4997c555),
|
||||
|
|
Loading…
Reference in New Issue