From abcea9a35a89a75bb8eacf0e3ebee626d2b9fad8 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Thu, 21 Mar 2019 10:42:55 +0300 Subject: [PATCH] mfplat: Implement MFCalculateImageSize(). Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- dlls/mfplat/mediatype.c | 47 ++++++++++++++++++++++++++++++++++ dlls/mfplat/mfplat.spec | 2 +- dlls/mfplat/tests/mfplat.c | 52 ++++++++++++++++++++++++++++++++++++++ include/mfapi.h | 21 ++++++++++++--- 4 files changed, 118 insertions(+), 4 deletions(-) diff --git a/dlls/mfplat/mediatype.c b/dlls/mfplat/mediatype.c index 272b1c2c875..4e6fa80f9c5 100644 --- a/dlls/mfplat/mediatype.c +++ b/dlls/mfplat/mediatype.c @@ -1449,3 +1449,50 @@ HRESULT WINAPI MFCreatePresentationDescriptor(DWORD count, IMFStreamDescriptor * return S_OK; } + +struct uncompressed_video_format +{ + const GUID *subtype; + unsigned int bytes_per_pixel; +}; + +static int uncompressed_video_format_compare(const void *a, const void *b) +{ + const GUID *guid = a; + const struct uncompressed_video_format *format = b; + return memcmp(guid, format->subtype, sizeof(*guid)); +} + +/*********************************************************************** + * MFCalculateImageSize (mfplat.@) + */ +HRESULT WINAPI MFCalculateImageSize(REFGUID subtype, UINT32 width, UINT32 height, UINT32 *size) +{ + static const struct uncompressed_video_format video_formats[] = + { + { &MFVideoFormat_RGB24, 3 }, + { &MFVideoFormat_ARGB32, 4 }, + { &MFVideoFormat_RGB32, 4 }, + { &MFVideoFormat_RGB565, 2 }, + { &MFVideoFormat_RGB555, 2 }, + { &MFVideoFormat_A2R10G10B10, 4 }, + { &MFVideoFormat_RGB8, 1 }, + { &MFVideoFormat_A16B16G16R16F, 8 }, + }; + struct uncompressed_video_format *format; + + TRACE("%s, %u, %u, %p.\n", debugstr_guid(subtype), width, height, size); + + format = bsearch(subtype, video_formats, ARRAY_SIZE(video_formats), sizeof(*video_formats), + uncompressed_video_format_compare); + if (format) + { + *size = ((width * format->bytes_per_pixel + 3) & ~3) * height; + } + else + { + *size = 0; + } + + return format ? S_OK : E_INVALIDARG; +} diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec index be5d8b22058..d8ed5f90e5b 100644 --- a/dlls/mfplat/mfplat.spec +++ b/dlls/mfplat/mfplat.spec @@ -26,7 +26,7 @@ @ stub MFBeginUnregisterWorkQueueWithMMCSS @ stub MFBlockThread @ stub MFCalculateBitmapImageSize -@ stub MFCalculateImageSize +@ stdcall MFCalculateImageSize(ptr long long ptr) @ stub MFCancelCreateFile @ stdcall MFCancelWorkItem(int64) @ stub MFCompareFullToPartialMediaType diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c index 9985f591725..b420513e3f7 100644 --- a/dlls/mfplat/tests/mfplat.c +++ b/dlls/mfplat/tests/mfplat.c @@ -2429,6 +2429,57 @@ static void test_stream_descriptor(void) IMFStreamDescriptor_Release(stream_desc); } +static void test_MFCalculateImageSize(void) +{ + static const struct image_size_test + { + const GUID *subtype; + UINT32 width; + UINT32 height; + UINT32 size; + } + image_size_tests[] = + { + { &MFVideoFormat_RGB8, 3, 5, 20 }, + { &MFVideoFormat_RGB8, 1, 1, 4 }, + { &MFVideoFormat_RGB555, 3, 5, 40 }, + { &MFVideoFormat_RGB555, 1, 1, 4 }, + { &MFVideoFormat_RGB565, 3, 5, 40 }, + { &MFVideoFormat_RGB565, 1, 1, 4 }, + { &MFVideoFormat_RGB24, 3, 5, 60 }, + { &MFVideoFormat_RGB24, 1, 1, 4 }, + { &MFVideoFormat_RGB32, 3, 5, 60 }, + { &MFVideoFormat_RGB32, 1, 1, 4 }, + { &MFVideoFormat_ARGB32, 3, 5, 60 }, + { &MFVideoFormat_ARGB32, 1, 1, 4 }, + { &MFVideoFormat_A2R10G10B10, 3, 5, 60 }, + { &MFVideoFormat_A2R10G10B10, 1, 1, 4 }, + { &MFVideoFormat_A16B16G16R16F, 3, 5, 120 }, + { &MFVideoFormat_A16B16G16R16F, 1, 1, 8 }, + }; + unsigned int i; + UINT32 size; + HRESULT hr; + + size = 1; + hr = MFCalculateImageSize(&IID_IUnknown, 1, 1, &size); + ok(hr == E_INVALIDARG || broken(hr == S_OK) /* Vista */, "Unexpected hr %#x.\n", hr); + ok(size == 0, "Unexpected size %u.\n", size); + + for (i = 0; i < ARRAY_SIZE(image_size_tests); ++i) + { + /* Those are supported since Win10. */ + BOOL is_broken = IsEqualGUID(image_size_tests[i].subtype, &MFVideoFormat_A16B16G16R16F) || + IsEqualGUID(image_size_tests[i].subtype, &MFVideoFormat_A2R10G10B10); + + hr = MFCalculateImageSize(image_size_tests[i].subtype, image_size_tests[i].width, + image_size_tests[i].height, &size); + ok(hr == S_OK || (is_broken && hr == E_INVALIDARG), "%u: failed to calculate image size, hr %#x.\n", i, hr); + ok(size == image_size_tests[i].size, "%u: unexpected image size %u, expected %u.\n", i, size, + image_size_tests[i].size); + } +} + START_TEST(mfplat) { CoInitialize(NULL); @@ -2458,6 +2509,7 @@ START_TEST(mfplat) test_system_time_source(); test_MFInvokeCallback(); test_stream_descriptor(); + test_MFCalculateImageSize(); CoUninitialize(); } diff --git a/include/mfapi.h b/include/mfapi.h index b38953c8553..1b8eafa9ad9 100644 --- a/include/mfapi.h +++ b/include/mfapi.h @@ -48,11 +48,25 @@ extern "C" { DEFINE_GUID(name, format, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); #ifndef DIRECT3D_VERSION -#define D3DFMT_X8R8G8B8 22 +#define D3DFMT_R8G8B8 20 +#define D3DFMT_A8R8G8B8 21 +#define D3DFMT_X8R8G8B8 22 +#define D3DFMT_R5G6B5 23 +#define D3DFMT_X1R5G5B5 24 +#define D3DFMT_A2B10G10R10 31 +#define D3DFMT_P8 41 +#define D3DFMT_A16B16G16R16F 113 #endif -DEFINE_MEDIATYPE_GUID(MFVideoFormat_WMV3, MAKEFOURCC('W','M','V','3')); -DEFINE_MEDIATYPE_GUID(MFVideoFormat_RGB32, D3DFMT_X8R8G8B8); +DEFINE_MEDIATYPE_GUID(MFVideoFormat_WMV3, MAKEFOURCC('W','M','V','3')); +DEFINE_MEDIATYPE_GUID(MFVideoFormat_RGB8, D3DFMT_P8); +DEFINE_MEDIATYPE_GUID(MFVideoFormat_RGB555, D3DFMT_X1R5G5B5); +DEFINE_MEDIATYPE_GUID(MFVideoFormat_RGB565, D3DFMT_R5G6B5); +DEFINE_MEDIATYPE_GUID(MFVideoFormat_RGB24, D3DFMT_R8G8B8); +DEFINE_MEDIATYPE_GUID(MFVideoFormat_RGB32, D3DFMT_X8R8G8B8); +DEFINE_MEDIATYPE_GUID(MFVideoFormat_ARGB32, D3DFMT_A8R8G8B8); +DEFINE_MEDIATYPE_GUID(MFVideoFormat_A2R10G10B10, D3DFMT_A2B10G10R10); +DEFINE_MEDIATYPE_GUID(MFVideoFormat_A16B16G16R16F, D3DFMT_A16B16G16R16F); #if defined(__cplusplus) && !defined(CINTERFACE) typedef struct tagMFASYNCRESULT : public IMFAsyncResult { @@ -172,6 +186,7 @@ typedef void (CALLBACK *MFPERIODICCALLBACK)(IUnknown *context); HRESULT WINAPI MFAddPeriodicCallback(MFPERIODICCALLBACK callback, IUnknown *context, DWORD *key); HRESULT WINAPI MFAllocateWorkQueue(DWORD *queue); HRESULT WINAPI MFAllocateWorkQueueEx(MFASYNC_WORKQUEUE_TYPE queue_type, DWORD *queue); +HRESULT WINAPI MFCalculateImageSize(REFGUID subtype, UINT32 width, UINT32 height, UINT32 *size); HRESULT WINAPI MFCancelWorkItem(MFWORKITEM_KEY key); HRESULT WINAPI MFCopyImage(BYTE *dest, LONG deststride, const BYTE *src, LONG srcstride, DWORD width, DWORD lines); HRESULT WINAPI MFCreateAlignedMemoryBuffer(DWORD max_length, DWORD alignment, IMFMediaBuffer **buffer);