[PATCH 5/5] mfplat: Implement locking methods for 2D memory buffers.
Nikolay Sivov
nsivov at codeweavers.com
Mon Mar 16 04:17:08 CDT 2020
Signed-off-by: Nikolay Sivov <nsivov at 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)
--
2.25.1
More information about the wine-devel
mailing list