In this patch set, GetOutputType() currently fails for NV11 and the following RGB types because MFCalculateImageSize() fails for them. I'll fix MFCalculateImageSize() for them recently (but not in this patch set).
-- v3: winegstreamer: Implement GetOutputType for WMV decoder. mf/tests: Test info headers returned by GetOutputType for WMV decoder. mf/tests: Test GetOutputType for WMV decoder.
From: Ziqing Hui zhui@codeweavers.com
--- dlls/mf/tests/transform.c | 180 +++++++++++++++++++++++++++++--------- 1 file changed, 141 insertions(+), 39 deletions(-)
diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index 09c0e83a7dc..784cb9afd31 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -26,7 +26,7 @@
#include "control.h" #include "d3d9types.h" -#include "dmoreg.h" +#include "dmo.h" #include "mferror.h" #include "mfidl.h" #include "mftransform.h" @@ -1089,13 +1089,89 @@ static void check_dmo_media_type_(int line, DMO_MEDIA_TYPE *media_type, const DM ok_(__FILE__, line)(media_type->lSampleSize == expected->lSampleSize, "Got unexpected lSampleSize %lu, expected %lu.\n", media_type->lSampleSize, expected->lSampleSize); - - ok_(__FILE__, line)(IsEqualGUID(&media_type->formattype, &GUID_NULL), + ok_(__FILE__, line)(IsEqualGUID(&media_type->formattype, &expected->formattype), "Got unexpected formattype %s.\n", debugstr_guid(&media_type->formattype)); ok_(__FILE__, line)(media_type->pUnk == NULL, "Got unexpected pUnk %p.\n", media_type->pUnk); - ok_(__FILE__, line)(media_type->cbFormat == 0, "Got unexpected cbFormat %lu.\n", media_type->cbFormat); - ok_(__FILE__, line)(media_type->pbFormat == NULL, "Got unexpected pbFormat %p.\n", media_type->pbFormat); + ok_(__FILE__, line)(media_type->cbFormat == expected->cbFormat, + "Got unexpected cbFormat %lu, expected %lu.\n", + media_type->cbFormat, expected->cbFormat); +} + +static void check_dmo_get_input_type(IMediaObject *media_object, const DMO_MEDIA_TYPE *expected_type, ULONG count) +{ + DMO_MEDIA_TYPE media_type; + HRESULT hr; + DWORD i; + + hr = IMediaObject_GetInputType(media_object, 1, 0, NULL); + ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetInputType returned unexpected hr %#lx.\n", hr); + hr = IMediaObject_GetInputType(media_object, 1, 0, &media_type); + ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetInputType returned unexpected hr %#lx.\n", hr); + hr = IMediaObject_GetInputType(media_object, 1, count, &media_type); + ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetInputType returned unexpected hr %#lx.\n", hr); + hr = IMediaObject_GetInputType(media_object, 0, count, &media_type); + ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned unexpected hr %#lx.\n", hr); + hr = IMediaObject_GetInputType(media_object, 0, count, NULL); + ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned unexpected hr %#lx.\n", hr); + hr = IMediaObject_GetInputType(media_object, 0, 0xdeadbeef, NULL); + ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned unexpected hr %#lx.\n", hr); + hr = IMediaObject_GetInputType(media_object, 0, count - 1, NULL); + ok(hr == S_OK, "GetInputType returned unexpected hr %#lx.\n", hr); + hr = IMediaObject_GetInputType(media_object, 0, count - 1, &media_type); + ok(hr == S_OK, "GetInputType returned unexpected hr %#lx.\n", hr); + if (hr == S_OK) + MoFreeMediaType(&media_type); + + i = -1; + while (SUCCEEDED(hr = IMediaObject_GetInputType(media_object, 0, ++i, &media_type))) + { + winetest_push_context("in %lu", i); + check_dmo_media_type(&media_type, &expected_type[i]); + MoFreeMediaType(&media_type); + winetest_pop_context(); + } + + ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned unexpected hr %#lx.\n", hr); + ok(i == count, "%lu types.\n", i); +} + +static void check_dmo_get_output_type(IMediaObject *media_object, const DMO_MEDIA_TYPE *expected_type, ULONG count) +{ + DMO_MEDIA_TYPE media_type; + HRESULT hr; + DWORD i; + + hr = IMediaObject_GetOutputType(media_object, 1, 0, NULL); + ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetOutputType returned unexpected hr %#lx.\n", hr); + hr = IMediaObject_GetOutputType(media_object, 1, 0, &media_type); + ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetOutputType returned unexpected hr %#lx.\n", hr); + hr = IMediaObject_GetOutputType(media_object, 1, count, &media_type); + ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetOutputType returned unexpected hr %#lx.\n", hr); + hr = IMediaObject_GetOutputType(media_object, 0, count, &media_type); + ok(hr == DMO_E_NO_MORE_ITEMS, "GetOutputType returned unexpected hr %#lx.\n", hr); + hr = IMediaObject_GetOutputType(media_object, 0, count, NULL); + ok(hr == DMO_E_NO_MORE_ITEMS || broken(hr == S_OK), "GetOutputType returned unexpected hr %#lx.\n", hr); + hr = IMediaObject_GetOutputType(media_object, 0, 0xdeadbeef, NULL); + ok(hr == DMO_E_NO_MORE_ITEMS || broken(hr == S_OK), "GetOutputType returned unexpected hr %#lx.\n", hr); + hr = IMediaObject_GetOutputType(media_object, 0, count - 1, NULL); + ok(hr == S_OK, "GetOutputType returned unexpected hr %#lx.\n", hr); + hr = IMediaObject_GetOutputType(media_object, 0, count - 1, &media_type); + ok(hr == S_OK, "GetOutputType returned unexpected hr %#lx.\n", hr); + if (hr == S_OK) + MoFreeMediaType(&media_type); + + i = -1; + while (SUCCEEDED(hr = IMediaObject_GetOutputType(media_object, 0, ++i, &media_type))) + { + winetest_push_context("out %lu", i); + check_dmo_media_type(&media_type, &expected_type[i]); + MoFreeMediaType(&media_type); + winetest_pop_context(); + } + + ok(hr == DMO_E_NO_MORE_ITEMS, "GetOutputType returned unexpected hr %#lx.\n", hr); + ok(i == count, "%lu types.\n", i); }
static HRESULT WINAPI test_unk_QueryInterface(IUnknown *iface, REFIID riid, void **obj) @@ -4531,15 +4607,31 @@ static void test_wmv_decoder_media_object(void) const GUID *const class_id = &CLSID_CWMVDecMediaObject; const DMO_MEDIA_TYPE expected_input_types[] = { - {MFMediaType_Video, MFVideoFormat_WMV1, FALSE, TRUE, FALSE}, - {MFMediaType_Video, MFVideoFormat_WMV2, FALSE, TRUE, FALSE}, - {MFMediaType_Video, MEDIASUBTYPE_WMVA, FALSE, TRUE, FALSE}, - {MFMediaType_Video, MEDIASUBTYPE_WMVP, FALSE, TRUE, FALSE}, - {MFMediaType_Video, MEDIASUBTYPE_WVP2, FALSE, TRUE, FALSE}, - {MFMediaType_Video, MFVideoFormat_WMV_Unknown, FALSE, TRUE, FALSE}, - {MFMediaType_Video, MFVideoFormat_WVC1, FALSE, TRUE, FALSE}, - {MFMediaType_Video, MFVideoFormat_WMV3, FALSE, TRUE, FALSE}, - {MFMediaType_Video, MFVideoFormat_VC1S, FALSE, TRUE, FALSE}, + {MFMediaType_Video, MEDIASUBTYPE_WMV1, FALSE, TRUE, 0, GUID_NULL, NULL, 0}, + {MFMediaType_Video, MEDIASUBTYPE_WMV2, FALSE, TRUE, 0, GUID_NULL, NULL, 0}, + {MFMediaType_Video, MEDIASUBTYPE_WMVA, FALSE, TRUE, 0, GUID_NULL, NULL, 0}, + {MFMediaType_Video, MEDIASUBTYPE_WMVP, FALSE, TRUE, 0, GUID_NULL, NULL, 0}, + {MFMediaType_Video, MEDIASUBTYPE_WVP2, FALSE, TRUE, 0, GUID_NULL, NULL, 0}, + {MFMediaType_Video, MFVideoFormat_WMV_Unknown, FALSE, TRUE, 0, GUID_NULL, NULL, 0}, + {MFMediaType_Video, MEDIASUBTYPE_WVC1, FALSE, TRUE, 0, GUID_NULL, NULL, 0}, + {MFMediaType_Video, MEDIASUBTYPE_WMV3, FALSE, TRUE, 0, GUID_NULL, NULL, 0}, + {MFMediaType_Video, MFVideoFormat_VC1S, FALSE, TRUE, 0, GUID_NULL, NULL, 0}, + }; + const DMO_MEDIA_TYPE expected_output_types[] = + { + {MFMediaType_Video, MEDIASUBTYPE_NV12, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88}, + {MFMediaType_Video, MEDIASUBTYPE_YV12, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88}, + {MFMediaType_Video, MEDIASUBTYPE_IYUV, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88}, + {MFMediaType_Video, MEDIASUBTYPE_I420, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88}, + {MFMediaType_Video, MEDIASUBTYPE_YUY2, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88}, + {MFMediaType_Video, MEDIASUBTYPE_UYVY, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88}, + {MFMediaType_Video, MEDIASUBTYPE_YVYU, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88}, + {MFMediaType_Video, MEDIASUBTYPE_NV11, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88}, + {MFMediaType_Video, MEDIASUBTYPE_RGB32, TRUE, FALSE, 1024, FORMAT_VideoInfo, NULL, 88}, + {MFMediaType_Video, MEDIASUBTYPE_RGB24, TRUE, FALSE, 768, FORMAT_VideoInfo, NULL, 88}, + {MFMediaType_Video, MEDIASUBTYPE_RGB565, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 100}, + {MFMediaType_Video, MEDIASUBTYPE_RGB555, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88}, + {MFMediaType_Video, MEDIASUBTYPE_RGB8, TRUE, FALSE, 256, FORMAT_VideoInfo, NULL, 1112}, }; const struct set_type_arg { @@ -4622,30 +4714,7 @@ static void test_wmv_decoder_media_object(void) ok(in_count == 0xdeadbeef, "Got unexpected in_count %lu.\n", in_count);
/* Test GetInputType. */ - i = -1; - while (SUCCEEDED(hr = IMediaObject_GetInputType(media_object, 0, ++i, &media_type))) - { - winetest_push_context("in %lu", i); - check_dmo_media_type(&media_type, &expected_input_types[i]); - winetest_pop_context(); - } - ok(i == ARRAY_SIZE(expected_input_types), "%lu input types.\n", i); - - /* Test GetInputType with invalid arguments. */ - hr = IMediaObject_GetInputType(media_object, 0, ARRAY_SIZE(expected_input_types) - 1, &media_type); - ok(hr == S_OK, "GetInputType returned unexpected hr %#lx.\n", hr); - hr = IMediaObject_GetInputType(media_object, 0, ARRAY_SIZE(expected_input_types), &media_type); - ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned unexpected hr %#lx.\n", hr); - hr = IMediaObject_GetInputType(media_object, 1, 0, &media_type); - ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetInputType returned unexpected hr %#lx.\n", hr); - hr = IMediaObject_GetInputType(media_object, 0, 0, NULL); - ok(hr == S_OK, "GetInputType returned unexpected hr %#lx.\n", hr); - hr = IMediaObject_GetInputType(media_object, 1, ARRAY_SIZE(expected_input_types), &media_type); - ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetInputType returned unexpected hr %#lx.\n", hr); - hr = IMediaObject_GetInputType(media_object, 0, ARRAY_SIZE(expected_input_types), NULL); - ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned unexpected hr %#lx.\n", hr); - hr = IMediaObject_GetInputType(media_object, 1, 0, NULL); - ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetInputType returned unexpected hr %#lx.\n", hr); + check_dmo_get_input_type(media_object, expected_input_types, ARRAY_SIZE(expected_input_types));
/* Test SetInputType. */ input_type = (DMO_MEDIA_TYPE *)buffer; @@ -4664,7 +4733,7 @@ static void test_wmv_decoder_media_object(void) continue; }
- winetest_push_context("Input %lu", i); + winetest_push_context("in %lu", i);
/* Test setting the type. */ init_dmo_media_type_video(input_type, subtype, 96, 96); @@ -4804,6 +4873,39 @@ static void test_wmv_decoder_media_object(void) winetest_pop_context(); }
+ /* Test GetOutputType without setting input type. */ + hr = IMediaObject_SetInputType(media_object, 0, NULL, DMO_SET_TYPEF_CLEAR); + ok(hr == S_OK, "SetInputType returned unexpected hr %#lx.\n", hr); + hr = IMediaObject_GetOutputType(media_object, 0, 0, &media_type); + todo_wine + ok(hr == DMO_E_TYPE_NOT_SET, "GetOutputType returned unexpected hr %#lx.\n", hr); + + /* Test GetOutputType after setting input type. */ + for (i = 0; i < ARRAY_SIZE(expected_input_types); ++i) + { + const GUID *subtype = &expected_input_types[i].subtype; + if (IsEqualGUID(subtype, &MEDIASUBTYPE_WMV2) + || IsEqualGUID(subtype, &MEDIASUBTYPE_WMVA) + || IsEqualGUID(subtype, &MEDIASUBTYPE_WVP2) + || IsEqualGUID(subtype, &MEDIASUBTYPE_WVC1) + || IsEqualGUID(subtype, &MFVideoFormat_VC1S)) + { + skip("Skipping GetOutputType tests for input subtype %s.\n", debugstr_guid(subtype)); + continue; + } + + winetest_push_context("in %lu", i); + + init_dmo_media_type_video(input_type, &expected_input_types[i].subtype, 16, 16); + hr = IMediaObject_SetInputType(media_object, 0, input_type, 0); + ok(hr == S_OK, "SetInputType returned unexpected hr %#lx.\n", hr); + + todo_wine + check_dmo_get_output_type(media_object, expected_output_types, ARRAY_SIZE(expected_output_types)); + + winetest_pop_context(); + } + ret = IMediaObject_Release(media_object); ok(ret == 0, "Release returned %lu\n", ret); CoUninitialize();
From: Ziqing Hui zhui@codeweavers.com
--- dlls/mf/tests/transform.c | 114 +++++++++++++++++++++++++++++++++----- 1 file changed, 101 insertions(+), 13 deletions(-)
diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index 784cb9afd31..a2e8d1d6e0b 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -1071,6 +1071,67 @@ DWORD check_mf_sample_collection_(const char *file, int line, IMFCollection *sam return ctx.diff / count; }
+#define check_video_info_header(a, b) check_video_info_header_(__LINE__, a, b) +static void check_video_info_header_(int line, VIDEOINFOHEADER *info, const VIDEOINFOHEADER *expected) +{ + ok_(__FILE__, line)(info->rcSource.left == expected->rcSource.left + && info->rcSource.top == expected->rcSource.top + && info->rcSource.right == expected->rcSource.right + && info->rcSource.bottom == expected->rcSource.bottom, + "Got unexpected rcSource {%ld, %ld, %ld, %ld}, expected {%ld, %ld, %ld, %ld}.\n", + info->rcSource.left, info->rcSource.top, info->rcSource.right, info->rcSource.bottom, + expected->rcSource.left, expected->rcSource.top, expected->rcSource.right, expected->rcSource.bottom); + ok_(__FILE__, line)(info->rcTarget.left == expected->rcTarget.left + && info->rcTarget.top == expected->rcTarget.top + && info->rcTarget.right == expected->rcTarget.right + && info->rcTarget.bottom == expected->rcTarget.bottom, + "Got unexpected rcTarget {%ld, %ld, %ld, %ld}, expected {%ld, %ld, %ld, %ld}.\n", + info->rcTarget.left, info->rcTarget.top, info->rcTarget.right, info->rcTarget.bottom, + expected->rcTarget.left, expected->rcTarget.top, expected->rcTarget.right, expected->rcTarget.bottom); + ok_(__FILE__, line)(info->dwBitRate == expected->dwBitRate, + "Got unexpected dwBitRate %lu, expected %lu.\n", + info->dwBitRate, expected->dwBitRate); + ok_(__FILE__, line)(info->dwBitErrorRate == expected->dwBitErrorRate, + "Got unexpected dwBitErrorRate %lu, expected %lu.\n", + info->dwBitErrorRate, expected->dwBitErrorRate); + ok_(__FILE__, line)(info->AvgTimePerFrame == expected->AvgTimePerFrame, + "Got unexpected AvgTimePerFrame %I64d, expected %I64d.\n", + info->AvgTimePerFrame, expected->AvgTimePerFrame); + ok_(__FILE__, line)(info->bmiHeader.biSize == expected->bmiHeader.biSize, + "Got unexpected bmiHeader.biSize %lu, expected %lu.\n", + info->bmiHeader.biSize, expected->bmiHeader.biSize); + ok_(__FILE__, line)(info->bmiHeader.biWidth == expected->bmiHeader.biWidth, + "Got unexpected bmiHeader.biWidth %ld, expected %ld.\n", + info->bmiHeader.biWidth, expected->bmiHeader.biWidth); + ok_(__FILE__, line)(info->bmiHeader.biHeight == expected->bmiHeader.biHeight, + "Got unexpected bmiHeader.biHeight %ld, expected %ld.\n", + info->bmiHeader.biHeight, expected->bmiHeader.biHeight); + ok_(__FILE__, line)(info->bmiHeader.biPlanes == expected->bmiHeader.biPlanes, + "Got unexpected bmiHeader.biPlanes %u, expected %u.\n", + info->bmiHeader.biPlanes, expected->bmiHeader.biPlanes); + ok_(__FILE__, line)(info->bmiHeader.biBitCount == expected->bmiHeader.biBitCount, + "Got unexpected bmiHeader.biBitCount %u, expected %u.\n", + info->bmiHeader.biBitCount, expected->bmiHeader.biBitCount); + ok_(__FILE__, line)(info->bmiHeader.biCompression == expected->bmiHeader.biCompression, + "Got unexpected bmiHeader.biCompression %#lx, expected %#lx.\n", + info->bmiHeader.biCompression, expected->bmiHeader.biCompression); + ok_(__FILE__, line)(info->bmiHeader.biSizeImage == expected->bmiHeader.biSizeImage, + "Got unexpected bmiHeader.biSizeImage %lu, expected %lu.\n", + info->bmiHeader.biSizeImage, expected->bmiHeader.biSizeImage); + ok_(__FILE__, line)(info->bmiHeader.biXPelsPerMeter == expected->bmiHeader.biXPelsPerMeter, + "Got unexpected bmiHeader.biXPelsPerMeter %ld, expected %ld.\n", + info->bmiHeader.biXPelsPerMeter, expected->bmiHeader.biXPelsPerMeter); + ok_(__FILE__, line)(info->bmiHeader.biYPelsPerMeter == expected->bmiHeader.biYPelsPerMeter, + "Got unexpected bmiHeader.xxxxxx %ld, expected %ld.\n", + info->bmiHeader.biYPelsPerMeter, expected->bmiHeader.biYPelsPerMeter); + ok_(__FILE__, line)(info->bmiHeader.biClrUsed == expected->bmiHeader.biClrUsed, + "Got unexpected bmiHeader.biClrUsed %lu, expected %lu.\n", + info->bmiHeader.biClrUsed, expected->bmiHeader.biClrUsed); + ok_(__FILE__, line)(info->bmiHeader.biClrImportant == expected->bmiHeader.biClrImportant, + "Got unexpected bmiHeader.biClrImportant %lu, expected %lu.\n", + info->bmiHeader.biClrImportant, expected->bmiHeader.biClrImportant); +} + #define check_dmo_media_type(a, b) check_dmo_media_type_(__LINE__, a, b) static void check_dmo_media_type_(int line, DMO_MEDIA_TYPE *media_type, const DMO_MEDIA_TYPE *expected) { @@ -1096,6 +1157,17 @@ static void check_dmo_media_type_(int line, DMO_MEDIA_TYPE *media_type, const DM ok_(__FILE__, line)(media_type->cbFormat == expected->cbFormat, "Got unexpected cbFormat %lu, expected %lu.\n", media_type->cbFormat, expected->cbFormat); + + if (expected->pbFormat) + { + ok_(__FILE__, line)(!!media_type->pbFormat, "Got NULL pbFormat.\n"); + if (!media_type->pbFormat) + return; + + if (IsEqualGUID(&media_type->formattype, &FORMAT_VideoInfo) + && IsEqualGUID(&expected->formattype, &FORMAT_VideoInfo)) + check_video_info_header((VIDEOINFOHEADER *)media_type->pbFormat, (VIDEOINFOHEADER *)expected->pbFormat); + } }
static void check_dmo_get_input_type(IMediaObject *media_object, const DMO_MEDIA_TYPE *expected_type, ULONG count) @@ -4617,21 +4689,37 @@ static void test_wmv_decoder_media_object(void) {MFMediaType_Video, MEDIASUBTYPE_WMV3, FALSE, TRUE, 0, GUID_NULL, NULL, 0}, {MFMediaType_Video, MFVideoFormat_VC1S, FALSE, TRUE, 0, GUID_NULL, NULL, 0}, }; + const VIDEOINFOHEADER expected_output_info[] = + { + {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 12, MAKEFOURCC('N', 'V', '1', '2'), 384, 0, 0, 0, 0}}, + {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 12, MAKEFOURCC('Y', 'V', '1', '2'), 384, 0, 0, 0, 0}}, + {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 12, MAKEFOURCC('I', 'Y', 'U', 'V'), 384, 0, 0, 0, 0}}, + {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 12, MAKEFOURCC('I', '4', '2', '0'), 384, 0, 0, 0, 0}}, + {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 16, MAKEFOURCC('Y', 'U', 'Y', '2'), 512, 0, 0, 0, 0}}, + {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 16, MAKEFOURCC('U', 'Y', 'V', 'Y'), 512, 0, 0, 0, 0}}, + {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 16, MAKEFOURCC('Y', 'V', 'Y', 'U'), 512, 0, 0, 0, 0}}, + {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 12, MAKEFOURCC('N', 'V', '1', '1'), 384, 0, 0, 0, 0}}, + {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 32, BI_RGB, 1024, 0, 0, 0, 0}}, + {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 24, BI_RGB, 768, 0, 0, 0, 0}}, + {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 16, BI_BITFIELDS, 512, 0, 0, 0, 0}}, + {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 16, BI_RGB, 512, 0, 0, 0, 0}}, + {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 8, BI_RGB, 256, 0, 0, 226, 226}}, + }; const DMO_MEDIA_TYPE expected_output_types[] = { - {MFMediaType_Video, MEDIASUBTYPE_NV12, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88}, - {MFMediaType_Video, MEDIASUBTYPE_YV12, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88}, - {MFMediaType_Video, MEDIASUBTYPE_IYUV, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88}, - {MFMediaType_Video, MEDIASUBTYPE_I420, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88}, - {MFMediaType_Video, MEDIASUBTYPE_YUY2, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88}, - {MFMediaType_Video, MEDIASUBTYPE_UYVY, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88}, - {MFMediaType_Video, MEDIASUBTYPE_YVYU, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88}, - {MFMediaType_Video, MEDIASUBTYPE_NV11, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88}, - {MFMediaType_Video, MEDIASUBTYPE_RGB32, TRUE, FALSE, 1024, FORMAT_VideoInfo, NULL, 88}, - {MFMediaType_Video, MEDIASUBTYPE_RGB24, TRUE, FALSE, 768, FORMAT_VideoInfo, NULL, 88}, - {MFMediaType_Video, MEDIASUBTYPE_RGB565, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 100}, - {MFMediaType_Video, MEDIASUBTYPE_RGB555, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88}, - {MFMediaType_Video, MEDIASUBTYPE_RGB8, TRUE, FALSE, 256, FORMAT_VideoInfo, NULL, 1112}, + {MFMediaType_Video, MEDIASUBTYPE_NV12, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[0]}, + {MFMediaType_Video, MEDIASUBTYPE_YV12, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[1]}, + {MFMediaType_Video, MEDIASUBTYPE_IYUV, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[2]}, + {MFMediaType_Video, MEDIASUBTYPE_I420, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[3]}, + {MFMediaType_Video, MEDIASUBTYPE_YUY2, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[4]}, + {MFMediaType_Video, MEDIASUBTYPE_UYVY, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[5]}, + {MFMediaType_Video, MEDIASUBTYPE_YVYU, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[6]}, + {MFMediaType_Video, MEDIASUBTYPE_NV11, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[7]}, + {MFMediaType_Video, MEDIASUBTYPE_RGB32, TRUE, FALSE, 1024, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[8]}, + {MFMediaType_Video, MEDIASUBTYPE_RGB24, TRUE, FALSE, 768, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[9]}, + {MFMediaType_Video, MEDIASUBTYPE_RGB565, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 100, (BYTE *)&expected_output_info[10]}, + {MFMediaType_Video, MEDIASUBTYPE_RGB555, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[11]}, + {MFMediaType_Video, MEDIASUBTYPE_RGB8, TRUE, FALSE, 256, FORMAT_VideoInfo, NULL, 1112, (BYTE *)&expected_output_info[12]}, }; const struct set_type_arg {
From: Ziqing Hui zhui@codeweavers.com
--- dlls/mf/tests/transform.c | 5 +- dlls/winegstreamer/wmv_decoder.c | 99 ++++++++++++++++++++++++++++---- 2 files changed, 92 insertions(+), 12 deletions(-)
diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index a2e8d1d6e0b..47045112fbf 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -1229,6 +1229,7 @@ static void check_dmo_get_output_type(IMediaObject *media_object, const DMO_MEDI hr = IMediaObject_GetOutputType(media_object, 0, count - 1, NULL); ok(hr == S_OK, "GetOutputType returned unexpected hr %#lx.\n", hr); hr = IMediaObject_GetOutputType(media_object, 0, count - 1, &media_type); + todo_wine ok(hr == S_OK, "GetOutputType returned unexpected hr %#lx.\n", hr); if (hr == S_OK) MoFreeMediaType(&media_type); @@ -1242,7 +1243,9 @@ static void check_dmo_get_output_type(IMediaObject *media_object, const DMO_MEDI winetest_pop_context(); }
+ todo_wine ok(hr == DMO_E_NO_MORE_ITEMS, "GetOutputType returned unexpected hr %#lx.\n", hr); + todo_wine ok(i == count, "%lu types.\n", i); }
@@ -4965,7 +4968,6 @@ static void test_wmv_decoder_media_object(void) hr = IMediaObject_SetInputType(media_object, 0, NULL, DMO_SET_TYPEF_CLEAR); ok(hr == S_OK, "SetInputType returned unexpected hr %#lx.\n", hr); hr = IMediaObject_GetOutputType(media_object, 0, 0, &media_type); - todo_wine ok(hr == DMO_E_TYPE_NOT_SET, "GetOutputType returned unexpected hr %#lx.\n", hr);
/* Test GetOutputType after setting input type. */ @@ -4988,7 +4990,6 @@ static void test_wmv_decoder_media_object(void) hr = IMediaObject_SetInputType(media_object, 0, input_type, 0); ok(hr == S_OK, "SetInputType returned unexpected hr %#lx.\n", hr);
- todo_wine check_dmo_get_output_type(media_object, expected_output_types, ARRAY_SIZE(expected_output_types));
winetest_pop_context(); diff --git a/dlls/winegstreamer/wmv_decoder.c b/dlls/winegstreamer/wmv_decoder.c index 1b03d9aa639..3aacede1345 100644 --- a/dlls/winegstreamer/wmv_decoder.c +++ b/dlls/winegstreamer/wmv_decoder.c @@ -29,21 +29,45 @@
WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
-extern const GUID MFVideoFormat_VC1S; +extern const GUID MEDIASUBTYPE_VC1S;
-DEFINE_GUID(MFVideoFormat_WMV_Unknown, 0x7ce12ca9,0xbfbf,0x43d9,0x9d,0x00,0x82,0xb8,0xed,0x54,0x31,0x6b); +DEFINE_GUID(MEDIASUBTYPE_WMV_Unknown, 0x7ce12ca9,0xbfbf,0x43d9,0x9d,0x00,0x82,0xb8,0xed,0x54,0x31,0x6b); + +struct decoder_type +{ + const GUID *subtype; + WORD bpp; + DWORD compression; +};
static const GUID *const wmv_decoder_input_types[] = { - &MFVideoFormat_WMV1, - &MFVideoFormat_WMV2, + &MEDIASUBTYPE_WMV1, + &MEDIASUBTYPE_WMV2, &MEDIASUBTYPE_WMVA, &MEDIASUBTYPE_WMVP, &MEDIASUBTYPE_WVP2, - &MFVideoFormat_WMV_Unknown, - &MFVideoFormat_WVC1, - &MFVideoFormat_WMV3, - &MFVideoFormat_VC1S, + &MEDIASUBTYPE_WMV_Unknown, + &MEDIASUBTYPE_WVC1, + &MEDIASUBTYPE_WMV3, + &MEDIASUBTYPE_VC1S, +}; + +static const struct decoder_type wmv_decoder_output_types[] = +{ + { &MEDIASUBTYPE_NV12, 12, MAKEFOURCC('N', 'V', '1', '2') }, + { &MEDIASUBTYPE_YV12, 12, MAKEFOURCC('Y', 'V', '1', '2') }, + { &MEDIASUBTYPE_IYUV, 12, MAKEFOURCC('I', 'Y', 'U', 'V') }, + { &MEDIASUBTYPE_I420, 12, MAKEFOURCC('I', '4', '2', '0') }, + { &MEDIASUBTYPE_YUY2, 16, MAKEFOURCC('Y', 'U', 'Y', '2') }, + { &MEDIASUBTYPE_UYVY, 16, MAKEFOURCC('U', 'Y', 'V', 'Y') }, + { &MEDIASUBTYPE_YVYU, 16, MAKEFOURCC('Y', 'V', 'Y', 'U') }, + { &MEDIASUBTYPE_NV11, 12, MAKEFOURCC('N', 'V', '1', '1') }, + { &MEDIASUBTYPE_RGB32, 32, BI_RGB }, + { &MEDIASUBTYPE_RGB24, 24, BI_RGB }, + { &MEDIASUBTYPE_RGB565, 16, BI_BITFIELDS }, + { &MEDIASUBTYPE_RGB555, 16, BI_RGB }, + { &MEDIASUBTYPE_RGB8, 8, BI_RGB }, };
struct wmv_decoder @@ -59,6 +83,11 @@ struct wmv_decoder struct wg_format input_format; };
+static bool wg_format_is_set(struct wg_format *format) +{ + return format->major_type != WG_MAJOR_TYPE_UNKNOWN; +} + static inline struct wmv_decoder *impl_from_IUnknown(IUnknown *iface) { return CONTAINING_RECORD(iface, struct wmv_decoder, IUnknown_inner); @@ -387,8 +416,58 @@ static HRESULT WINAPI media_object_GetInputType(IMediaObject *iface, DWORD index static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD index, DWORD type_index, DMO_MEDIA_TYPE *type) { - FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface, index, type_index, type); - return E_NOTIMPL; + struct wmv_decoder *decoder = impl_from_IMediaObject(iface); + VIDEOINFOHEADER *info; + const GUID *subtype; + LONG width, height; + UINT32 image_size; + HRESULT hr; + + TRACE("iface %p, index %lu, type_index %lu, type %p.\n", iface, index, type_index, type); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + if (type_index >= ARRAY_SIZE(wmv_decoder_output_types)) + return DMO_E_NO_MORE_ITEMS; + if (!type) + return S_OK; + if (!wg_format_is_set(&decoder->input_format)) + return DMO_E_TYPE_NOT_SET; + + width = decoder->input_format.u.video_wmv.width; + height = decoder->input_format.u.video_wmv.height; + subtype = wmv_decoder_output_types[type_index].subtype; + if (FAILED(hr = MFCalculateImageSize(subtype, width, height, &image_size))) + { + FIXME("Failed to get image size of subtype %s.\n", debugstr_guid(subtype)); + return hr; + } + + memset(type, 0, sizeof(*type)); + type->majortype = MFMediaType_Video; + type->subtype = *subtype; + type->bFixedSizeSamples = TRUE; + type->bTemporalCompression = FALSE; + type->lSampleSize = image_size; + type->formattype = FORMAT_VideoInfo; + type->cbFormat = sizeof(VIDEOINFOHEADER); + type->pbFormat = CoTaskMemAlloc(type->cbFormat); + memset(type->pbFormat, 0, type->cbFormat); + + info = (VIDEOINFOHEADER *)type->pbFormat; + info->rcSource.right = width; + info->rcSource.bottom = height; + info->rcTarget.right = width; + info->rcTarget.bottom = height; + info->bmiHeader.biSize = sizeof(info->bmiHeader); + info->bmiHeader.biWidth = width; + info->bmiHeader.biHeight = height; + info->bmiHeader.biPlanes = 1; + info->bmiHeader.biBitCount = wmv_decoder_output_types[type_index].bpp; + info->bmiHeader.biCompression = wmv_decoder_output_types[type_index].compression; + info->bmiHeader.biSizeImage = image_size; + + return S_OK; }
static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index,
Zebediah says we can't simply add IYUV and RGB8 to wg_video_format. Then I think this method doesn't work because we need a wg_video_format to identify each type and convert it to subtype/bpp/compression.
Also, we can't simply make IYUV fails in GetOutputType(). Because there is high possibility that an application use type index to enumerate each output formats. If one format fails, the enumration will stop, formats behind the failed format will be ignored.
Sorry, I missed looking at the rest of this review.
Adding an IYUV format to winegstreamer to match this isn't the worst thing we can do, although in that case we should probably stop mapping IYUV to WG_VIDEO_FORMAT_I420 elsewhere.
Adding RGB8 without properly supporting it bothers me more. It probably wouldn't be the worst thing to create a WG_MAJOR_TYPE_RGB8 and not actually implement conversion, though.
But I also don't think it's that bad just to leave the structs as in v1, or v3.
This merge request was approved by Rémi Bernon.
@rbernon @zfigura I'm going to keep submitting more WMV decoder patches in this MR until code freeze is over. Could you please keep reviewing my patches although it's code freezing now? That would be great help for me to let me know if I'm doing things correctly.
On Mon Dec 12 06:16:28 2022 +0000, Ziqing Hui wrote:
@rbernon @zfigura I'm going to keep submitting more WMV decoder patches in this MR until code freeze is over. Could you please keep reviewing my patches although it's code freezing now? That would be great help for me to let me know if I'm doing things correctly.
Well. I'm going to open a new MR and close this one. I'll keep updating implementation patches in that new MR during code freeze time.
This merge request was closed by Ziqing Hui.