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,