[PATCH 3/5] winegstreamer: Implement H264 decoder GetOutputAvailableType.

Rémi Bernon rbernon at codeweavers.com
Mon Mar 14 06:09:06 CDT 2022


This adds some todo_wine because we were not enumerating any media type
before, and we do now.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/mf/tests/mf.c                |  59 +++++++------
 dlls/winegstreamer/h264_decoder.c | 133 +++++++++++++++++++++++++++++-
 2 files changed, 159 insertions(+), 33 deletions(-)

diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 09efdc0c75f..7e0cb777327 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -106,14 +106,16 @@ struct attribute_desc
     const char *name;
     PROPVARIANT value;
     BOOL ratio;
+    BOOL todo;
+    BOOL todo_value;
 };
 typedef struct attribute_desc media_type_desc[32];
 
-#define ATTR_GUID(k, g)      {.key = &k, .name = #k, {.vt = VT_CLSID, .puuid = (GUID *)&g}}
-#define ATTR_UINT32(k, v)    {.key = &k, .name = #k, {.vt = VT_UI4, .ulVal = v}}
-#define ATTR_BLOB(k, p, n)   {.key = &k, .name = #k, {.vt = VT_VECTOR | VT_UI1, .caub = {.pElems = (void *)p, .cElems = n}}}
-#define ATTR_RATIO(k, n, d)  {.key = &k, .name = #k, {.vt = VT_UI8, .uhVal = {.HighPart = n, .LowPart = d}}, .ratio = TRUE}
-#define ATTR_UINT64(k, v)    {.key = &k, .name = #k, {.vt = VT_UI8, .uhVal = {.QuadPart = v}}}
+#define ATTR_GUID(k, g, ...)      {.key = &k, .name = #k, {.vt = VT_CLSID, .puuid = (GUID *)&g}, __VA_ARGS__ }
+#define ATTR_UINT32(k, v, ...)    {.key = &k, .name = #k, {.vt = VT_UI4, .ulVal = v}, __VA_ARGS__ }
+#define ATTR_BLOB(k, p, n, ...)   {.key = &k, .name = #k, {.vt = VT_VECTOR | VT_UI1, .caub = {.pElems = (void *)p, .cElems = n}}, __VA_ARGS__ }
+#define ATTR_RATIO(k, n, d, ...)  {.key = &k, .name = #k, {.vt = VT_UI8, .uhVal = {.HighPart = n, .LowPart = d}}, .ratio = TRUE, __VA_ARGS__ }
+#define ATTR_UINT64(k, v, ...)    {.key = &k, .name = #k, {.vt = VT_UI8, .uhVal = {.QuadPart = v}}, __VA_ARGS__ }
 
 #define check_media_type(a, b, c) check_attributes_(__LINE__, (IMFAttributes *)a, b, c)
 #define check_attributes(a, b, c) check_attributes_(__LINE__, a, b, c)
@@ -127,6 +129,7 @@ static void check_attributes_(int line, IMFAttributes *attributes, const struct
     for (i = 0; i < limit && desc[i].key; ++i)
     {
         hr = IMFAttributes_GetItem(attributes, desc[i].key, &value);
+        todo_wine_if(desc[i].todo)
         ok_(__FILE__, line)(hr == S_OK, "%s missing, hr %#lx\n", debugstr_a(desc[i].name), hr);
         if (hr != S_OK) continue;
 
@@ -153,6 +156,7 @@ static void check_attributes_(int line, IMFAttributes *attributes, const struct
         }
 
         ret = PropVariantCompareEx(&value, &desc[i].value, 0, 0);
+        todo_wine_if(desc[i].todo_value)
         ok_(__FILE__, line)(ret == 0, "%s mismatch, type %u, value %s\n",
                 debugstr_a(desc[i].name), value.vt, buffer);
     }
@@ -6545,70 +6549,70 @@ static void test_h264_decoder(void)
             ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
             ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
             ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
-            ATTR_RATIO(MF_MT_FRAME_SIZE, 80, 80),
-            ATTR_UINT32(MF_MT_SAMPLE_SIZE, 9600),
-            ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 80),
+            ATTR_RATIO(MF_MT_FRAME_SIZE, 80, 80, .todo_value = TRUE),
+            ATTR_UINT32(MF_MT_SAMPLE_SIZE, 9600, .todo_value = TRUE),
+            ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 80, .todo_value = TRUE),
             /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
             ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
             ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
             ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
-            ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
+            ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16, .todo = TRUE),
         },
         {
             ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
             ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
             ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
             ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
-            ATTR_RATIO(MF_MT_FRAME_SIZE, 80, 80),
-            ATTR_UINT32(MF_MT_SAMPLE_SIZE, 9600),
-            ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 80),
+            ATTR_RATIO(MF_MT_FRAME_SIZE, 80, 80, .todo_value = TRUE),
+            ATTR_UINT32(MF_MT_SAMPLE_SIZE, 9600, .todo_value = TRUE),
+            ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 80, .todo_value = TRUE),
             /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
             ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
             ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
             ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
-            ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
+            ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16, .todo = TRUE),
         },
         {
             ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
             ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
             ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
             ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
-            ATTR_RATIO(MF_MT_FRAME_SIZE, 80, 80),
-            ATTR_UINT32(MF_MT_SAMPLE_SIZE, 9600),
-            ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 80),
+            ATTR_RATIO(MF_MT_FRAME_SIZE, 80, 80, .todo_value = TRUE),
+            ATTR_UINT32(MF_MT_SAMPLE_SIZE, 9600, .todo_value = TRUE),
+            ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 80, .todo_value = TRUE),
             /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
             ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
             ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
             ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
-            ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
+            ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16, .todo = TRUE),
         },
         {
             ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
             ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
             ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
             ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
-            ATTR_RATIO(MF_MT_FRAME_SIZE, 80, 80),
-            ATTR_UINT32(MF_MT_SAMPLE_SIZE, 9600),
-            ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 80),
+            ATTR_RATIO(MF_MT_FRAME_SIZE, 80, 80, .todo_value = TRUE),
+            ATTR_UINT32(MF_MT_SAMPLE_SIZE, 9600, .todo_value = TRUE),
+            ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 80, .todo_value = TRUE),
             /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
             ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
             ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
             ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
-            ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
+            ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16, .todo = TRUE),
         },
         {
             ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
             ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
             ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
             ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
-            ATTR_RATIO(MF_MT_FRAME_SIZE, 80, 80),
-            ATTR_UINT32(MF_MT_SAMPLE_SIZE, 12800),
-            ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 160),
+            ATTR_RATIO(MF_MT_FRAME_SIZE, 80, 80, .todo_value = TRUE),
+            ATTR_UINT32(MF_MT_SAMPLE_SIZE, 12800, .todo_value = TRUE),
+            ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 160, .todo_value = TRUE),
             /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
             ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
             ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
             ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
-            ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
+            ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16, .todo = TRUE),
         },
     };
 
@@ -6651,7 +6655,6 @@ static void test_h264_decoder(void)
     /* no output type is available before an input type is set */
 
     hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
-    todo_wine
     ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
 
     /* setting output media type first doesn't work */
@@ -6755,9 +6758,7 @@ static void test_h264_decoder(void)
         ok(ret == 0, "Release returned %lu\n", ret);
         winetest_pop_context();
     }
-    todo_wine
     ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
-    todo_wine
     ok(i == 5, "%lu output media types\n", i);
 
     /* check required output media type attributes */
@@ -6929,9 +6930,7 @@ static void test_h264_decoder(void)
         ok(ret == 0, "Release returned %lu\n", ret);
         winetest_pop_context();
     }
-    todo_wine
     ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
-    todo_wine
     ok(i == 5, "%lu output media types\n", i);
 
     /* and generate a new one as well in a temporary directory */
diff --git a/dlls/winegstreamer/h264_decoder.c b/dlls/winegstreamer/h264_decoder.c
index 318998d02a3..c84f84ece28 100644
--- a/dlls/winegstreamer/h264_decoder.c
+++ b/dlls/winegstreamer/h264_decoder.c
@@ -33,6 +33,14 @@ static const GUID *const h264_decoder_input_types[] =
     &MFVideoFormat_H264,
     &MFVideoFormat_H264_ES,
 };
+static const GUID *const h264_decoder_output_types[] =
+{
+    &MFVideoFormat_NV12,
+    &MFVideoFormat_YV12,
+    &MFVideoFormat_IYUV,
+    &MFVideoFormat_I420,
+    &MFVideoFormat_YUY2,
+};
 
 struct h264_decoder
 {
@@ -46,6 +54,95 @@ static struct h264_decoder *impl_from_IMFTransform(IMFTransform *iface)
     return CONTAINING_RECORD(iface, struct h264_decoder, IMFTransform_iface);
 }
 
+static HRESULT fill_output_media_type(IMFMediaType *media_type, IMFMediaType *default_type)
+{
+    UINT32 value, width, height;
+    UINT64 ratio;
+    GUID subtype;
+    HRESULT hr;
+
+    if (FAILED(hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &subtype)))
+        return hr;
+
+    if (FAILED(hr = IMFMediaType_GetUINT64(media_type, &MF_MT_FRAME_SIZE, &ratio)))
+    {
+        if (!default_type || FAILED(hr = IMFMediaType_GetUINT64(default_type, &MF_MT_FRAME_SIZE, &ratio)))
+            ratio = (UINT64)1920 << 32 | 1080;
+        if (FAILED(hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ratio)))
+            return hr;
+    }
+    width = ratio >> 32;
+    height = ratio;
+
+    if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_FRAME_RATE, NULL)))
+    {
+        if (!default_type || FAILED(hr = IMFMediaType_GetUINT64(default_type, &MF_MT_FRAME_RATE, &ratio)))
+            ratio = (UINT64)30000 << 32 | 1001;
+        if (FAILED(hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_RATE, ratio)))
+            return hr;
+    }
+
+    if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_PIXEL_ASPECT_RATIO, NULL)))
+    {
+        if (!default_type || FAILED(hr = IMFMediaType_GetUINT64(default_type, &MF_MT_PIXEL_ASPECT_RATIO, &ratio)))
+            ratio = (UINT64)1 << 32 | 1;
+        if (FAILED(hr = IMFMediaType_SetUINT64(media_type, &MF_MT_PIXEL_ASPECT_RATIO, ratio)))
+            return hr;
+    }
+
+    if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_SAMPLE_SIZE, NULL)))
+    {
+        if ((!default_type || FAILED(hr = IMFMediaType_GetUINT32(default_type, &MF_MT_SAMPLE_SIZE, &value))) &&
+                FAILED(hr = MFCalculateImageSize(&subtype, width, height, &value)))
+            return hr;
+        if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_SAMPLE_SIZE, value)))
+            return hr;
+    }
+
+    if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_DEFAULT_STRIDE, NULL)))
+    {
+        if ((!default_type || FAILED(hr = IMFMediaType_GetUINT32(default_type, &MF_MT_DEFAULT_STRIDE, &value))) &&
+                FAILED(hr = MFGetStrideForBitmapInfoHeader(subtype.Data1, width, (LONG *)&value)))
+            return hr;
+        if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_DEFAULT_STRIDE, value)))
+            return hr;
+    }
+
+    if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_INTERLACE_MODE, NULL)))
+    {
+        if (!default_type || FAILED(hr = IMFMediaType_GetUINT32(default_type, &MF_MT_INTERLACE_MODE, &value)))
+            value = MFVideoInterlace_MixedInterlaceOrProgressive;
+        if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_INTERLACE_MODE, value)))
+            return hr;
+    }
+
+    if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, NULL)))
+    {
+        if (!default_type || FAILED(hr = IMFMediaType_GetUINT32(default_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, &value)))
+            value = 1;
+        if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_ALL_SAMPLES_INDEPENDENT, value)))
+            return hr;
+    }
+
+    if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_VIDEO_ROTATION, NULL)))
+    {
+        if (!default_type || FAILED(hr = IMFMediaType_GetUINT32(default_type, &MF_MT_VIDEO_ROTATION, &value)))
+            value = 0;
+        if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_VIDEO_ROTATION, value)))
+            return hr;
+    }
+
+    if (FAILED(hr = IMFMediaType_GetItem(media_type, &MF_MT_FIXED_SIZE_SAMPLES, NULL)))
+    {
+        if (!default_type || FAILED(hr = IMFMediaType_GetUINT32(default_type, &MF_MT_FIXED_SIZE_SAMPLES, &value)))
+            value = 1;
+        if (FAILED(hr = IMFMediaType_SetUINT32(media_type, &MF_MT_FIXED_SIZE_SAMPLES, value)))
+            return hr;
+    }
+
+    return S_OK;
+}
+
 static HRESULT WINAPI transform_QueryInterface(IMFTransform *iface, REFIID iid, void **out)
 {
     struct h264_decoder *decoder = impl_from_IMFTransform(iface);
@@ -168,8 +265,38 @@ static HRESULT WINAPI transform_GetInputAvailableType(IMFTransform *iface, DWORD
 static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWORD id,
         DWORD index, IMFMediaType **type)
 {
-    FIXME("iface %p, id %#lx, index %#lx, type %p stub!\n", iface, id, index, type);
-    return E_NOTIMPL;
+    struct h264_decoder *decoder = impl_from_IMFTransform(iface);
+    IMFMediaType *media_type;
+    const GUID *output_type;
+    HRESULT hr;
+
+    TRACE("iface %p, id %#lx, index %#lx, type %p.\n", iface, id, index, type);
+
+    if (!decoder->input_type)
+        return MF_E_TRANSFORM_TYPE_NOT_SET;
+
+    *type = NULL;
+
+    if (index >= ARRAY_SIZE(h264_decoder_output_types))
+        return MF_E_NO_MORE_TYPES;
+    output_type = h264_decoder_output_types[index];
+
+    if (FAILED(hr = MFCreateMediaType(&media_type)))
+        return hr;
+
+    if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video)))
+        goto done;
+    if (FAILED(hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, output_type)))
+        goto done;
+
+    hr = fill_output_media_type(media_type, NULL);
+
+done:
+    if (SUCCEEDED(hr))
+        IMFMediaType_AddRef((*type = media_type));
+
+    IMFMediaType_Release(media_type);
+    return hr;
 }
 
 static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags)
@@ -182,7 +309,7 @@ static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFM
     TRACE("iface %p, id %#lx, type %p, flags %#lx.\n", iface, id, type, flags);
 
     if (FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_MAJOR_TYPE, &major)) ||
-        FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
+            FAILED(hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &subtype)))
         return E_INVALIDARG;
 
     if (!IsEqualGUID(&major, &MFMediaType_Video))
-- 
2.35.1




More information about the wine-devel mailing list