Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/mfplat/mediatype.c | 120 +++++++++++++++++++++++++++++--------
dlls/mfplat/mfplat.spec | 2 +-
dlls/mfplat/tests/mfplat.c | 73 +++++++++++++++++++++-
include/mfapi.h | 1 +
4 files changed, 166 insertions(+), 30 deletions(-)
diff --git a/dlls/mfplat/mediatype.c b/dlls/mfplat/mediatype.c
index 8378e24196..c3e3133b8f 100644
--- a/dlls/mfplat/mediatype.c
+++ b/dlls/mfplat/mediatype.c
@@ -19,6 +19,7 @@
#define COBJMACROS
#include "mfplat_private.h"
+#include "d3d9types.h"
#include "initguid.h"
#include "ks.h"
@@ -1763,6 +1764,8 @@ struct uncompressed_video_format
{
const GUID *subtype;
unsigned int bytes_per_pixel;
+ unsigned int alignment;
+ BOOL bottom_up;
};
static int __cdecl uncompressed_video_format_compare(const void *a, const void *b)
@@ -1772,33 +1775,57 @@ static int __cdecl uncompressed_video_format_compare(const void *a, const void *
return memcmp(guid, format->subtype, sizeof(*guid));
}
-static HRESULT mf_get_image_size(REFGUID subtype, unsigned int width, unsigned int height, unsigned int *size)
+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_NV12, 1, 0, 0 },
+ { &MFVideoFormat_D16, 2, 3, 0 },
+ { &MFVideoFormat_L16, 2, 3, 0 },
+ { &MFVideoFormat_A16B16G16R16F, 8, 3, 1 },
+};
+
+static struct uncompressed_video_format *mf_get_video_format(const GUID *subtype)
+{
+ return bsearch(subtype, video_formats, ARRAY_SIZE(video_formats), sizeof(*video_formats),
+ uncompressed_video_format_compare);
+}
+
+static unsigned int mf_get_stride_for_format(const struct uncompressed_video_format *format, unsigned int width)
+{
+ return (width * format->bytes_per_pixel + format->alignment) & ~format->alignment;
+}
+
+/***********************************************************************
+ * MFGetStrideForBitmapInfoHeader (mfplat.@)
+ */
+HRESULT WINAPI MFGetStrideForBitmapInfoHeader(DWORD fourcc, DWORD width, LONG *stride)
{
- 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;
+ GUID subtype;
- 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
+ TRACE("%#x, %u, %p.\n", fourcc, width, stride);
+
+ memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
+ subtype.Data1 = fourcc;
+
+ if (!(format = mf_get_video_format(&subtype)))
{
- *size = 0;
+ *stride = 0;
+ return MF_E_INVALIDMEDIATYPE;
}
- return format ? S_OK : E_INVALIDARG;
+ *stride = mf_get_stride_for_format(format, width);
+ if (format->bottom_up)
+ *stride *= -1;
+
+ return S_OK;
}
/***********************************************************************
@@ -1806,24 +1833,65 @@ static HRESULT mf_get_image_size(REFGUID subtype, unsigned int width, unsigned i
*/
HRESULT WINAPI MFCalculateImageSize(REFGUID subtype, UINT32 width, UINT32 height, UINT32 *size)
{
+ struct uncompressed_video_format *format;
+ unsigned int stride;
+
TRACE("%s, %u, %u, %p.\n", debugstr_mf_guid(subtype), width, height, size);
- return mf_get_image_size(subtype, width, height, size);
+ if (!(format = mf_get_video_format(subtype)))
+ {
+ *size = 0;
+ return E_INVALIDARG;
+ }
+
+ switch (subtype->Data1)
+ {
+ case MAKEFOURCC('N','V','1','2'):
+ /* 2 x 2 block, interleaving UV for half the height */
+ *size = ((width + 1) & ~1) * height * 3 / 2;
+ break;
+ case D3DFMT_L8:
+ case D3DFMT_L16:
+ case D3DFMT_D16:
+ *size = width * format->bytes_per_pixel * height;
+ break;
+ default:
+ stride = mf_get_stride_for_format(format, width);
+ *size = stride * height;
+ }
+
+ return S_OK;
}
/***********************************************************************
* MFGetPlaneSize (mfplat.@)
*/
-HRESULT WINAPI MFGetPlaneSize(DWORD format, DWORD width, DWORD height, DWORD *size)
+HRESULT WINAPI MFGetPlaneSize(DWORD fourcc, DWORD width, DWORD height, DWORD *size)
{
+ struct uncompressed_video_format *format;
+ unsigned int stride;
GUID subtype;
- TRACE("%#x, %u, %u, %p.\n", format, width, height, size);
+ TRACE("%#x, %u, %u, %p.\n", fourcc, width, height, size);
memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
- subtype.Data1 = format;
+ subtype.Data1 = fourcc;
+
+ if (!(format = mf_get_video_format(&subtype)))
+ return MF_E_INVALIDMEDIATYPE;
+
+ stride = mf_get_stride_for_format(format, width);
- return mf_get_image_size(&subtype, width, height, size);
+ switch (fourcc)
+ {
+ case MAKEFOURCC('N','V','1','2'):
+ *size = stride * height * 3 / 2;
+ break;
+ default:
+ *size = stride * height;
+ }
+
+ return S_OK;
}
/***********************************************************************
diff --git a/dlls/mfplat/mfplat.spec b/dlls/mfplat/mfplat.spec
index 1e11a1fc2a..338e8f8eff 100644
--- a/dlls/mfplat/mfplat.spec
+++ b/dlls/mfplat/mfplat.spec
@@ -101,7 +101,7 @@
@ stdcall MFGetPluginControl(ptr)
@ stub MFGetPrivateWorkqueues
@ stub MFGetSockaddrFromNumericName
-@ stub MFGetStrideForBitmapInfoHeader
+@ stdcall MFGetStrideForBitmapInfoHeader(long long ptr)
@ stdcall MFGetSystemTime()
@ stdcall MFGetTimerPeriodicity(ptr)
@ stub MFGetUncompressedVideoFormat
diff --git a/dlls/mfplat/tests/mfplat.c b/dlls/mfplat/tests/mfplat.c
index 97108e1478..0fd55c6fa1 100644
--- a/dlls/mfplat/tests/mfplat.c
+++ b/dlls/mfplat/tests/mfplat.c
@@ -92,6 +92,7 @@ static HRESULT (WINAPI *pMFAllocateWorkQueueEx)(MFASYNC_WORKQUEUE_TYPE queue_typ
static HRESULT (WINAPI *pMFTEnumEx)(GUID category, UINT32 flags, const MFT_REGISTER_TYPE_INFO *input_type,
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 const WCHAR fileschemeW[] = L"file://";
@@ -664,6 +665,7 @@ static void init_functions(void)
X(MFCreateMFByteStreamOnStream);
X(MFCreateTransformActivate);
X(MFGetPlaneSize);
+ X(MFGetStrideForBitmapInfoHeader);
X(MFHeapAlloc);
X(MFHeapFree);
X(MFPutWaitingWorkItem);
@@ -3376,6 +3378,7 @@ static void test_MFCalculateImageSize(void)
UINT32 width;
UINT32 height;
UINT32 size;
+ UINT32 plane_size; /* Matches image size when 0. */
}
image_size_tests[] =
{
@@ -3395,6 +3398,13 @@ static void test_MFCalculateImageSize(void)
{ &MFVideoFormat_A2R10G10B10, 1, 1, 4 },
{ &MFVideoFormat_A16B16G16R16F, 3, 5, 120 },
{ &MFVideoFormat_A16B16G16R16F, 1, 1, 8 },
+
+ /* YUV */
+ { &MFVideoFormat_NV12, 1, 3, 9, 4 },
+ { &MFVideoFormat_NV12, 1, 2, 6, 3 },
+ { &MFVideoFormat_NV12, 2, 2, 6, 6 },
+ { &MFVideoFormat_NV12, 3, 2, 12, 9 },
+ { &MFVideoFormat_NV12, 4, 2, 12, 12 },
};
unsigned int i;
UINT32 size;
@@ -3418,15 +3428,17 @@ static void test_MFCalculateImageSize(void)
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);
+ image_size_tests[i].size);
if (pMFGetPlaneSize)
{
+ unsigned int plane_size = image_size_tests[i].plane_size ? image_size_tests[i].plane_size :
+ image_size_tests[i].size;
+
hr = pMFGetPlaneSize(image_size_tests[i].subtype->Data1, image_size_tests[i].width, image_size_tests[i].height,
&size);
ok(hr == S_OK, "%u: failed to get plane size, hr %#x.\n", i, hr);
- ok(size == image_size_tests[i].size, "%u: unexpected plane size %u, expected %u.\n", i, size,
- image_size_tests[i].size);
+ ok(size == plane_size, "%u: unexpected plane size %u, expected %u.\n", i, size, plane_size);
}
}
}
@@ -4473,6 +4485,60 @@ static void test_queue_com_state(const char *name)
ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
}
+static void test_MFGetStrideForBitmapInfoHeader(void)
+{
+ static const struct stride_test
+ {
+ const GUID *subtype;
+ unsigned int width;
+ LONG stride;
+ }
+ stride_tests[] =
+ {
+ { &MFVideoFormat_RGB8, 3, -4 },
+ { &MFVideoFormat_RGB8, 1, -4 },
+ { &MFVideoFormat_RGB555, 3, -8 },
+ { &MFVideoFormat_RGB555, 1, -4 },
+ { &MFVideoFormat_RGB565, 3, -8 },
+ { &MFVideoFormat_RGB565, 1, -4 },
+ { &MFVideoFormat_RGB24, 3, -12 },
+ { &MFVideoFormat_RGB24, 1, -4 },
+ { &MFVideoFormat_RGB32, 3, -12 },
+ { &MFVideoFormat_RGB32, 1, -4 },
+ { &MFVideoFormat_ARGB32, 3, -12 },
+ { &MFVideoFormat_ARGB32, 1, -4 },
+ { &MFVideoFormat_A2R10G10B10, 3, -12 },
+ { &MFVideoFormat_A2R10G10B10, 1, -4 },
+ { &MFVideoFormat_A16B16G16R16F, 3, -24 },
+ { &MFVideoFormat_A16B16G16R16F, 1, -8 },
+
+ /* YUV */
+ { &MFVideoFormat_NV12, 1, 1 },
+ { &MFVideoFormat_NV12, 2, 2 },
+ { &MFVideoFormat_NV12, 3, 3 },
+ };
+ unsigned int i;
+ LONG stride;
+ HRESULT hr;
+
+ if (!pMFGetStrideForBitmapInfoHeader)
+ {
+ win_skip("MFGetStrideForBitmapInfoHeader() is not available.\n");
+ return;
+ }
+
+ hr = pMFGetStrideForBitmapInfoHeader(MAKEFOURCC('H','2','6','4'), 1, &stride);
+ ok(hr == MF_E_INVALIDMEDIATYPE, "Unexpected hr %#x.\n", hr);
+
+ for (i = 0; i < ARRAY_SIZE(stride_tests); ++i)
+ {
+ hr = pMFGetStrideForBitmapInfoHeader(stride_tests[i].subtype->Data1, stride_tests[i].width, &stride);
+ ok(hr == S_OK, "%u: failed to get stride, hr %#x.\n", i, hr);
+ ok(stride == stride_tests[i].stride, "%u: format %s, unexpected stride %d, expected %d.\n", i,
+ wine_dbgstr_an((char *)&stride_tests[i].subtype->Data1, 4), stride, stride_tests[i].stride);
+ }
+}
+
START_TEST(mfplat)
{
char **argv;
@@ -4524,6 +4590,7 @@ START_TEST(mfplat)
test_MFCreateTransformActivate();
test_MFTRegisterLocal();
test_queue_com();
+ test_MFGetStrideForBitmapInfoHeader();
CoUninitialize();
}
diff --git a/include/mfapi.h b/include/mfapi.h
index 38577cfe62..1f01dbe0c8 100644
--- a/include/mfapi.h
+++ b/include/mfapi.h
@@ -421,6 +421,7 @@ void * WINAPI MFHeapAlloc(SIZE_T size, ULONG flags, char *file, int line, EAllo
void WINAPI MFHeapFree(void *ptr);
HRESULT WINAPI MFGetAttributesAsBlob(IMFAttributes *attributes, UINT8 *buffer, UINT size);
HRESULT WINAPI MFGetAttributesAsBlobSize(IMFAttributes *attributes, UINT32 *size);
+HRESULT WINAPI MFGetStrideForBitmapInfoHeader(DWORD format, DWORD width, LONG *stride);
HRESULT WINAPI MFGetPlaneSize(DWORD format, DWORD width, DWORD height, DWORD *size);
HRESULT WINAPI MFGetTimerPeriodicity(DWORD *periodicity);
HRESULT WINAPI MFTEnum(GUID category, UINT32 flags, MFT_REGISTER_TYPE_INFO *input_type,
--
2.25.1