[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