[PATCH 1/3] mfplat: Add MFGetStrideForBitmapInfoHeader().

Nikolay Sivov nsivov at codeweavers.com
Thu Mar 12 10:39:10 CDT 2020


Signed-off-by: Nikolay Sivov <nsivov at 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




More information about the wine-devel mailing list