From 7dff5809efa2587a9427ae648909f5b5d542edde Mon Sep 17 00:00:00 2001 From: Derek Lesho Date: Mon, 7 Jun 2021 19:40:16 +0300 Subject: [PATCH] mfplat: Copy all image planes in buffer copies. Signed-off-by: Derek Lesho Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/mfplat/buffer.c | 57 ++++++++++++++++++++++++++++++++++---- dlls/mfplat/tests/mfplat.c | 42 +++++++++++++++++++++++++++- 2 files changed, 92 insertions(+), 7 deletions(-) diff --git a/dlls/mfplat/buffer.c b/dlls/mfplat/buffer.c index df11c8fd408..adb53c7dfe7 100644 --- a/dlls/mfplat/buffer.c +++ b/dlls/mfplat/buffer.c @@ -32,6 +32,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat); #define ALIGN_SIZE(size, alignment) (((size) + (alignment)) & ~((alignment))) +typedef void (*p_copy_image_func)(BYTE *dest, LONG dest_stride, const BYTE *src, LONG src_stride, DWORD width, DWORD lines); + struct buffer { IMFMediaBuffer IMFMediaBuffer_iface; @@ -53,8 +55,8 @@ struct buffer unsigned int width; unsigned int height; int pitch; - unsigned int locks; + p_copy_image_func copy_image; } _2d; struct { @@ -73,6 +75,35 @@ struct buffer CRITICAL_SECTION cs; }; +static void copy_image(const struct buffer *buffer, BYTE *dest, LONG dest_stride, const BYTE *src, + LONG src_stride, DWORD width, DWORD lines) +{ + MFCopyImage(dest, dest_stride, src, src_stride, width, lines); + + if (buffer->_2d.copy_image) + { + dest += dest_stride * lines; + src += src_stride * lines; + buffer->_2d.copy_image(dest, dest_stride, src, src_stride, width, lines); + } +} + +static void copy_image_nv12(BYTE *dest, LONG dest_stride, const BYTE *src, LONG src_stride, DWORD width, DWORD lines) +{ + MFCopyImage(dest, dest_stride, src, src_stride, width, lines / 2); +} + +static void copy_image_imc1(BYTE *dest, LONG dest_stride, const BYTE *src, LONG src_stride, DWORD width, DWORD lines) +{ + MFCopyImage(dest, dest_stride, src, src_stride, width / 2, lines); +} + +static void copy_image_imc2(BYTE *dest, LONG dest_stride, const BYTE *src, LONG src_stride, DWORD width, DWORD lines) +{ + MFCopyImage(dest, dest_stride, src, src_stride, width / 2, lines / 2); + MFCopyImage(dest + dest_stride / 2, dest_stride, src + src_stride / 2, src_stride, width / 2, lines / 2); +} + static inline struct buffer *impl_from_IMFMediaBuffer(IMFMediaBuffer *iface) { return CONTAINING_RECORD(iface, struct buffer, IMFMediaBuffer_iface); @@ -307,7 +338,7 @@ static HRESULT WINAPI memory_1d_2d_buffer_Unlock(IMFMediaBuffer *iface) if (buffer->_2d.linear_buffer && !--buffer->_2d.locks) { - MFCopyImage(buffer->data, buffer->_2d.pitch, buffer->_2d.linear_buffer, buffer->_2d.width, + copy_image(buffer, buffer->data, buffer->_2d.pitch, buffer->_2d.linear_buffer, buffer->_2d.width, buffer->_2d.width, buffer->_2d.height); free(buffer->_2d.linear_buffer); @@ -357,7 +388,7 @@ static HRESULT WINAPI d3d9_surface_buffer_Lock(IMFMediaBuffer *iface, BYTE **dat hr = IDirect3DSurface9_LockRect(buffer->d3d9_surface.surface, &rect, NULL, 0); if (SUCCEEDED(hr)) { - MFCopyImage(buffer->_2d.linear_buffer, buffer->_2d.width, rect.pBits, rect.Pitch, + copy_image(buffer, buffer->_2d.linear_buffer, buffer->_2d.width, rect.pBits, rect.Pitch, buffer->_2d.width, buffer->_2d.height); IDirect3DSurface9_UnlockRect(buffer->d3d9_surface.surface); } @@ -396,7 +427,7 @@ static HRESULT WINAPI d3d9_surface_buffer_Unlock(IMFMediaBuffer *iface) if (SUCCEEDED(hr = IDirect3DSurface9_LockRect(buffer->d3d9_surface.surface, &rect, NULL, 0))) { - MFCopyImage(rect.pBits, rect.Pitch, buffer->_2d.linear_buffer, buffer->_2d.width, + copy_image(buffer, rect.pBits, rect.Pitch, buffer->_2d.linear_buffer, buffer->_2d.width, buffer->_2d.width, buffer->_2d.height); IDirect3DSurface9_UnlockRect(buffer->d3d9_surface.surface); } @@ -936,7 +967,7 @@ static HRESULT WINAPI dxgi_surface_buffer_Lock(IMFMediaBuffer *iface, BYTE **dat hr = dxgi_surface_buffer_map(buffer); if (SUCCEEDED(hr)) { - MFCopyImage(buffer->_2d.linear_buffer, buffer->_2d.width, buffer->dxgi_surface.map_desc.pData, + copy_image(buffer, buffer->_2d.linear_buffer, buffer->_2d.width, buffer->dxgi_surface.map_desc.pData, buffer->dxgi_surface.map_desc.RowPitch, buffer->_2d.width, buffer->_2d.height); } } @@ -970,7 +1001,7 @@ static HRESULT WINAPI dxgi_surface_buffer_Unlock(IMFMediaBuffer *iface) hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED); else if (!--buffer->_2d.locks) { - MFCopyImage(buffer->dxgi_surface.map_desc.pData, buffer->dxgi_surface.map_desc.RowPitch, + copy_image(buffer, buffer->dxgi_surface.map_desc.pData, buffer->dxgi_surface.map_desc.RowPitch, buffer->_2d.linear_buffer, buffer->_2d.width, buffer->_2d.width, buffer->_2d.height); dxgi_surface_buffer_unmap(buffer); @@ -1262,6 +1293,17 @@ static HRESULT create_1d_buffer(DWORD max_length, DWORD alignment, IMFMediaBuffe return S_OK; } +static p_copy_image_func get_2d_buffer_copy_func(DWORD fourcc) +{ + if (fourcc == MAKEFOURCC('N','V','1','2')) + return copy_image_nv12; + if (fourcc == MAKEFOURCC('I','M','C','1') || fourcc == MAKEFOURCC('I','M','C','3')) + return copy_image_imc1; + if (fourcc == MAKEFOURCC('I','M','C','2') || fourcc == MAKEFOURCC('I','M','C','4')) + return copy_image_imc2; + return NULL; +} + static HRESULT create_2d_buffer(DWORD width, DWORD height, DWORD fourcc, BOOL bottom_up, IMFMediaBuffer **buffer) { unsigned int stride, max_length, plane_size; @@ -1336,6 +1378,7 @@ static HRESULT create_2d_buffer(DWORD width, DWORD height, DWORD fourcc, BOOL bo object->_2d.height = height; object->_2d.pitch = bottom_up ? -pitch : pitch; object->_2d.scanline0 = bottom_up ? object->data + pitch * (object->_2d.height - 1) : object->data; + object->_2d.copy_image = get_2d_buffer_copy_func(fourcc); *buffer = &object->IMFMediaBuffer_iface; @@ -1374,6 +1417,7 @@ static HRESULT create_d3d9_surface_buffer(IUnknown *surface, BOOL bottom_up, IMF object->_2d.width = stride; object->_2d.height = desc.Height; object->max_length = object->_2d.plane_size; + object->_2d.copy_image = get_2d_buffer_copy_func(desc.Format); *buffer = &object->IMFMediaBuffer_iface; @@ -1428,6 +1472,7 @@ static HRESULT create_dxgi_surface_buffer(IUnknown *surface, unsigned int sub_re object->_2d.width = stride; object->_2d.height = desc.Height; object->max_length = object->_2d.plane_size; + object->_2d.copy_image = get_2d_buffer_copy_func(desc.Format); if (FAILED(hr = init_attributes_object(&object->dxgi_surface.attributes, 0))) { diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 7f049aa90bb..89f6a945c8a 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -5496,10 +5496,10 @@ static void test_MFCreate2DMediaBuffer(void) }; unsigned int max_length, length, length2; BYTE *buffer_start, *data, *data2; + int i, j, k, pitch, pitch2, stride; IMF2DBuffer2 *_2dbuffer2; IMF2DBuffer *_2dbuffer; IMFMediaBuffer *buffer; - int i, pitch, pitch2; HRESULT hr; BOOL ret; @@ -5694,6 +5694,8 @@ static void test_MFCreate2DMediaBuffer(void) ok(length2 == ptr->contiguous_length, "%d: unexpected linear buffer length %u for %u x %u, format %s.\n", i, length2, ptr->width, ptr->height, wine_dbgstr_an((char *)&ptr->fourcc, 4)); + memset(data, 0xff, length2); + hr = IMFMediaBuffer_Unlock(buffer); ok(hr == S_OK, "Failed to unlock buffer, hr %#x.\n", hr); @@ -5712,6 +5714,44 @@ static void test_MFCreate2DMediaBuffer(void) ok(data2 == data, "Unexpected data pointer.\n"); ok(pitch == pitch2, "Unexpected pitch.\n"); + /* primary plane */ + for(j = 0; j < ptr->height; j++) + for (k = 0; k < ptr->width; k++) + ok(data[j * pitch + k] == 0xff, "Unexpected byte %02x at test %d row %d column %d.\n", data[j * pitch + k], i, j, k); + + hr = pMFGetStrideForBitmapInfoHeader(ptr->fourcc, ptr->width, &stride); + ok(hr == S_OK, "Failed to get stride, hr %#x.\n", hr); + + /* secondary planes */ + switch (ptr->fourcc) + { + case MAKEFOURCC('I','M','C','1'): + case MAKEFOURCC('I','M','C','3'): + for (j = ptr->height; j < length2 / stride; j++) + for (k = 0; k < ptr->width / 2; k++) + ok(data[j * pitch + k] == 0xff, "Unexpected byte %02x at test %d row %d column %d.\n", data[j * pitch + k], i, j, k); + break; + + case MAKEFOURCC('I','M','C','2'): + case MAKEFOURCC('I','M','C','4'): + for (j = ptr->height; j < length2 / stride; j++) + for (k = 0; k < ptr->width / 2; k++) + ok(data[j * pitch + k] == 0xff, "Unexpected byte %02x at test %d row %d column %d.\n", data[j * pitch + k], i, j, k); + for (j = ptr->height; j < length2 / stride; j++) + for (k = pitch / 2; k < pitch / 2 + ptr->width / 2; k++) + ok(data[j * pitch + k] == 0xff, "Unexpected byte %02x at test %d row %d column %d.\n", data[j * pitch + k], i, j, k); + break; + + case MAKEFOURCC('N','V','1','2'): + for (j = ptr->height; j < length2 / stride; j++) + for (k = 0; k < ptr->width; k++) + ok(data[j * pitch + k] == 0xff, "Unexpected byte %02x at test %d row %d column %d.\n", data[j * pitch + k], i, j, k); + break; + + default: + ; + } + hr = IMF2DBuffer_Unlock2D(_2dbuffer); ok(hr == S_OK, "Failed to unlock buffer, hr %#x.\n", hr);