Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/mfplat/buffer.c | 229 +++++++++++++++++++++++++++++++---- dlls/mfplat/mediatype.c | 54 +++++---- dlls/mfplat/mfplat_private.h | 2 +- dlls/mfplat/tests/mfplat.c | 193 ++++++++++++++++++++++++++++- 4 files changed, 427 insertions(+), 51 deletions(-)
diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c index b1d353a59b..69633134f5 100644 --- a/dlls/mfplat/buffer.c +++ b/dlls/mfplat/buffer.c @@ -35,6 +35,21 @@ struct memory_buffer BYTE *data; DWORD max_length; DWORD current_length; + + struct + { + BYTE *linear_buffer; + unsigned int plane_size; + + BYTE *scanline0; + unsigned int width; + unsigned int height; + int pitch; + + unsigned int locks; + } _2d; + + CRITICAL_SECTION cs; };
enum sample_prop_flags @@ -113,6 +128,8 @@ static ULONG WINAPI memory_buffer_Release(IMFMediaBuffer *iface)
if (!refcount) { + DeleteCriticalSection(&buffer->cs); + heap_free(buffer->_2d.linear_buffer); heap_free(buffer->data); heap_free(buffer); } @@ -226,13 +243,73 @@ static HRESULT WINAPI memory_1d_2d_buffer_QueryInterface(IMFMediaBuffer *iface, return S_OK; }
+static HRESULT WINAPI memory_1d_2d_buffer_Lock(IMFMediaBuffer *iface, BYTE **data, DWORD *max_length, DWORD *current_length) +{ + struct memory_buffer *buffer = impl_from_IMFMediaBuffer(iface); + HRESULT hr = S_OK; + + TRACE("%p, %p, %p, %p.\n", iface, data, max_length, current_length); + + if (!data) + return E_POINTER; + + /* Allocate linear buffer and return it as a copy of current content. Maximum and current length are + unrelated to 2D buffer maximum allocate length, or maintained current length. */ + + EnterCriticalSection(&buffer->cs); + + if (!buffer->_2d.linear_buffer && buffer->_2d.locks) + hr = MF_E_INVALIDREQUEST; + else if (!buffer->_2d.linear_buffer) + { + if (!(buffer->_2d.linear_buffer = heap_alloc(ALIGN_SIZE(buffer->_2d.plane_size, 64)))) + hr = E_OUTOFMEMORY; + } + + if (SUCCEEDED(hr)) + { + ++buffer->_2d.locks; + *data = buffer->_2d.linear_buffer; + if (max_length) + *max_length = buffer->_2d.plane_size; + if (current_length) + *current_length = buffer->_2d.plane_size; + } + + LeaveCriticalSection(&buffer->cs); + + return hr; +} + +static HRESULT WINAPI memory_1d_2d_buffer_Unlock(IMFMediaBuffer *iface) +{ + struct memory_buffer *buffer = impl_from_IMFMediaBuffer(iface); + + TRACE("%p.\n", iface); + + EnterCriticalSection(&buffer->cs); + + if (buffer->_2d.linear_buffer && !--buffer->_2d.locks) + { + MFCopyImage(buffer->data, buffer->_2d.pitch, buffer->_2d.linear_buffer, buffer->_2d.width, + buffer->_2d.width, buffer->_2d.height); + + heap_free(buffer->_2d.linear_buffer); + buffer->_2d.linear_buffer = NULL; + } + + LeaveCriticalSection(&buffer->cs); + + 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_1d_2d_buffer_Lock, + memory_1d_2d_buffer_Unlock, memory_buffer_GetCurrentLength, memory_buffer_SetCurrentLength, memory_buffer_GetMaxLength, @@ -256,39 +333,117 @@ static ULONG WINAPI memory_2d_buffer_Release(IMF2DBuffer2 *iface) return IMFMediaBuffer_Release(&buffer->IMFMediaBuffer_iface); }
+static HRESULT memory_2d_buffer_lock(struct memory_buffer *buffer, BYTE **scanline0, LONG *pitch, + BYTE **buffer_start, DWORD *buffer_length) +{ + HRESULT hr = S_OK; + + if (buffer->_2d.linear_buffer) + hr = MF_E_UNEXPECTED; + else + { + ++buffer->_2d.locks; + *scanline0 = buffer->data; + *pitch = buffer->_2d.pitch; + if (buffer_start) + *buffer_start = buffer->data; + if (buffer_length) + *buffer_length = buffer->max_length; + } + + return hr; +} + static HRESULT WINAPI memory_2d_buffer_Lock2D(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch) { - FIXME("%p, %p, %p.\n", iface, scanline0, pitch); + struct memory_buffer *buffer = impl_from_IMF2DBuffer2(iface); + HRESULT hr;
- return E_NOTIMPL; + TRACE("%p, %p, %p.\n", iface, scanline0, pitch); + + if (!scanline0 || !pitch) + return E_POINTER; + + EnterCriticalSection(&buffer->cs); + + hr = memory_2d_buffer_lock(buffer, scanline0, pitch, NULL, NULL); + + LeaveCriticalSection(&buffer->cs); + + return hr; }
static HRESULT WINAPI memory_2d_buffer_Unlock2D(IMF2DBuffer2 *iface) { - FIXME("%p.\n", iface); + struct memory_buffer *buffer = impl_from_IMF2DBuffer2(iface); + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p.\n", iface); + + EnterCriticalSection(&buffer->cs); + + if (!buffer->_2d.linear_buffer) + { + if (buffer->_2d.locks) + --buffer->_2d.locks; + else + hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED); + } + + LeaveCriticalSection(&buffer->cs); + + return hr; }
static HRESULT WINAPI memory_2d_buffer_GetScanline0AndPitch(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch) { - FIXME("%p, %p, %p.\n", iface, scanline0, pitch); + struct memory_buffer *buffer = impl_from_IMF2DBuffer2(iface); + HRESULT hr = S_OK;
- return E_NOTIMPL; + TRACE("%p, %p, %p.\n", iface, scanline0, pitch); + + if (!scanline0 || !pitch) + return E_POINTER; + + EnterCriticalSection(&buffer->cs); + + if (buffer->_2d.linear_buffer || !buffer->_2d.locks) + hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED); + else + { + *scanline0 = buffer->_2d.scanline0; + *pitch = buffer->_2d.pitch; + } + + LeaveCriticalSection(&buffer->cs); + + return hr; }
static HRESULT WINAPI memory_2d_buffer_IsContiguousFormat(IMF2DBuffer2 *iface, BOOL *is_contiguous) { - FIXME("%p, %p.\n", iface, is_contiguous); + TRACE("%p, %p.\n", iface, is_contiguous);
- return E_NOTIMPL; + if (!is_contiguous) + return E_POINTER; + + *is_contiguous = FALSE; + + return S_OK; }
static HRESULT WINAPI memory_2d_buffer_GetContiguousLength(IMF2DBuffer2 *iface, DWORD *length) { - FIXME("%p, %p.\n", iface, length); + struct memory_buffer *buffer = impl_from_IMF2DBuffer2(iface);
- return E_NOTIMPL; + TRACE("%p, %p.\n", iface, length); + + if (!length) + return E_POINTER; + + *length = buffer->_2d.plane_size; + + return S_OK; }
static HRESULT WINAPI memory_2d_buffer_ContiguousCopyTo(IMF2DBuffer2 *iface, BYTE *dest_buffer, DWORD dest_length) @@ -308,9 +463,21 @@ static HRESULT WINAPI memory_2d_buffer_ContiguousCopyFrom(IMF2DBuffer2 *iface, c 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); + struct memory_buffer *buffer = impl_from_IMF2DBuffer2(iface); + HRESULT hr;
- return E_NOTIMPL; + TRACE("%p, %#x, %p, %p, %p, %p.\n", iface, flags, scanline0, pitch, buffer_start, buffer_length); + + if (!scanline0 || !pitch || !buffer_start || !buffer_length) + return E_POINTER; + + EnterCriticalSection(&buffer->cs); + + hr = memory_2d_buffer_lock(buffer, scanline0, pitch, buffer_start, buffer_length); + + LeaveCriticalSection(&buffer->cs); + + return hr; }
static HRESULT WINAPI memory_2d_buffer_Copy2DTo(IMF2DBuffer2 *iface, IMF2DBuffer2 *dest_buffer) @@ -347,6 +514,7 @@ static HRESULT memory_buffer_init(struct memory_buffer *buffer, DWORD max_length buffer->refcount = 1; buffer->max_length = max_length; buffer->current_length = 0; + InitializeCriticalSection(&buffer->cs);
return S_OK; } @@ -377,12 +545,14 @@ static HRESULT create_1d_buffer(DWORD max_length, DWORD alignment, IMFMediaBuffe return S_OK; }
-static HRESULT create_2d_buffer(DWORD width, DWORD height, DWORD fourcc, IMFMediaBuffer **buffer) +static HRESULT create_2d_buffer(DWORD width, DWORD height, DWORD fourcc, BOOL bottom_up, IMFMediaBuffer **buffer) { + unsigned int bpp, max_length, plane_size; struct memory_buffer *object; - unsigned int bpp, max_length; GUID subtype; + BOOL is_yuv; HRESULT hr; + int pitch;
if (!buffer) return E_POINTER; @@ -392,30 +562,43 @@ static HRESULT create_2d_buffer(DWORD width, DWORD height, DWORD fourcc, IMFMedi memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype)); subtype.Data1 = fourcc;
- if (!(bpp = mf_format_get_bpp(&subtype))) + if (!(bpp = mf_format_get_bpp(&subtype, &is_yuv))) + return MF_E_INVALIDMEDIATYPE; + + if (is_yuv && bottom_up) return MF_E_INVALIDMEDIATYPE;
+ if (FAILED(hr = MFGetPlaneSize(fourcc, width, height, &plane_size))) + return hr; + object = heap_alloc_zero(sizeof(*object)); if (!object) return E_OUTOFMEMORY;
+ pitch = ALIGN_SIZE(width * bpp, 64); + switch (fourcc) { case MAKEFOURCC('N','V','1','2'): - max_length = ALIGN_SIZE(width * bpp, 64) * height * 3 / 2; + max_length = pitch * height * 3 / 2; break; default: - max_length = ALIGN_SIZE(width * bpp, 64) * height; + max_length = pitch * 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)) + if (FAILED(hr = memory_buffer_init(object, max_length, MF_1_BYTE_ALIGNMENT, &memory_1d_2d_buffer_vtbl))) { heap_free(object); return hr; }
+ object->IMF2DBuffer2_iface.lpVtbl = &memory_2d_buffer_vtbl; + object->_2d.plane_size = plane_size; + object->_2d.width = width * bpp; + object->_2d.height = height; + object->_2d.pitch = bottom_up ? -pitch : pitch; + object->_2d.scanline0 = bottom_up ? object->data + object->_2d.width * (object->_2d.height - 1) : object->data; + *buffer = &object->IMFMediaBuffer_iface;
return S_OK; @@ -445,7 +628,7 @@ HRESULT WINAPI MFCreate2DMediaBuffer(DWORD width, DWORD height, DWORD fourcc, BO { TRACE("%u, %u, %#x, %d, %p.\n", width, height, fourcc, bottom_up, buffer);
- return create_2d_buffer(width, height, fourcc, buffer); + return create_2d_buffer(width, height, fourcc, bottom_up, buffer); }
static unsigned int buffer_get_aligned_length(unsigned int length, unsigned int alignment) diff --git a/dlls/mfplat/mediatype.c b/dlls/mfplat/mediatype.c index d764baf0b9..142ee69cf6 100644 --- a/dlls/mfplat/mediatype.c +++ b/dlls/mfplat/mediatype.c @@ -1768,9 +1768,10 @@ HRESULT WINAPI MFCreatePresentationDescriptor(DWORD count, IMFStreamDescriptor * struct uncompressed_video_format { const GUID *subtype; - unsigned int bytes_per_pixel; - unsigned int alignment; - BOOL bottom_up; + unsigned char bytes_per_pixel; + unsigned char alignment; + unsigned char bottom_up; + unsigned char yuv; };
static int __cdecl uncompressed_video_format_compare(const void *a, const void *b) @@ -1782,24 +1783,24 @@ static int __cdecl uncompressed_video_format_compare(const void *a, const void *
static const struct uncompressed_video_format video_formats[] = { - { &MFVideoFormat_RGB24, 3, 3, 1 }, - { &MFVideoFormat_ARGB32, 4, 3, 1 }, - { &MFVideoFormat_RGB32, 4, 3, 1 }, - { &MFVideoFormat_RGB565, 2, 3, 1 }, - { &MFVideoFormat_RGB555, 2, 3, 1 }, - { &MFVideoFormat_A2R10G10B10, 4, 3, 1 }, - { &MFVideoFormat_RGB8, 1, 3, 1 }, - { &MFVideoFormat_L8, 1, 3, 1 }, - { &MFVideoFormat_AYUV, 4, 3, 0 }, - { &MFVideoFormat_IMC1, 2, 3, 0 }, - { &MFVideoFormat_IMC2, 1, 0, 0 }, - { &MFVideoFormat_IMC3, 2, 3, 0 }, - { &MFVideoFormat_IMC4, 1, 0, 0 }, - { &MFVideoFormat_NV12, 1, 0, 0 }, - { &MFVideoFormat_D16, 2, 3, 0 }, - { &MFVideoFormat_L16, 2, 3, 0 }, - { &MFVideoFormat_YV12, 1, 0, 0 }, - { &MFVideoFormat_A16B16G16R16F, 8, 3, 1 }, + { &MFVideoFormat_RGB24, 3, 3, 1, 0 }, + { &MFVideoFormat_ARGB32, 4, 3, 1, 0 }, + { &MFVideoFormat_RGB32, 4, 3, 1, 0 }, + { &MFVideoFormat_RGB565, 2, 3, 1, 0 }, + { &MFVideoFormat_RGB555, 2, 3, 1, 0 }, + { &MFVideoFormat_A2R10G10B10, 4, 3, 1, 0 }, + { &MFVideoFormat_RGB8, 1, 3, 1, 0 }, + { &MFVideoFormat_L8, 1, 3, 1, 0 }, + { &MFVideoFormat_AYUV, 4, 3, 0, 1 }, + { &MFVideoFormat_IMC1, 2, 3, 0, 1 }, + { &MFVideoFormat_IMC2, 1, 0, 0, 1 }, + { &MFVideoFormat_IMC3, 2, 3, 0, 1 }, + { &MFVideoFormat_IMC4, 1, 0, 0, 1 }, + { &MFVideoFormat_NV12, 1, 0, 0, 1 }, + { &MFVideoFormat_D16, 2, 3, 0, 0 }, + { &MFVideoFormat_L16, 2, 3, 0, 0 }, + { &MFVideoFormat_YV12, 1, 0, 0, 1 }, + { &MFVideoFormat_A16B16G16R16F, 8, 3, 1, 0 }, };
static struct uncompressed_video_format *mf_get_video_format(const GUID *subtype) @@ -1813,10 +1814,17 @@ 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) +unsigned int mf_format_get_bpp(const GUID *subtype, BOOL *is_yuv) { struct uncompressed_video_format *format = mf_get_video_format(subtype); - return format ? format->bytes_per_pixel : 0; + + if (format) + { + *is_yuv = format->yuv; + return format->bytes_per_pixel; + } + + return 0; }
/*********************************************************************** diff --git a/dlls/mfplat/mfplat_private.h b/dlls/mfplat/mfplat_private.h index d68a8ed550..0c374f116b 100644 --- a/dlls/mfplat/mfplat_private.h +++ b/dlls/mfplat/mfplat_private.h @@ -114,7 +114,7 @@ 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; +extern unsigned int mf_format_get_bpp(const GUID *subtype, BOOL *is_yuv) DECLSPEC_HIDDEN;
static inline const char *debugstr_propvar(const PROPVARIANT *v) { diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 621b5b4393..bf63337b60 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -41,6 +41,7 @@ #define D3D11_INIT_GUID #include "initguid.h" #include "d3d11_4.h" +#include "d3d9types.h"
DEFINE_GUID(DUMMY_CLSID, 0x12345678,0x1234,0x1234,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19); DEFINE_GUID(DUMMY_GUID1, 0x12345678,0x1234,0x1234,0x21,0x21,0x21,0x21,0x21,0x21,0x21,0x21); @@ -4599,11 +4600,31 @@ static void test_MFGetStrideForBitmapInfoHeader(void)
static void test_MFCreate2DMediaBuffer(void) { + static const struct _2d_buffer_test + { + unsigned int width; + unsigned int height; + unsigned int fourcc; + unsigned int contiguous_length; + } _2d_buffer_tests[] = + { + { 2, 2, MAKEFOURCC('N','V','1','2'), 6 }, + { 4, 2, MAKEFOURCC('N','V','1','2'), 12 }, + { 2, 4, MAKEFOURCC('N','V','1','2'), 12 }, + { 1, 3, MAKEFOURCC('N','V','1','2'), 4 }, + + { 2, 4, D3DFMT_A8R8G8B8, 32 }, + { 1, 4, D3DFMT_A8R8G8B8, 16 }, + { 4, 1, D3DFMT_A8R8G8B8, 16 }, + }; + unsigned int max_length, length, length2; + BYTE *buffer_start, *data, *data2; IMF2DBuffer2 *_2dbuffer2; IMF2DBuffer *_2dbuffer; IMFMediaBuffer *buffer; - DWORD length; + int i, pitch; HRESULT hr; + BOOL ret;
if (!pMFCreate2DMediaBuffer) { @@ -4617,26 +4638,190 @@ static void test_MFCreate2DMediaBuffer(void) hr = pMFCreate2DMediaBuffer(2, 3, MAKEFOURCC('N','V','1','2'), FALSE, NULL); ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
+ /* YUV formats can't be bottom-up. */ + hr = pMFCreate2DMediaBuffer(2, 3, MAKEFOURCC('N','V','1','2'), TRUE, &buffer); + ok(hr == MF_E_INVALIDMEDIATYPE, "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); + /* Full backing buffer size, with 64 bytes per row alignment. */ + hr = IMFMediaBuffer_GetMaxLength(buffer, &max_length); ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr); - ok(length > 0, "Unexpected length.\n"); + ok(max_length > 0, "Unexpected length %u.\n", max_length); + + hr = IMFMediaBuffer_GetCurrentLength(buffer, &length); + ok(hr == S_OK, "Failed to get current length, hr %#x.\n", hr); + ok(!length, "Unexpected length.\n"); + + hr = IMFMediaBuffer_SetCurrentLength(buffer, 10); + ok(hr == S_OK, "Failed to set current length, hr %#x.\n", hr); + + hr = IMFMediaBuffer_GetCurrentLength(buffer, &length); + ok(hr == S_OK, "Failed to get current length, hr %#x.\n", hr); + ok(length == 10, "Unexpected length.\n"); + + /* Linear lock/unlock. */ + + hr = IMFMediaBuffer_Lock(buffer, NULL, &max_length, &length); + ok(FAILED(hr), "Unexpected hr %#x.\n", hr); + + /* Linear locking call returns plane size.*/ + hr = IMFMediaBuffer_Lock(buffer, &data, &max_length, &length); + ok(hr == S_OK, "Failed to lock buffer, hr %#x.\n", hr); + ok(max_length == length, "Unexpected length.\n"); + + length = 0; + pMFGetPlaneSize(MAKEFOURCC('N','V','1','2'), 2, 3, &length); + ok(max_length == length && length == 9, "Unexpected length %u.\n", length); + + /* Already locked */ + hr = IMFMediaBuffer_Lock(buffer, &data2, NULL, NULL); + ok(hr == S_OK, "Failed to lock buffer, hr %#x.\n", hr); + ok(data2 == data, "Unexpected pointer.\n"); + + hr = IMFMediaBuffer_Unlock(buffer); + ok(hr == S_OK, "Failed to unlock buffer, hr %#x.\n", hr);
hr = IMFMediaBuffer_QueryInterface(buffer, &IID_IMF2DBuffer, (void **)&_2dbuffer); ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr); - IMF2DBuffer_Release(_2dbuffer); + + hr = IMF2DBuffer_GetContiguousLength(_2dbuffer, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = IMF2DBuffer_GetContiguousLength(_2dbuffer, &length); + ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr); + ok(length == 9, "Unexpected length %u.\n", length); + + hr = IMF2DBuffer_IsContiguousFormat(_2dbuffer, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + /* 2D lock. */ + hr = IMF2DBuffer_Lock2D(_2dbuffer, &data, &pitch); + ok(hr == MF_E_UNEXPECTED, "Unexpected hr %#x.\n", hr); + + hr = IMF2DBuffer_GetScanline0AndPitch(_2dbuffer, &data, &pitch); + ok(hr == HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED), "Unexpected hr %#x.\n", hr); + + hr = IMFMediaBuffer_Unlock(buffer); + ok(hr == S_OK, "Failed to unlock buffer, hr %#x.\n", hr); + + hr = IMF2DBuffer_GetScanline0AndPitch(_2dbuffer, &data, &pitch); + ok(hr == HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED), "Unexpected hr %#x.\n", hr); + + hr = IMF2DBuffer_Lock2D(_2dbuffer, NULL, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = IMF2DBuffer_Lock2D(_2dbuffer, &data, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = IMF2DBuffer_Lock2D(_2dbuffer, NULL, &pitch); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = IMF2DBuffer_Lock2D(_2dbuffer, &data, &pitch); + ok(hr == S_OK, "Failed to lock buffer, hr %#x.\n", hr); + ok(!!data, "Expected data pointer.\n"); + ok(pitch == 64, "Unexpected pitch %d.\n", pitch); + + hr = IMF2DBuffer_Lock2D(_2dbuffer, &data2, &pitch); + ok(hr == S_OK, "Failed to lock buffer, hr %#x.\n", hr); + ok(data == data2, "Expected data pointer.\n"); + + hr = IMF2DBuffer_GetScanline0AndPitch(_2dbuffer, NULL, &pitch); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = IMF2DBuffer_GetScanline0AndPitch(_2dbuffer, &data, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + /* Active 2D lock */ + hr = IMFMediaBuffer_Lock(buffer, &data2, NULL, NULL); + ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#x.\n", hr); + + hr = IMF2DBuffer_Unlock2D(_2dbuffer); + ok(hr == S_OK, "Failed to unlock buffer, hr %#x.\n", hr); + + hr = IMFMediaBuffer_Lock(buffer, &data2, NULL, NULL); + ok(hr == MF_E_INVALIDREQUEST, "Unexpected hr %#x.\n", hr); + + hr = IMF2DBuffer_Unlock2D(_2dbuffer); + ok(hr == S_OK, "Failed to unlock buffer, hr %#x.\n", hr); + + hr = IMF2DBuffer_Unlock2D(_2dbuffer); + ok(hr == HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED), "Unexpected hr %#x.\n", hr);
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)) + { + hr = IMF2DBuffer_Lock2D(_2dbuffer, &data, &pitch); + ok(hr == S_OK, "Failed to lock buffer, hr %#x.\n", hr); + + hr = IMF2DBuffer2_Lock2DSize(_2dbuffer2, MF2DBuffer_LockFlags_Read, &data2, &pitch, &buffer_start, &length); + ok(hr == S_OK, "Failed to lock buffer, hr %#x.\n", hr); + + hr = IMF2DBuffer_Unlock2D(_2dbuffer); + ok(hr == S_OK, "Failed to unlock buffer, hr %#x.\n", hr); + + hr = IMF2DBuffer_Unlock2D(_2dbuffer); + ok(hr == S_OK, "Failed to unlock buffer, hr %#x.\n", hr); + + /* Flags are ignored. */ + hr = IMF2DBuffer2_Lock2DSize(_2dbuffer2, MF2DBuffer_LockFlags_Read, &data2, &pitch, &buffer_start, &length); + ok(hr == S_OK, "Failed to lock buffer, hr %#x.\n", hr); + + hr = IMF2DBuffer2_Lock2DSize(_2dbuffer2, MF2DBuffer_LockFlags_Write, &data2, &pitch, &buffer_start, &length); + ok(hr == S_OK, "Failed to lock buffer, hr %#x.\n", hr); + + hr = IMF2DBuffer_Unlock2D(_2dbuffer); + ok(hr == S_OK, "Failed to unlock buffer, hr %#x.\n", hr); + + hr = IMF2DBuffer_Unlock2D(_2dbuffer); + ok(hr == S_OK, "Failed to unlock buffer, hr %#x.\n", hr); + + hr = IMF2DBuffer2_Lock2DSize(_2dbuffer2, MF2DBuffer_LockFlags_Write, &data2, &pitch, NULL, &length); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + + hr = IMF2DBuffer2_Lock2DSize(_2dbuffer2, MF2DBuffer_LockFlags_Write, &data2, &pitch, &buffer_start, NULL); + ok(hr == E_POINTER, "Unexpected hr %#x.\n", hr); + IMF2DBuffer2_Release(_2dbuffer2); + } else win_skip("IMF2DBuffer2 is not supported.\n");
+ IMF2DBuffer_Release(_2dbuffer); + IMFMediaBuffer_Release(buffer); + + for (i = 0; i < ARRAY_SIZE(_2d_buffer_tests); ++i) + { + const struct _2d_buffer_test *ptr = &_2d_buffer_tests[i]; + + hr = pMFCreate2DMediaBuffer(ptr->width, ptr->height, ptr->fourcc, FALSE, &buffer); + ok(hr == S_OK, "Failed to create a buffer, hr %#x.\n", hr); + + hr = IMFMediaBuffer_QueryInterface(buffer, &IID_IMF2DBuffer, (void **)&_2dbuffer); + ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr); + + hr = IMF2DBuffer_GetContiguousLength(_2dbuffer, &length); + ok(hr == S_OK, "Failed to get length, hr %#x.\n", hr); + ok(length == ptr->contiguous_length, "%d: unexpected contiguous length %u for %u x %u, format %s.\n", + i, length, ptr->width, ptr->height, wine_dbgstr_an((char *)&ptr->fourcc, 4)); + + hr = pMFGetPlaneSize(ptr->fourcc, ptr->width, ptr->height, &length2); + ok(hr == S_OK, "Failed to get plane size, hr %#x.\n", hr); + ok(length2 == length, "%d: contiguous length %u does not match plane size %u.\n", i, length, length2); + + ret = TRUE; + hr = IMF2DBuffer_IsContiguousFormat(_2dbuffer, &ret); + ok(hr == S_OK, "Failed to get format flag, hr %#x.\n", hr); + ok(!ret, "%d: unexpected format flag %d.\n", i, ret); + + IMF2DBuffer_Release(_2dbuffer); + + IMFMediaBuffer_Release(buffer); + } }
static void test_MFCreateMediaBufferFromMediaType(void)