mf/tests: Test info headers returned by GetOutputType for WMV decoder.
[wine.git] / dlls / mf / tests / transform.c
bloba2e8d1d6e0b7eeb49f04fbe68ef487e3b7510163
1 /*
2 * Copyright 2017 Nikolay Sivov
3 * Copyright 2022 RĂ©mi Bernon for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <stdarg.h>
21 #include <string.h>
23 #define COBJMACROS
24 #include "windef.h"
25 #include "winbase.h"
27 #include "control.h"
28 #include "d3d9types.h"
29 #include "dmo.h"
30 #include "mferror.h"
31 #include "mfidl.h"
32 #include "mftransform.h"
33 #include "propvarutil.h"
34 #include "uuids.h"
35 #include "wmcodecdsp.h"
36 #include "mediaerr.h"
37 #include "amvideo.h"
39 #include "mf_test.h"
41 #include "wine/test.h"
43 #include "initguid.h"
45 DEFINE_GUID(DMOVideoFormat_RGB24,D3DFMT_R8G8B8,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
46 DEFINE_GUID(DMOVideoFormat_RGB32,D3DFMT_X8R8G8B8,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
47 DEFINE_GUID(DMOVideoFormat_RGB555,D3DFMT_X1R5G5B5,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
48 DEFINE_GUID(DMOVideoFormat_RGB565,D3DFMT_R5G6B5,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
49 DEFINE_GUID(DMOVideoFormat_RGB8,D3DFMT_P8,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
50 DEFINE_GUID(MFAudioFormat_RAW_AAC1,WAVE_FORMAT_RAW_AAC1,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
51 DEFINE_GUID(MFVideoFormat_ABGR32,0x00000020,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
52 DEFINE_GUID(MFVideoFormat_P208,0x38303250,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
53 DEFINE_GUID(MFVideoFormat_VC1S,0x53314356,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
54 DEFINE_GUID(MFVideoFormat_WMV_Unknown,0x7ce12ca9,0xbfbf,0x43d9,0x9d,0x00,0x82,0xb8,0xed,0x54,0x31,0x6b);
56 DEFINE_GUID(mft_output_sample_incomplete,0xffffff,0xffff,0xffff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
58 static void load_resource(const WCHAR *filename, const BYTE **data, DWORD *length)
60 HRSRC resource = FindResourceW(NULL, filename, (const WCHAR *)RT_RCDATA);
61 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
62 *data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
63 *length = SizeofResource(GetModuleHandleW(NULL), resource);
66 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
67 static void _expect_ref(IUnknown* obj, ULONG expected_refcount, int line)
69 ULONG refcount;
70 IUnknown_AddRef(obj);
71 refcount = IUnknown_Release(obj);
72 ok_(__FILE__, line)(refcount == expected_refcount, "Unexpected refcount %ld, expected %ld.\n", refcount,
73 expected_refcount);
76 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
77 static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported)
79 IUnknown *iface = iface_ptr;
80 HRESULT hr, expected_hr;
81 IUnknown *unk;
83 expected_hr = supported ? S_OK : E_NOINTERFACE;
85 hr = IUnknown_QueryInterface(iface, iid, (void **)&unk);
86 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#lx, expected %#lx.\n", hr, expected_hr);
87 if (SUCCEEDED(hr))
88 IUnknown_Release(unk);
91 #define check_member_(file, line, val, exp, fmt, member) \
92 ok_ (file, line)((val).member == (exp).member, "got " #member " " fmt "\n", (val).member)
93 #define check_member(val, exp, fmt, member) check_member_(__FILE__, __LINE__, val, exp, fmt, member)
95 void check_attributes_(const char *file, int line, IMFAttributes *attributes,
96 const struct attribute_desc *desc, ULONG limit)
98 char buffer[256], *buf = buffer;
99 PROPVARIANT value;
100 int i, j, ret;
101 HRESULT hr;
103 for (i = 0; i < limit && desc[i].key; ++i)
105 hr = IMFAttributes_GetItem(attributes, desc[i].key, &value);
106 todo_wine_if(desc[i].todo)
107 ok_(file, line)(hr == S_OK, "%s missing, hr %#lx\n", debugstr_a(desc[i].name), hr);
108 if (hr != S_OK) continue;
110 switch (value.vt)
112 default: sprintf(buffer, "??"); break;
113 case VT_CLSID: sprintf(buffer, "%s", debugstr_guid(value.puuid)); break;
114 case VT_UI4: sprintf(buffer, "%lu", value.ulVal); break;
115 case VT_UI8:
116 if (desc[i].ratio)
117 sprintf(buffer, "%lu:%lu", value.uhVal.HighPart, value.uhVal.LowPart);
118 else
119 sprintf(buffer, "%I64u", value.uhVal.QuadPart);
120 break;
121 case VT_VECTOR | VT_UI1:
122 buf += sprintf(buf, "size %lu, data {", value.caub.cElems);
123 for (j = 0; j < 16 && j < value.caub.cElems; ++j)
124 buf += sprintf(buf, "0x%02x,", value.caub.pElems[j]);
125 if (value.caub.cElems > 16)
126 buf += sprintf(buf, "...}");
127 else
128 buf += sprintf(buf - (j ? 1 : 0), "}");
129 break;
132 ret = PropVariantCompareEx(&value, &desc[i].value, 0, 0);
133 todo_wine_if(desc[i].todo_value)
134 ok_(file, line)(ret == 0, "%s mismatch, type %u, value %s\n",
135 debugstr_a(desc[i].name), value.vt, buffer);
139 struct transform_info
141 const WCHAR *name;
142 const GUID *major_type;
143 struct
145 const GUID *subtype;
146 BOOL broken;
147 } inputs[32], input_end, outputs[32], output_end;
150 static BOOL check_mft_enum(GUID category, MFT_REGISTER_TYPE_INFO *input_type,
151 MFT_REGISTER_TYPE_INFO *output_type, const GUID *expect_class_id)
153 GUID *class_ids = NULL;
154 UINT32 count = 0, i;
155 HRESULT hr;
157 hr = MFTEnum(category, 0, input_type, output_type, NULL, &class_ids, &count);
158 if (FAILED(hr) || count == 0)
160 todo_wine
161 win_skip("MFTEnum returned %#lx, count %u, skipping tests.\n", hr, count);
162 return FALSE;
165 ok(hr == S_OK, "MFTEnum returned %#lx\n", hr);
166 for (i = 0; i < count; ++i)
167 if (IsEqualGUID(expect_class_id, class_ids + i))
168 break;
169 ok(i < count, "Failed to find transform.\n");
170 CoTaskMemFree(class_ids);
172 return i < count;
175 static void check_mft_get_info(const GUID *class_id, const struct transform_info *expect)
177 MFT_REGISTER_TYPE_INFO *input_types = NULL, *output_types = NULL;
178 UINT32 input_count = 0, output_count = 0, i;
179 WCHAR *name;
180 HRESULT hr;
182 hr = MFTGetInfo(*class_id, &name, &input_types, &input_count, &output_types, &output_count, NULL);
183 ok(hr == S_OK, "MFTEnum returned %#lx\n", hr);
184 ok(!wcscmp(name, expect->name), "got name %s\n", debugstr_w(name));
186 for (i = 0; i < input_count && expect->inputs[i].subtype; ++i)
188 ok(IsEqualGUID(&input_types[i].guidMajorType, expect->major_type),
189 "got input[%u] major %s\n", i, debugstr_guid(&input_types[i].guidMajorType));
190 ok(IsEqualGUID(&input_types[i].guidSubtype, expect->inputs[i].subtype),
191 "got input[%u] subtype %s\n", i, debugstr_guid(&input_types[i].guidSubtype));
193 for (; expect->inputs[i].subtype; ++i)
194 ok(broken(expect->inputs[i].broken), "missing input[%u] subtype %s\n",
195 i, debugstr_guid(expect->inputs[i].subtype));
196 for (; i < input_count; ++i)
197 ok(0, "extra input[%u] subtype %s\n", i, debugstr_guid(&input_types[i].guidSubtype));
199 for (i = 0; expect->outputs[i].subtype; ++i)
201 ok(IsEqualGUID(&output_types[i].guidMajorType, expect->major_type),
202 "got output[%u] major %s\n", i, debugstr_guid(&output_types[i].guidMajorType));
203 ok(IsEqualGUID(&output_types[i].guidSubtype, expect->outputs[i].subtype),
204 "got output[%u] subtype %s\n", i, debugstr_guid(&output_types[i].guidSubtype));
206 for (; expect->outputs[i].subtype; ++i)
207 ok(0, "missing output[%u] subtype %s\n", i, debugstr_guid(expect->outputs[i].subtype));
208 for (; i < output_count; ++i)
209 ok(0, "extra output[%u] subtype %s\n", i, debugstr_guid(&output_types[i].guidSubtype));
211 CoTaskMemFree(output_types);
212 CoTaskMemFree(input_types);
213 CoTaskMemFree(name);
216 static void check_dmo_get_info(const GUID *class_id, const struct transform_info *expect)
218 DWORD input_count = 0, output_count = 0;
219 DMO_PARTIAL_MEDIATYPE output[32] = {{{0}}};
220 DMO_PARTIAL_MEDIATYPE input[32] = {{{0}}};
221 WCHAR name[80];
222 HRESULT hr;
223 int i;
225 hr = DMOGetName(class_id, name);
226 ok(hr == S_OK, "DMOGetName returned %#lx\n", hr);
227 ok(!wcscmp(name, expect->name), "got name %s\n", debugstr_w(name));
229 hr = DMOGetTypes(class_id, ARRAY_SIZE(input), &input_count, input,
230 ARRAY_SIZE(output), &output_count, output);
231 ok(hr == S_OK, "DMOGetTypes returned %#lx\n", hr);
233 for (i = 0; i < input_count && expect->inputs[i].subtype; ++i)
235 ok(IsEqualGUID(&input[i].type, expect->major_type),
236 "got input[%u] major %s\n", i, debugstr_guid(&input[i].type));
237 ok(IsEqualGUID(&input[i].subtype, expect->inputs[i].subtype),
238 "got input[%u] subtype %s\n", i, debugstr_guid(&input[i].subtype));
240 for (; expect->inputs[i].subtype; ++i)
241 ok(0, "missing input[%u] subtype %s\n", i, debugstr_guid(expect->inputs[i].subtype));
242 for (; i < input_count; ++i)
243 ok(0, "extra input[%u] subtype %s\n", i, debugstr_guid(&input[i].subtype));
245 for (i = 0; expect->outputs[i].subtype; ++i)
247 ok(IsEqualGUID(&output[i].type, expect->major_type),
248 "got output[%u] major %s\n", i, debugstr_guid(&output[i].type));
249 ok(IsEqualGUID(&output[i].subtype, expect->outputs[i].subtype),
250 "got output[%u] subtype %s\n", i, debugstr_guid(&output[i].subtype));
252 for (; expect->outputs[i].subtype; ++i)
253 ok(0, "missing output[%u] subtype %s\n", i, debugstr_guid(expect->outputs[i].subtype));
254 for (; i < output_count; ++i)
255 ok(0, "extra output[%u] subtype %s\n", i, debugstr_guid(&output[i].subtype));
258 void init_media_type(IMFMediaType *mediatype, const struct attribute_desc *desc, ULONG limit)
260 HRESULT hr;
261 ULONG i;
263 hr = IMFMediaType_DeleteAllItems(mediatype);
264 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
266 for (i = 0; i < limit && desc[i].key; ++i)
268 hr = IMFMediaType_SetItem(mediatype, desc[i].key, &desc[i].value);
269 ok(hr == S_OK, "SetItem %s returned %#lx\n", debugstr_a(desc[i].name), hr);
273 static void init_dmo_media_type_video(DMO_MEDIA_TYPE *media_type,
274 const GUID *subtype, const LONG width, const LONG height)
276 VIDEOINFOHEADER *header = (VIDEOINFOHEADER *)(media_type + 1);
278 memset(header, 0, sizeof(*header));
279 header->bmiHeader.biSize = sizeof(header->bmiHeader);
280 header->bmiHeader.biWidth = width;
281 header->bmiHeader.biHeight = height;
282 header->bmiHeader.biCompression = subtype->Data1;
284 media_type->majortype = MEDIATYPE_Video;
285 media_type->subtype = *subtype;
286 media_type->bFixedSizeSamples = FALSE;
287 media_type->bTemporalCompression = TRUE;
288 media_type->lSampleSize = 0;
289 media_type->formattype = FORMAT_VideoInfo;
290 media_type->pUnk = NULL;
291 media_type->cbFormat = sizeof(*header) + 4; /* 4 bytes codec data. */
292 media_type->pbFormat = (BYTE *)header;
295 static void check_mft_optional_methods(IMFTransform *transform, DWORD output_count)
297 DWORD in_id, out_id, in_count, out_count, in_min, in_max, out_min, out_max;
298 PROPVARIANT propvar = {.vt = VT_EMPTY};
299 IMFMediaEvent *event;
300 HRESULT hr;
302 in_min = in_max = out_min = out_max = 0xdeadbeef;
303 hr = IMFTransform_GetStreamLimits(transform, &in_min, &in_max, &out_min, &out_max);
304 ok(hr == S_OK, "GetStreamLimits returned %#lx\n", hr);
305 ok(in_min == 1, "got input_min %lu\n", in_min);
306 ok(in_max == 1, "got input_max %lu\n", in_max);
307 ok(out_min == output_count, "got output_min %lu\n", out_min);
308 ok(out_max == output_count, "got output_max %lu\n", out_max);
310 in_count = out_count = 0xdeadbeef;
311 hr = IMFTransform_GetStreamCount(transform, &in_count, &out_count);
312 ok(hr == S_OK, "GetStreamCount returned %#lx\n", hr);
313 ok(in_count == 1, "got input_count %lu\n", in_count);
314 ok(out_count == output_count, "got output_count %lu\n", out_count);
316 in_count = out_count = 1;
317 in_id = out_id = 0xdeadbeef;
318 hr = IMFTransform_GetStreamIDs(transform, in_count, &in_id, out_count, &out_id);
319 ok(hr == E_NOTIMPL, "GetStreamIDs returned %#lx\n", hr);
321 hr = IMFTransform_DeleteInputStream(transform, 0);
322 ok(hr == E_NOTIMPL, "DeleteInputStream returned %#lx\n", hr);
323 hr = IMFTransform_DeleteInputStream(transform, 1);
324 ok(hr == E_NOTIMPL, "DeleteInputStream returned %#lx\n", hr);
326 hr = IMFTransform_AddInputStreams(transform, 0, NULL);
327 ok(hr == E_NOTIMPL, "AddInputStreams returned %#lx\n", hr);
328 in_id = 0xdeadbeef;
329 hr = IMFTransform_AddInputStreams(transform, 1, &in_id);
330 ok(hr == E_NOTIMPL, "AddInputStreams returned %#lx\n", hr);
332 hr = IMFTransform_SetOutputBounds(transform, 0, 0);
333 ok(hr == E_NOTIMPL || hr == S_OK, "SetOutputBounds returned %#lx\n", hr);
335 hr = MFCreateMediaEvent(MEEndOfStream, &GUID_NULL, S_OK, &propvar, &event);
336 ok(hr == S_OK, "MFCreateMediaEvent returned %#lx\n", hr);
337 hr = IMFTransform_ProcessEvent(transform, 0, NULL);
338 ok(hr == E_NOTIMPL || hr == E_POINTER || hr == E_INVALIDARG, "ProcessEvent returned %#lx\n", hr);
339 hr = IMFTransform_ProcessEvent(transform, 1, event);
340 ok(hr == E_NOTIMPL, "ProcessEvent returned %#lx\n", hr);
341 hr = IMFTransform_ProcessEvent(transform, 0, event);
342 ok(hr == E_NOTIMPL, "ProcessEvent returned %#lx\n", hr);
343 IMFMediaEvent_Release(event);
346 static void check_mft_get_attributes(IMFTransform *transform, const struct attribute_desc *expect_transform_attributes,
347 BOOL expect_output_attributes)
349 IMFAttributes *attributes, *tmp_attributes;
350 UINT32 count;
351 HRESULT hr;
352 ULONG ref;
354 hr = IMFTransform_GetAttributes(transform, &attributes);
355 todo_wine_if(expect_transform_attributes && hr == E_NOTIMPL)
356 ok(hr == (expect_transform_attributes ? S_OK : E_NOTIMPL), "GetAttributes returned %#lx\n", hr);
357 if (hr == S_OK)
359 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
360 check_attributes(attributes, expect_transform_attributes, -1);
362 hr = IMFTransform_GetAttributes(transform, &tmp_attributes);
363 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
364 ok(attributes == tmp_attributes, "got attributes %p\n", tmp_attributes);
365 IMFAttributes_Release(tmp_attributes);
367 ref = IMFAttributes_Release(attributes);
368 ok(ref == 1, "Release returned %lu\n", ref);
371 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes);
372 todo_wine_if(expect_output_attributes && hr == E_NOTIMPL)
373 ok(hr == (expect_output_attributes ? S_OK : E_NOTIMPL)
374 || broken(hr == MF_E_UNSUPPORTED_REPRESENTATION) /* Win7 */,
375 "GetOutputStreamAttributes returned %#lx\n", hr);
376 if (hr == S_OK)
378 ok(hr == S_OK, "GetOutputStreamAttributes returned %#lx\n", hr);
380 count = 0xdeadbeef;
381 hr = IMFAttributes_GetCount(attributes, &count);
382 ok(hr == S_OK, "GetCount returned %#lx\n", hr);
383 ok(!count, "got %u attributes\n", count);
385 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &tmp_attributes);
386 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
387 ok(attributes == tmp_attributes, "got attributes %p\n", tmp_attributes);
388 IMFAttributes_Release(tmp_attributes);
390 ref = IMFAttributes_Release(attributes);
391 ok(ref == 1, "Release returned %lu\n", ref);
393 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, NULL);
394 ok(hr == E_NOTIMPL || hr == E_POINTER, "GetOutputStreamAttributes returned %#lx\n", hr);
395 hr = IMFTransform_GetOutputStreamAttributes(transform, 1, &attributes);
396 ok(hr == MF_E_INVALIDSTREAMNUMBER, "GetOutputStreamAttributes returned %#lx\n", hr);
399 hr = IMFTransform_GetInputStreamAttributes(transform, 0, &attributes);
400 ok(hr == E_NOTIMPL || broken(hr == MF_E_UNSUPPORTED_REPRESENTATION) /* Win7 */,
401 "GetInputStreamAttributes returned %#lx\n", hr);
404 #define check_mft_input_stream_info(a, b) check_mft_input_stream_info_(__LINE__, a, b)
405 static void check_mft_input_stream_info_(int line, MFT_INPUT_STREAM_INFO *value, const MFT_INPUT_STREAM_INFO *expect)
407 check_member_(__FILE__, line, *value, *expect, "%I64d", hnsMaxLatency);
408 check_member_(__FILE__, line, *value, *expect, "%#lx", dwFlags);
409 check_member_(__FILE__, line, *value, *expect, "%#lx", cbSize);
410 check_member_(__FILE__, line, *value, *expect, "%#lx", cbMaxLookahead);
411 check_member_(__FILE__, line, *value, *expect, "%#lx", cbAlignment);
414 #define check_mft_get_input_stream_info(a, b, c) check_mft_get_input_stream_info_(__LINE__, a, b, c)
415 static void check_mft_get_input_stream_info_(int line, IMFTransform *transform, HRESULT expect_hr, const MFT_INPUT_STREAM_INFO *expect)
417 MFT_INPUT_STREAM_INFO info, empty = {0};
418 HRESULT hr;
420 memset(&info, 0xcd, sizeof(info));
421 hr = IMFTransform_GetInputStreamInfo(transform, 0, &info);
422 ok_(__FILE__, line)(hr == expect_hr, "GetInputStreamInfo returned %#lx\n", hr);
423 check_mft_input_stream_info_(line, &info, expect ? expect : &empty);
426 #define check_mft_output_stream_info(a, b) check_mft_output_stream_info_(__LINE__, a, b)
427 static void check_mft_output_stream_info_(int line, MFT_OUTPUT_STREAM_INFO *value, const MFT_OUTPUT_STREAM_INFO *expect)
429 check_member_(__FILE__, line, *value, *expect, "%#lx", dwFlags);
430 check_member_(__FILE__, line, *value, *expect, "%#lx", cbSize);
431 check_member_(__FILE__, line, *value, *expect, "%#lx", cbAlignment);
434 #define check_mft_get_output_stream_info(a, b, c) check_mft_get_output_stream_info_(__LINE__, a, b, c)
435 static void check_mft_get_output_stream_info_(int line, IMFTransform *transform, HRESULT expect_hr, const MFT_OUTPUT_STREAM_INFO *expect)
437 MFT_OUTPUT_STREAM_INFO info, empty = {0};
438 HRESULT hr;
440 memset(&info, 0xcd, sizeof(info));
441 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &info);
442 ok_(__FILE__, line)(hr == expect_hr, "GetOutputStreamInfo returned %#lx\n", hr);
443 check_mft_output_stream_info_(line, &info, expect ? expect : &empty);
446 #define check_mft_set_input_type_required(a, b) check_mft_set_input_type_required_(__LINE__, a, b)
447 static void check_mft_set_input_type_required_(int line, IMFTransform *transform, const struct attribute_desc *attributes)
449 const struct attribute_desc *attr;
450 IMFMediaType *media_type;
451 HRESULT hr;
452 ULONG ref;
454 hr = MFCreateMediaType(&media_type);
455 ok_(__FILE__, line)(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
456 init_media_type(media_type, attributes, -1);
458 for (attr = attributes; attr && attr->key; attr++)
460 winetest_push_context("%s", debugstr_a(attr->name));
461 hr = IMFMediaType_DeleteItem(media_type, attr->key);
462 ok_(__FILE__, line)(hr == S_OK, "DeleteItem returned %#lx\n", hr);
463 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
464 ok_(__FILE__, line)(FAILED(hr) == attr->required, "SetInputType returned %#lx.\n", hr);
465 hr = IMFMediaType_SetItem(media_type, attr->key, &attr->value);
466 ok_(__FILE__, line)(hr == S_OK, "SetItem returned %#lx\n", hr);
467 winetest_pop_context();
470 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
471 ok_(__FILE__, line)(hr == S_OK, "SetInputType returned %#lx.\n", hr);
472 ref = IMFMediaType_Release(media_type);
473 ok_(__FILE__, line)(!ref, "Release returned %lu\n", ref);
476 static void check_mft_set_input_type(IMFTransform *transform, const struct attribute_desc *attributes)
478 IMFMediaType *media_type;
479 HRESULT hr;
481 hr = MFCreateMediaType(&media_type);
482 ok(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
483 init_media_type(media_type, attributes, -1);
485 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
486 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
487 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
488 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
490 IMFMediaType_Release(media_type);
493 #define check_mft_get_input_current_type(a, b) check_mft_get_input_current_type_(a, b, FALSE, FALSE)
494 static void check_mft_get_input_current_type_(IMFTransform *transform, const struct attribute_desc *attributes,
495 BOOL todo_current, BOOL todo_compare)
497 HRESULT hr, expect_hr = attributes ? S_OK : MF_E_TRANSFORM_TYPE_NOT_SET;
498 IMFMediaType *media_type, *current_type;
499 BOOL result;
501 hr = IMFTransform_GetInputCurrentType(transform, 0, &current_type);
502 todo_wine_if(todo_current)
503 ok(hr == expect_hr, "GetInputCurrentType returned hr %#lx.\n", hr);
504 if (FAILED(hr))
505 return;
507 hr = MFCreateMediaType(&media_type);
508 ok(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
509 init_media_type(media_type, attributes, -1);
511 hr = IMFMediaType_Compare(current_type, (IMFAttributes *)media_type,
512 MF_ATTRIBUTES_MATCH_ALL_ITEMS, &result);
513 ok(hr == S_OK, "Compare returned hr %#lx.\n", hr);
514 todo_wine_if(todo_compare)
515 ok(result, "got result %u.\n", !!result);
517 IMFMediaType_Release(media_type);
518 IMFMediaType_Release(current_type);
521 #define check_mft_set_output_type_required(a, b) check_mft_set_output_type_required_(__LINE__, a, b)
522 static void check_mft_set_output_type_required_(int line, IMFTransform *transform, const struct attribute_desc *attributes)
524 const struct attribute_desc *attr;
525 IMFMediaType *media_type;
526 HRESULT hr;
527 ULONG ref;
529 hr = MFCreateMediaType(&media_type);
530 ok_(__FILE__, line)(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
531 init_media_type(media_type, attributes, -1);
533 for (attr = attributes; attr && attr->key; attr++)
535 winetest_push_context("%s", debugstr_a(attr->name));
536 hr = IMFMediaType_DeleteItem(media_type, attr->key);
537 ok_(__FILE__, line)(hr == S_OK, "DeleteItem returned %#lx\n", hr);
538 hr = IMFTransform_SetOutputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
539 ok_(__FILE__, line)(FAILED(hr) == attr->required, "SetOutputType returned %#lx.\n", hr);
540 hr = IMFMediaType_SetItem(media_type, attr->key, &attr->value);
541 ok_(__FILE__, line)(hr == S_OK, "SetItem returned %#lx\n", hr);
542 winetest_pop_context();
545 hr = IMFTransform_SetOutputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
546 ok_(__FILE__, line)(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
547 ref = IMFMediaType_Release(media_type);
548 ok_(__FILE__, line)(!ref, "Release returned %lu\n", ref);
551 static void check_mft_set_output_type(IMFTransform *transform, const struct attribute_desc *attributes,
552 HRESULT expect_hr)
554 IMFMediaType *media_type;
555 HRESULT hr;
557 hr = MFCreateMediaType(&media_type);
558 ok(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
559 init_media_type(media_type, attributes, -1);
561 hr = IMFTransform_SetOutputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
562 ok(hr == expect_hr, "SetOutputType returned %#lx.\n", hr);
563 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
564 ok(hr == expect_hr, "SetOutputType returned %#lx.\n", hr);
566 IMFMediaType_Release(media_type);
569 #define check_mft_get_output_current_type(a, b) check_mft_get_output_current_type_(a, b, FALSE, FALSE)
570 static void check_mft_get_output_current_type_(IMFTransform *transform, const struct attribute_desc *attributes,
571 BOOL todo_current, BOOL todo_compare)
573 HRESULT hr, expect_hr = attributes ? S_OK : MF_E_TRANSFORM_TYPE_NOT_SET;
574 IMFMediaType *media_type, *current_type;
575 BOOL result;
577 hr = IMFTransform_GetOutputCurrentType(transform, 0, &current_type);
578 todo_wine_if(todo_current)
579 ok(hr == expect_hr, "GetOutputCurrentType returned hr %#lx.\n", hr);
580 if (FAILED(hr))
581 return;
583 hr = MFCreateMediaType(&media_type);
584 ok(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
585 init_media_type(media_type, attributes, -1);
587 hr = IMFMediaType_Compare(current_type, (IMFAttributes *)media_type,
588 MF_ATTRIBUTES_MATCH_ALL_ITEMS, &result);
589 ok(hr == S_OK, "Compare returned hr %#lx.\n", hr);
590 todo_wine_if(todo_compare)
591 ok(result, "got result %u.\n", !!result);
593 IMFMediaType_Release(media_type);
594 IMFMediaType_Release(current_type);
597 #define check_mft_process_output(a, b, c) check_mft_process_output_(__LINE__, a, b, c)
598 static HRESULT check_mft_process_output_(int line, IMFTransform *transform, IMFSample *output_sample, DWORD *output_status)
600 static const DWORD expect_flags = MFT_OUTPUT_DATA_BUFFER_INCOMPLETE | MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE
601 | MFT_OUTPUT_DATA_BUFFER_STREAM_END | MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE;
602 MFT_OUTPUT_DATA_BUFFER output[3];
603 HRESULT hr, ret;
604 DWORD status;
606 status = 0;
607 memset(&output, 0, sizeof(output));
608 output[0].pSample = output_sample;
609 output[0].dwStreamID = 0;
610 ret = IMFTransform_ProcessOutput(transform, 0, 1, output, &status);
611 ok_(__FILE__, line)(output[0].dwStreamID == 0, "got dwStreamID %#lx\n", output[0].dwStreamID);
612 ok_(__FILE__, line)(output[0].pEvents == NULL, "got pEvents %p\n", output[0].pEvents);
613 ok_(__FILE__, line)(output[0].pSample == output_sample, "got pSample %p\n", output[0].pSample);
614 ok_(__FILE__, line)((output[0].dwStatus & ~expect_flags) == 0
615 || broken((output[0].dwStatus & ~expect_flags) == 6) /* Win7 */
616 || broken((output[0].dwStatus & ~expect_flags) == 7) /* Win7 */,
617 "got dwStatus %#lx\n", output[0].dwStatus);
618 *output_status = output[0].dwStatus & expect_flags;
620 if (!output_sample)
621 ok_(__FILE__, line)(status == 0, "got status %#lx\n", status);
622 else if (ret == MF_E_TRANSFORM_STREAM_CHANGE)
623 ok_(__FILE__, line)(status == MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS,
624 "got status %#lx\n", status);
625 else
627 if (*output_status & MFT_OUTPUT_DATA_BUFFER_INCOMPLETE)
629 hr = IMFSample_SetUINT32(output_sample, &mft_output_sample_incomplete, 1);
630 ok_(__FILE__, line)(hr == S_OK, "SetUINT32 returned %#lx\n", hr);
632 else
634 hr = IMFSample_DeleteItem(output_sample, &mft_output_sample_incomplete);
635 ok_(__FILE__, line)(hr == S_OK, "DeleteItem returned %#lx\n", hr);
637 ok_(__FILE__, line)(status == 0, "got status %#lx\n", status);
640 return ret;
643 DWORD compare_nv12(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
645 DWORD x, y, size, diff = 0, width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
647 /* skip BMP header and RGB data from the dump */
648 size = *(DWORD *)(expect + 2);
649 *length = *length + size;
650 expect = expect + size;
652 for (y = 0; y < height; y++, data += width, expect += width)
654 if (y < rect->top || y >= rect->bottom) continue;
655 for (x = 0; x < width; x++)
657 if (x < rect->left || x >= rect->right) continue;
658 diff += abs((int)expect[x] - (int)data[x]);
662 for (y = 0; y < height; y += 2, data += width, expect += width)
664 if (y < rect->top || y >= rect->bottom) continue;
665 for (x = 0; x < width; x += 2)
667 if (x < rect->left || x >= rect->right) continue;
668 diff += abs((int)expect[x + 0] - (int)data[x + 0]);
669 diff += abs((int)expect[x + 1] - (int)data[x + 1]);
673 size = (rect->right - rect->left) * (rect->bottom - rect->top) * 3 / 2;
674 return diff * 100 / 256 / size;
677 DWORD compare_i420(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
679 DWORD i, x, y, size, diff = 0, width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
681 /* skip BMP header and RGB data from the dump */
682 size = *(DWORD *)(expect + 2);
683 *length = *length + size;
684 expect = expect + size;
686 for (y = 0; y < height; y++, data += width, expect += width)
688 if (y < rect->top || y >= rect->bottom) continue;
689 for (x = 0; x < width; x++)
691 if (x < rect->left || x >= rect->right) continue;
692 diff += abs((int)expect[x] - (int)data[x]);
696 for (i = 0; i < 2; ++i) for (y = 0; y < height; y += 2, data += width / 2, expect += width / 2)
698 if (y < rect->top || y >= rect->bottom) continue;
699 for (x = 0; x < width; x += 2)
701 if (x < rect->left || x >= rect->right) continue;
702 diff += abs((int)expect[x / 2] - (int)data[x / 2]);
706 size = (rect->right - rect->left) * (rect->bottom - rect->top) * 3 / 2;
707 return diff * 100 / 256 / size;
710 DWORD compare_rgb32(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
712 DWORD x, y, size, diff = 0, width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
714 /* skip BMP header from the dump */
715 size = *(DWORD *)(expect + 2 + 2 * sizeof(DWORD));
716 *length = *length + size;
717 expect = expect + size;
719 for (y = 0; y < height; y++, data += width * 4, expect += width * 4)
721 if (y < rect->top || y >= rect->bottom) continue;
722 for (x = 0; x < width; x++)
724 if (x < rect->left || x >= rect->right) continue;
725 diff += abs((int)expect[4 * x + 0] - (int)data[4 * x + 0]);
726 diff += abs((int)expect[4 * x + 1] - (int)data[4 * x + 1]);
727 diff += abs((int)expect[4 * x + 2] - (int)data[4 * x + 2]);
731 size = (rect->right - rect->left) * (rect->bottom - rect->top) * 3;
732 return diff * 100 / 256 / size;
735 DWORD compare_pcm16(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
737 const INT16 *data_pcm = (INT16 *)data, *expect_pcm = (INT16 *)expect;
738 DWORD i, size = *length / 2, diff = 0;
740 for (i = 0; i < size; i++)
741 diff += abs((int)*expect_pcm++ - (int)*data_pcm++);
743 return diff * 100 / 65536 / size;
746 static DWORD compare_bytes(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
748 DWORD i, size = *length, diff = 0;
750 for (i = 0; i < size; i++)
751 diff += abs((int)*expect++ - (int)*data++);
753 return diff * 100 / 256 / size;
756 void dump_rgb32(const BYTE *data, DWORD length, const RECT *rect, HANDLE output)
758 DWORD width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
759 static const char magic[2] = "BM";
760 struct
762 DWORD length;
763 DWORD reserved;
764 DWORD offset;
765 BITMAPINFOHEADER biHeader;
766 } header =
768 .length = length + sizeof(header) + 2, .offset = sizeof(header) + 2,
769 .biHeader =
771 .biSize = sizeof(BITMAPINFOHEADER), .biWidth = width, .biHeight = height, .biPlanes = 1,
772 .biBitCount = 32, .biCompression = BI_RGB, .biSizeImage = width * height * 4,
775 DWORD written;
776 BOOL ret;
778 ret = WriteFile(output, magic, sizeof(magic), &written, NULL);
779 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
780 ok(written == sizeof(magic), "written %lu bytes\n", written);
781 ret = WriteFile(output, &header, sizeof(header), &written, NULL);
782 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
783 ok(written == sizeof(header), "written %lu bytes\n", written);
784 ret = WriteFile(output, data, length, &written, NULL);
785 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
786 ok(written == length, "written %lu bytes\n", written);
789 void dump_nv12(const BYTE *data, DWORD length, const RECT *rect, HANDLE output)
791 DWORD written, x, y, width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
792 BYTE *rgb32_data = malloc(width * height * 4), *rgb32 = rgb32_data;
793 BOOL ret;
795 for (y = 0; y < height; y++) for (x = 0; x < width; x++)
797 *rgb32++ = data[width * y + x];
798 *rgb32++ = data[width * height + width * (y / 2) + (x & ~1) + 0];
799 *rgb32++ = data[width * height + width * (y / 2) + (x & ~1) + 1];
800 *rgb32++ = 0xff;
803 dump_rgb32(rgb32_data, width * height * 4, rect, output);
804 free(rgb32_data);
806 ret = WriteFile(output, data, length, &written, NULL);
807 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
808 ok(written == length, "written %lu bytes\n", written);
811 void dump_i420(const BYTE *data, DWORD length, const RECT *rect, HANDLE output)
813 DWORD written, x, y, width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
814 BYTE *rgb32_data = malloc(width * height * 4), *rgb32 = rgb32_data;
815 BOOL ret;
817 for (y = 0; y < height; y++) for (x = 0; x < width; x++)
819 *rgb32++ = data[width * y + x];
820 *rgb32++ = data[width * height + (width / 2) * (y / 2) + x / 2];
821 *rgb32++ = data[width * height + (width / 2) * (y / 2) + (width / 2) * (height / 2) + x / 2];
822 *rgb32++ = 0xff;
825 dump_rgb32(rgb32_data, width * height * 4, rect, output);
826 free(rgb32_data);
828 ret = WriteFile(output, data, length, &written, NULL);
829 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
830 ok(written == length, "written %lu bytes\n", written);
833 typedef void (*enum_mf_media_buffers_cb)(IMFMediaBuffer *buffer, const struct buffer_desc *desc, void *context);
834 static void enum_mf_media_buffers(IMFSample *sample, const struct sample_desc *sample_desc,
835 enum_mf_media_buffers_cb callback, void *context)
837 IMFMediaBuffer *buffer;
838 HRESULT hr;
839 DWORD i;
841 for (i = 0; SUCCEEDED(hr = IMFSample_GetBufferByIndex(sample, i, &buffer)); i++)
843 winetest_push_context("buffer %lu", i);
844 ok(hr == S_OK, "GetBufferByIndex returned %#lx\n", hr);
845 ok(i < sample_desc->buffer_count, "got unexpected buffer\n");
847 callback(buffer, sample_desc->buffers + i, context);
849 IMFMediaBuffer_Release(buffer);
850 winetest_pop_context();
852 ok(hr == E_INVALIDARG, "GetBufferByIndex returned %#lx\n", hr);
855 struct enum_mf_sample_state
857 const struct sample_desc *next_sample;
858 struct sample_desc sample;
861 typedef void (*enum_mf_sample_cb)(IMFSample *sample, const struct sample_desc *sample_desc, void *context);
862 static void enum_mf_samples(IMFCollection *samples, const struct sample_desc *collection_desc,
863 enum_mf_sample_cb callback, void *context)
865 struct enum_mf_sample_state state = {.next_sample = collection_desc};
866 IMFSample *sample;
867 HRESULT hr;
868 DWORD i;
870 for (i = 0; SUCCEEDED(hr = IMFCollection_GetElement(samples, i, (IUnknown **)&sample)); i++)
872 winetest_push_context("sample %lu", i);
873 ok(hr == S_OK, "GetElement returned %#lx\n", hr);
875 state.sample.sample_time += state.sample.sample_duration;
876 if (!state.sample.repeat_count--)
877 state.sample = *state.next_sample++;
879 callback(sample, &state.sample, context);
881 IMFSample_Release(sample);
882 winetest_pop_context();
884 ok(hr == E_INVALIDARG, "GetElement returned %#lx\n", hr);
887 static void dump_mf_media_buffer(IMFMediaBuffer *buffer, const struct buffer_desc *buffer_desc, HANDLE output)
889 DWORD length, written;
890 HRESULT hr;
891 BYTE *data;
892 BOOL ret;
894 hr = IMFMediaBuffer_Lock(buffer, &data, NULL, &length);
895 ok(hr == S_OK, "Lock returned %#lx\n", hr);
897 if (buffer_desc->dump)
898 buffer_desc->dump(data, length, &buffer_desc->rect, output);
899 else
901 if (buffer_desc->length == -1)
903 ret = WriteFile(output, &length, sizeof(length), &written, NULL);
904 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
905 ok(written == sizeof(length), "written %lu bytes\n", written);
908 ret = WriteFile(output, data, length, &written, NULL);
909 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
910 ok(written == length, "written %lu bytes\n", written);
913 hr = IMFMediaBuffer_Unlock(buffer);
914 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
917 static void dump_mf_sample(IMFSample *sample, const struct sample_desc *sample_desc, HANDLE output)
919 enum_mf_media_buffers(sample, sample_desc, dump_mf_media_buffer, output);
922 static void dump_mf_sample_collection(IMFCollection *samples, const struct sample_desc *collection_desc,
923 const WCHAR *output_filename)
925 WCHAR path[MAX_PATH];
926 HANDLE output;
928 GetTempPathW(ARRAY_SIZE(path), path);
929 lstrcatW(path, output_filename);
931 output = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
932 ok(output != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
934 enum_mf_samples(samples, collection_desc, dump_mf_sample, output);
936 trace("created %s\n", debugstr_w(path));
937 CloseHandle(output);
940 #define check_mf_media_buffer(a, b, c) check_mf_media_buffer_(__FILE__, __LINE__, a, b, c)
941 static DWORD check_mf_media_buffer_(const char *file, int line, IMFMediaBuffer *buffer, const struct buffer_desc *expect,
942 const BYTE **expect_data, DWORD *expect_data_len)
944 DWORD length, diff = 0, expect_length = expect->length;
945 HRESULT hr;
946 BYTE *data;
948 if (expect_length == -1)
950 expect_length = *(DWORD *)*expect_data;
951 *expect_data = *expect_data + sizeof(DWORD);
952 *expect_data_len = *expect_data_len - sizeof(DWORD);
955 hr = IMFMediaBuffer_Lock(buffer, &data, NULL, &length);
956 ok_(file, line)(hr == S_OK, "Lock returned %#lx\n", hr);
957 todo_wine_if(expect->todo_length)
958 ok_(file, line)(length == expect_length, "got length %#lx\n", length);
960 if (*expect_data_len < length)
961 todo_wine_if(expect->todo_length)
962 ok_(file, line)(0, "missing %#lx bytes\n", length - *expect_data_len);
963 else if (!expect->compare)
964 diff = compare_bytes(data, &length, NULL, *expect_data);
965 else
966 diff = expect->compare(data, &length, &expect->rect, *expect_data);
968 hr = IMFMediaBuffer_Unlock(buffer);
969 ok_(file, line)(hr == S_OK, "Unlock returned %#lx\n", hr);
971 *expect_data = *expect_data + min(length, *expect_data_len);
972 *expect_data_len = *expect_data_len - min(length, *expect_data_len);
974 return diff;
977 struct check_mf_sample_context
979 DWORD total_length;
980 const BYTE *data;
981 DWORD data_len;
982 DWORD diff;
983 const char *file;
984 int line;
987 static void check_mf_sample_buffer(IMFMediaBuffer *buffer, const struct buffer_desc *expect, void *context)
989 struct check_mf_sample_context *ctx = context;
990 DWORD expect_length = expect->length == -1 ? *(DWORD *)ctx->data : expect->length;
991 ctx->diff += check_mf_media_buffer_(ctx->file, ctx->line, buffer, expect, &ctx->data, &ctx->data_len);
992 ctx->total_length += expect_length;
995 #define check_mf_sample(a, b, c, d) check_mf_sample_(__FILE__, __LINE__, a, b, c, d)
996 static DWORD check_mf_sample_(const char *file, int line, IMFSample *sample, const struct sample_desc *expect,
997 const BYTE **expect_data, DWORD *expect_data_len)
999 struct check_mf_sample_context ctx = {.data = *expect_data, .data_len = *expect_data_len, .file = file, .line = line};
1000 DWORD buffer_count, total_length, sample_flags;
1001 LONGLONG timestamp;
1002 HRESULT hr;
1004 if (expect->attributes)
1005 check_attributes_(file, line, (IMFAttributes *)sample, expect->attributes, -1);
1007 buffer_count = 0xdeadbeef;
1008 hr = IMFSample_GetBufferCount(sample, &buffer_count);
1009 ok_(file, line)(hr == S_OK, "GetBufferCount returned %#lx\n", hr);
1010 ok_(file, line)(buffer_count == expect->buffer_count,
1011 "got %lu buffers\n", buffer_count);
1013 sample_flags = 0xdeadbeef;
1014 hr = IMFSample_GetSampleFlags(sample, &sample_flags);
1015 ok_(file, line)(hr == S_OK, "GetSampleFlags returned %#lx\n", hr);
1016 ok_(file, line)(sample_flags == 0,
1017 "got sample flags %#lx\n", sample_flags);
1019 timestamp = 0xdeadbeef;
1020 hr = IMFSample_GetSampleTime(sample, &timestamp);
1021 ok_(file, line)(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
1022 todo_wine_if(expect->todo_time && timestamp == expect->todo_time)
1023 ok_(file, line)(llabs(timestamp - expect->sample_time) <= 50,
1024 "got sample time %I64d\n", timestamp);
1026 timestamp = 0xdeadbeef;
1027 hr = IMFSample_GetSampleDuration(sample, &timestamp);
1028 ok_(file, line)(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
1029 todo_wine_if(expect->todo_length)
1030 ok_(file, line)(llabs(timestamp - expect->sample_duration) <= 1,
1031 "got sample duration %I64d\n", timestamp);
1033 enum_mf_media_buffers(sample, expect, check_mf_sample_buffer, &ctx);
1035 total_length = 0xdeadbeef;
1036 hr = IMFSample_GetTotalLength(sample, &total_length);
1037 ok_(file, line)(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
1038 todo_wine_if(expect->todo_length)
1039 ok_(file, line)(total_length == ctx.total_length,
1040 "got total length %#lx\n", total_length);
1041 ok_(file, line)(*expect_data_len >= ctx.total_length,
1042 "missing %#lx data\n", ctx.total_length - *expect_data_len);
1044 *expect_data = ctx.data;
1045 *expect_data_len = ctx.data_len;
1047 return ctx.diff / buffer_count;
1050 static void check_mf_sample_collection_enum(IMFSample *sample, const struct sample_desc *expect, void *context)
1052 struct check_mf_sample_context *ctx = context;
1053 ctx->diff += check_mf_sample_(ctx->file, ctx->line, sample, expect, &ctx->data, &ctx->data_len);
1056 DWORD check_mf_sample_collection_(const char *file, int line, IMFCollection *samples,
1057 const struct sample_desc *expect_samples, const WCHAR *expect_data_filename)
1059 struct check_mf_sample_context ctx = {.file = file, .line = line};
1060 DWORD count;
1061 HRESULT hr;
1063 load_resource(expect_data_filename, &ctx.data, &ctx.data_len);
1064 enum_mf_samples(samples, expect_samples, check_mf_sample_collection_enum, &ctx);
1066 dump_mf_sample_collection(samples, expect_samples, expect_data_filename);
1068 hr = IMFCollection_GetElementCount(samples, &count);
1069 ok_(file, line)(hr == S_OK, "GetElementCount returned %#lx\n", hr);
1071 return ctx.diff / count;
1074 #define check_video_info_header(a, b) check_video_info_header_(__LINE__, a, b)
1075 static void check_video_info_header_(int line, VIDEOINFOHEADER *info, const VIDEOINFOHEADER *expected)
1077 ok_(__FILE__, line)(info->rcSource.left == expected->rcSource.left
1078 && info->rcSource.top == expected->rcSource.top
1079 && info->rcSource.right == expected->rcSource.right
1080 && info->rcSource.bottom == expected->rcSource.bottom,
1081 "Got unexpected rcSource {%ld, %ld, %ld, %ld}, expected {%ld, %ld, %ld, %ld}.\n",
1082 info->rcSource.left, info->rcSource.top, info->rcSource.right, info->rcSource.bottom,
1083 expected->rcSource.left, expected->rcSource.top, expected->rcSource.right, expected->rcSource.bottom);
1084 ok_(__FILE__, line)(info->rcTarget.left == expected->rcTarget.left
1085 && info->rcTarget.top == expected->rcTarget.top
1086 && info->rcTarget.right == expected->rcTarget.right
1087 && info->rcTarget.bottom == expected->rcTarget.bottom,
1088 "Got unexpected rcTarget {%ld, %ld, %ld, %ld}, expected {%ld, %ld, %ld, %ld}.\n",
1089 info->rcTarget.left, info->rcTarget.top, info->rcTarget.right, info->rcTarget.bottom,
1090 expected->rcTarget.left, expected->rcTarget.top, expected->rcTarget.right, expected->rcTarget.bottom);
1091 ok_(__FILE__, line)(info->dwBitRate == expected->dwBitRate,
1092 "Got unexpected dwBitRate %lu, expected %lu.\n",
1093 info->dwBitRate, expected->dwBitRate);
1094 ok_(__FILE__, line)(info->dwBitErrorRate == expected->dwBitErrorRate,
1095 "Got unexpected dwBitErrorRate %lu, expected %lu.\n",
1096 info->dwBitErrorRate, expected->dwBitErrorRate);
1097 ok_(__FILE__, line)(info->AvgTimePerFrame == expected->AvgTimePerFrame,
1098 "Got unexpected AvgTimePerFrame %I64d, expected %I64d.\n",
1099 info->AvgTimePerFrame, expected->AvgTimePerFrame);
1100 ok_(__FILE__, line)(info->bmiHeader.biSize == expected->bmiHeader.biSize,
1101 "Got unexpected bmiHeader.biSize %lu, expected %lu.\n",
1102 info->bmiHeader.biSize, expected->bmiHeader.biSize);
1103 ok_(__FILE__, line)(info->bmiHeader.biWidth == expected->bmiHeader.biWidth,
1104 "Got unexpected bmiHeader.biWidth %ld, expected %ld.\n",
1105 info->bmiHeader.biWidth, expected->bmiHeader.biWidth);
1106 ok_(__FILE__, line)(info->bmiHeader.biHeight == expected->bmiHeader.biHeight,
1107 "Got unexpected bmiHeader.biHeight %ld, expected %ld.\n",
1108 info->bmiHeader.biHeight, expected->bmiHeader.biHeight);
1109 ok_(__FILE__, line)(info->bmiHeader.biPlanes == expected->bmiHeader.biPlanes,
1110 "Got unexpected bmiHeader.biPlanes %u, expected %u.\n",
1111 info->bmiHeader.biPlanes, expected->bmiHeader.biPlanes);
1112 ok_(__FILE__, line)(info->bmiHeader.biBitCount == expected->bmiHeader.biBitCount,
1113 "Got unexpected bmiHeader.biBitCount %u, expected %u.\n",
1114 info->bmiHeader.biBitCount, expected->bmiHeader.biBitCount);
1115 ok_(__FILE__, line)(info->bmiHeader.biCompression == expected->bmiHeader.biCompression,
1116 "Got unexpected bmiHeader.biCompression %#lx, expected %#lx.\n",
1117 info->bmiHeader.biCompression, expected->bmiHeader.biCompression);
1118 ok_(__FILE__, line)(info->bmiHeader.biSizeImage == expected->bmiHeader.biSizeImage,
1119 "Got unexpected bmiHeader.biSizeImage %lu, expected %lu.\n",
1120 info->bmiHeader.biSizeImage, expected->bmiHeader.biSizeImage);
1121 ok_(__FILE__, line)(info->bmiHeader.biXPelsPerMeter == expected->bmiHeader.biXPelsPerMeter,
1122 "Got unexpected bmiHeader.biXPelsPerMeter %ld, expected %ld.\n",
1123 info->bmiHeader.biXPelsPerMeter, expected->bmiHeader.biXPelsPerMeter);
1124 ok_(__FILE__, line)(info->bmiHeader.biYPelsPerMeter == expected->bmiHeader.biYPelsPerMeter,
1125 "Got unexpected bmiHeader.xxxxxx %ld, expected %ld.\n",
1126 info->bmiHeader.biYPelsPerMeter, expected->bmiHeader.biYPelsPerMeter);
1127 ok_(__FILE__, line)(info->bmiHeader.biClrUsed == expected->bmiHeader.biClrUsed,
1128 "Got unexpected bmiHeader.biClrUsed %lu, expected %lu.\n",
1129 info->bmiHeader.biClrUsed, expected->bmiHeader.biClrUsed);
1130 ok_(__FILE__, line)(info->bmiHeader.biClrImportant == expected->bmiHeader.biClrImportant,
1131 "Got unexpected bmiHeader.biClrImportant %lu, expected %lu.\n",
1132 info->bmiHeader.biClrImportant, expected->bmiHeader.biClrImportant);
1135 #define check_dmo_media_type(a, b) check_dmo_media_type_(__LINE__, a, b)
1136 static void check_dmo_media_type_(int line, DMO_MEDIA_TYPE *media_type, const DMO_MEDIA_TYPE *expected)
1138 ok_(__FILE__, line)(IsEqualGUID(&media_type->majortype, &expected->majortype),
1139 "Got unexpected majortype %s, expected %s.\n",
1140 debugstr_guid(&media_type->majortype), debugstr_guid(&expected->majortype));
1141 ok_(__FILE__, line)(IsEqualGUID(&media_type->subtype, &expected->subtype),
1142 "Got unexpected subtype %s, expected %s.\n",
1143 debugstr_guid(&media_type->subtype), debugstr_guid(&expected->subtype));
1144 ok_(__FILE__, line)(media_type->bFixedSizeSamples == expected->bFixedSizeSamples,
1145 "Got unexpected bFixedSizeSamples %d, expected %d.\n",
1146 media_type->bFixedSizeSamples, expected->bFixedSizeSamples);
1147 ok_(__FILE__, line)(media_type->bTemporalCompression == expected->bTemporalCompression,
1148 "Got unexpected bTemporalCompression %d, expected %d.\n",
1149 media_type->bTemporalCompression, expected->bTemporalCompression);
1150 ok_(__FILE__, line)(media_type->lSampleSize == expected->lSampleSize,
1151 "Got unexpected lSampleSize %lu, expected %lu.\n",
1152 media_type->lSampleSize, expected->lSampleSize);
1153 ok_(__FILE__, line)(IsEqualGUID(&media_type->formattype, &expected->formattype),
1154 "Got unexpected formattype %s.\n",
1155 debugstr_guid(&media_type->formattype));
1156 ok_(__FILE__, line)(media_type->pUnk == NULL, "Got unexpected pUnk %p.\n", media_type->pUnk);
1157 ok_(__FILE__, line)(media_type->cbFormat == expected->cbFormat,
1158 "Got unexpected cbFormat %lu, expected %lu.\n",
1159 media_type->cbFormat, expected->cbFormat);
1161 if (expected->pbFormat)
1163 ok_(__FILE__, line)(!!media_type->pbFormat, "Got NULL pbFormat.\n");
1164 if (!media_type->pbFormat)
1165 return;
1167 if (IsEqualGUID(&media_type->formattype, &FORMAT_VideoInfo)
1168 && IsEqualGUID(&expected->formattype, &FORMAT_VideoInfo))
1169 check_video_info_header((VIDEOINFOHEADER *)media_type->pbFormat, (VIDEOINFOHEADER *)expected->pbFormat);
1173 static void check_dmo_get_input_type(IMediaObject *media_object, const DMO_MEDIA_TYPE *expected_type, ULONG count)
1175 DMO_MEDIA_TYPE media_type;
1176 HRESULT hr;
1177 DWORD i;
1179 hr = IMediaObject_GetInputType(media_object, 1, 0, NULL);
1180 ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetInputType returned unexpected hr %#lx.\n", hr);
1181 hr = IMediaObject_GetInputType(media_object, 1, 0, &media_type);
1182 ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetInputType returned unexpected hr %#lx.\n", hr);
1183 hr = IMediaObject_GetInputType(media_object, 1, count, &media_type);
1184 ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetInputType returned unexpected hr %#lx.\n", hr);
1185 hr = IMediaObject_GetInputType(media_object, 0, count, &media_type);
1186 ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned unexpected hr %#lx.\n", hr);
1187 hr = IMediaObject_GetInputType(media_object, 0, count, NULL);
1188 ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned unexpected hr %#lx.\n", hr);
1189 hr = IMediaObject_GetInputType(media_object, 0, 0xdeadbeef, NULL);
1190 ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned unexpected hr %#lx.\n", hr);
1191 hr = IMediaObject_GetInputType(media_object, 0, count - 1, NULL);
1192 ok(hr == S_OK, "GetInputType returned unexpected hr %#lx.\n", hr);
1193 hr = IMediaObject_GetInputType(media_object, 0, count - 1, &media_type);
1194 ok(hr == S_OK, "GetInputType returned unexpected hr %#lx.\n", hr);
1195 if (hr == S_OK)
1196 MoFreeMediaType(&media_type);
1198 i = -1;
1199 while (SUCCEEDED(hr = IMediaObject_GetInputType(media_object, 0, ++i, &media_type)))
1201 winetest_push_context("in %lu", i);
1202 check_dmo_media_type(&media_type, &expected_type[i]);
1203 MoFreeMediaType(&media_type);
1204 winetest_pop_context();
1207 ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned unexpected hr %#lx.\n", hr);
1208 ok(i == count, "%lu types.\n", i);
1211 static void check_dmo_get_output_type(IMediaObject *media_object, const DMO_MEDIA_TYPE *expected_type, ULONG count)
1213 DMO_MEDIA_TYPE media_type;
1214 HRESULT hr;
1215 DWORD i;
1217 hr = IMediaObject_GetOutputType(media_object, 1, 0, NULL);
1218 ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetOutputType returned unexpected hr %#lx.\n", hr);
1219 hr = IMediaObject_GetOutputType(media_object, 1, 0, &media_type);
1220 ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetOutputType returned unexpected hr %#lx.\n", hr);
1221 hr = IMediaObject_GetOutputType(media_object, 1, count, &media_type);
1222 ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetOutputType returned unexpected hr %#lx.\n", hr);
1223 hr = IMediaObject_GetOutputType(media_object, 0, count, &media_type);
1224 ok(hr == DMO_E_NO_MORE_ITEMS, "GetOutputType returned unexpected hr %#lx.\n", hr);
1225 hr = IMediaObject_GetOutputType(media_object, 0, count, NULL);
1226 ok(hr == DMO_E_NO_MORE_ITEMS || broken(hr == S_OK), "GetOutputType returned unexpected hr %#lx.\n", hr);
1227 hr = IMediaObject_GetOutputType(media_object, 0, 0xdeadbeef, NULL);
1228 ok(hr == DMO_E_NO_MORE_ITEMS || broken(hr == S_OK), "GetOutputType returned unexpected hr %#lx.\n", hr);
1229 hr = IMediaObject_GetOutputType(media_object, 0, count - 1, NULL);
1230 ok(hr == S_OK, "GetOutputType returned unexpected hr %#lx.\n", hr);
1231 hr = IMediaObject_GetOutputType(media_object, 0, count - 1, &media_type);
1232 ok(hr == S_OK, "GetOutputType returned unexpected hr %#lx.\n", hr);
1233 if (hr == S_OK)
1234 MoFreeMediaType(&media_type);
1236 i = -1;
1237 while (SUCCEEDED(hr = IMediaObject_GetOutputType(media_object, 0, ++i, &media_type)))
1239 winetest_push_context("out %lu", i);
1240 check_dmo_media_type(&media_type, &expected_type[i]);
1241 MoFreeMediaType(&media_type);
1242 winetest_pop_context();
1245 ok(hr == DMO_E_NO_MORE_ITEMS, "GetOutputType returned unexpected hr %#lx.\n", hr);
1246 ok(i == count, "%lu types.\n", i);
1249 static HRESULT WINAPI test_unk_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
1251 if (IsEqualIID(riid, &IID_IUnknown))
1253 *obj = iface;
1254 IUnknown_AddRef(iface);
1255 return S_OK;
1258 *obj = NULL;
1259 return E_NOINTERFACE;
1262 static ULONG WINAPI test_unk_AddRef(IUnknown *iface)
1264 return 2;
1267 static ULONG WINAPI test_unk_Release(IUnknown *iface)
1269 return 1;
1272 static const IUnknownVtbl test_unk_vtbl =
1274 test_unk_QueryInterface,
1275 test_unk_AddRef,
1276 test_unk_Release,
1279 static BOOL is_supported_video_type(const GUID *guid)
1281 return IsEqualGUID(guid, &MFVideoFormat_L8)
1282 || IsEqualGUID(guid, &MFVideoFormat_L16)
1283 || IsEqualGUID(guid, &MFVideoFormat_D16)
1284 || IsEqualGUID(guid, &MFVideoFormat_IYUV)
1285 || IsEqualGUID(guid, &MFVideoFormat_YV12)
1286 || IsEqualGUID(guid, &MFVideoFormat_NV12)
1287 || IsEqualGUID(guid, &MFVideoFormat_NV21)
1288 || IsEqualGUID(guid, &MFVideoFormat_420O)
1289 || IsEqualGUID(guid, &MFVideoFormat_P010)
1290 || IsEqualGUID(guid, &MFVideoFormat_P016)
1291 || IsEqualGUID(guid, &MFVideoFormat_UYVY)
1292 || IsEqualGUID(guid, &MFVideoFormat_YUY2)
1293 || IsEqualGUID(guid, &MFVideoFormat_P208)
1294 || IsEqualGUID(guid, &MFVideoFormat_NV11)
1295 || IsEqualGUID(guid, &MFVideoFormat_AYUV)
1296 || IsEqualGUID(guid, &MFVideoFormat_ARGB32)
1297 || IsEqualGUID(guid, &MFVideoFormat_RGB32)
1298 || IsEqualGUID(guid, &MFVideoFormat_A2R10G10B10)
1299 || IsEqualGUID(guid, &MFVideoFormat_A16B16G16R16F)
1300 || IsEqualGUID(guid, &MFVideoFormat_RGB24)
1301 || IsEqualGUID(guid, &MFVideoFormat_I420)
1302 || IsEqualGUID(guid, &MFVideoFormat_YVYU)
1303 || IsEqualGUID(guid, &MFVideoFormat_RGB555)
1304 || IsEqualGUID(guid, &MFVideoFormat_RGB565)
1305 || IsEqualGUID(guid, &MFVideoFormat_RGB8)
1306 || IsEqualGUID(guid, &MFVideoFormat_Y216)
1307 || IsEqualGUID(guid, &MFVideoFormat_v410)
1308 || IsEqualGUID(guid, &MFVideoFormat_Y41P)
1309 || IsEqualGUID(guid, &MFVideoFormat_Y41T)
1310 || IsEqualGUID(guid, &MFVideoFormat_Y42T)
1311 || IsEqualGUID(guid, &MFVideoFormat_ABGR32);
1314 static BOOL is_sample_copier_available_type(IMFMediaType *type)
1316 GUID major = { 0 };
1317 UINT32 count;
1318 HRESULT hr;
1320 hr = IMFMediaType_GetMajorType(type, &major);
1321 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
1323 hr = IMFMediaType_GetCount(type, &count);
1324 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
1325 ok(count == 1, "Unexpected attribute count %u.\n", count);
1327 return IsEqualGUID(&major, &MFMediaType_Video) || IsEqualGUID(&major, &MFMediaType_Audio);
1330 static void test_sample_copier(void)
1332 static const struct attribute_desc expect_transform_attributes[] =
1334 ATTR_UINT32(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, 1),
1335 {0},
1337 const MFT_OUTPUT_STREAM_INFO initial_output_info = {0}, output_info = {.cbSize = 16 * 16};
1338 const MFT_INPUT_STREAM_INFO initial_input_info = {0}, input_info = {.cbSize = 16 * 16};
1339 IMFMediaType *mediatype, *mediatype2;
1340 IMFSample *sample, *client_sample;
1341 IMFMediaBuffer *media_buffer;
1342 MFT_INPUT_STREAM_INFO info;
1343 DWORD flags, output_status;
1344 IMFTransform *copier;
1345 HRESULT hr;
1346 LONG ref;
1348 if (!pMFCreateSampleCopierMFT)
1350 win_skip("MFCreateSampleCopierMFT() is not available.\n");
1351 return;
1354 winetest_push_context("copier");
1356 hr = pMFCreateSampleCopierMFT(&copier);
1357 ok(hr == S_OK, "Failed to create sample copier, hr %#lx.\n", hr);
1359 check_interface(copier, &IID_IMFTransform, TRUE);
1360 check_interface(copier, &IID_IMediaObject, FALSE);
1361 check_interface(copier, &IID_IPropertyStore, FALSE);
1362 check_interface(copier, &IID_IPropertyBag, FALSE);
1364 check_mft_optional_methods(copier, 1);
1365 check_mft_get_attributes(copier, expect_transform_attributes, FALSE);
1367 /* Available types. */
1368 hr = IMFTransform_GetInputAvailableType(copier, 0, 0, &mediatype);
1369 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1370 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
1371 IMFMediaType_Release(mediatype);
1373 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype);
1374 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1375 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
1376 IMFMediaType_Release(mediatype);
1378 hr = IMFTransform_GetInputAvailableType(copier, 0, 2, &mediatype);
1379 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
1381 hr = IMFTransform_GetInputAvailableType(copier, 1, 0, &mediatype);
1382 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
1384 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype);
1385 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
1387 hr = IMFTransform_GetOutputAvailableType(copier, 1, 0, &mediatype);
1388 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
1390 check_mft_get_input_current_type(copier, NULL);
1391 check_mft_get_output_current_type(copier, NULL);
1393 hr = MFCreateSample(&sample);
1394 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
1396 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
1397 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
1399 hr = MFCreateMediaType(&mediatype);
1400 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
1402 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
1403 ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr);
1405 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
1406 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1408 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8);
1409 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1411 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
1412 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1414 check_mft_get_input_stream_info(copier, S_OK, &initial_input_info);
1415 check_mft_get_output_stream_info(copier, S_OK, &initial_output_info);
1417 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
1418 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
1420 memset(&info, 0xcd, sizeof(info));
1421 hr = IMFTransform_GetInputStreamInfo(copier, 0, &info);
1422 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
1423 check_member(info, initial_input_info, "%I64d", hnsMaxLatency);
1424 check_member(info, initial_input_info, "%#lx", dwFlags);
1425 todo_wine
1426 check_member(info, initial_input_info, "%#lx", cbSize);
1427 check_member(info, initial_input_info, "%#lx", cbMaxLookahead);
1428 check_member(info, initial_input_info, "%#lx", cbAlignment);
1429 check_mft_get_output_stream_info(copier, S_OK, &output_info);
1431 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
1432 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
1433 IMFMediaType_Release(mediatype2);
1435 check_mft_get_input_current_type(copier, NULL);
1437 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
1438 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
1440 /* Setting input type resets output type. */
1441 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
1442 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1443 IMFMediaType_Release(mediatype2);
1445 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
1446 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
1448 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
1449 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
1451 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype2);
1452 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1453 ok(is_sample_copier_available_type(mediatype2), "Unexpected type.\n");
1454 IMFMediaType_Release(mediatype2);
1456 check_mft_get_input_stream_info(copier, S_OK, &input_info);
1457 check_mft_get_output_stream_info(copier, S_OK, &output_info);
1459 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype2);
1460 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1461 hr = IMFMediaType_IsEqual(mediatype2, mediatype, &flags);
1462 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1463 IMFMediaType_Release(mediatype2);
1465 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
1466 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
1467 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected flags %#lx.\n", flags);
1469 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2);
1470 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
1471 IMFMediaType_Release(mediatype2);
1473 hr = IMFTransform_GetOutputStatus(copier, &flags);
1474 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
1476 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
1477 ok(hr == S_OK, "Failed to set output type, hr %#lx.\n", hr);
1479 hr = IMFTransform_GetOutputStatus(copier, &flags);
1480 ok(hr == S_OK, "Failed to get output status, hr %#lx.\n", hr);
1481 ok(!flags, "Unexpected flags %#lx.\n", flags);
1483 /* Pushing samples. */
1484 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
1485 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
1487 hr = IMFSample_AddBuffer(sample, media_buffer);
1488 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
1489 IMFMediaBuffer_Release(media_buffer);
1491 EXPECT_REF(sample, 1);
1492 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
1493 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
1494 EXPECT_REF(sample, 2);
1496 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
1497 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
1498 ok(!flags, "Unexpected flags %#lx.\n", flags);
1500 hr = IMFTransform_GetOutputStatus(copier, &flags);
1501 ok(hr == S_OK, "Failed to get output status, hr %#lx.\n", hr);
1502 ok(flags == MFT_OUTPUT_STATUS_SAMPLE_READY, "Unexpected flags %#lx.\n", flags);
1504 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
1505 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#lx.\n", hr);
1507 check_mft_get_input_stream_info(copier, S_OK, &input_info);
1508 check_mft_get_output_stream_info(copier, S_OK, &output_info);
1510 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
1511 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
1513 hr = MFCreateSample(&client_sample);
1514 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
1516 hr = IMFSample_AddBuffer(client_sample, media_buffer);
1517 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
1518 IMFMediaBuffer_Release(media_buffer);
1520 hr = check_mft_process_output(copier, client_sample, &output_status);
1521 ok(hr == S_OK, "Failed to get output, hr %#lx.\n", hr);
1522 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
1523 EXPECT_REF(sample, 1);
1525 hr = check_mft_process_output(copier, client_sample, &output_status);
1526 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Failed to get output, hr %#lx.\n", hr);
1527 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
1529 /* Flushing. */
1530 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
1531 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
1532 EXPECT_REF(sample, 2);
1534 hr = IMFTransform_ProcessMessage(copier, MFT_MESSAGE_COMMAND_FLUSH, 0);
1535 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
1537 ref = IMFSample_Release(sample);
1538 ok(ref == 0, "Release returned %ld\n", ref);
1539 ref = IMFSample_Release(client_sample);
1540 ok(ref == 0, "Release returned %ld\n", ref);
1542 ref = IMFTransform_Release(copier);
1543 ok(ref == 0, "Release returned %ld\n", ref);
1544 ref = IMFMediaType_Release(mediatype);
1545 ok(ref == 0, "Release returned %ld\n", ref);
1547 winetest_pop_context();
1550 struct sample_metadata
1552 unsigned int flags;
1553 LONGLONG duration;
1554 LONGLONG time;
1557 static void sample_copier_process(IMFTransform *copier, IMFMediaBuffer *input_buffer,
1558 IMFMediaBuffer *output_buffer, const struct sample_metadata *md)
1560 static const struct sample_metadata zero_md = { 0, ~0u, ~0u };
1561 IMFSample *input_sample, *output_sample;
1562 DWORD flags, output_status;
1563 LONGLONG time;
1564 HRESULT hr;
1565 LONG ref;
1567 hr = MFCreateSample(&input_sample);
1568 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
1570 if (md)
1572 hr = IMFSample_SetSampleFlags(input_sample, md->flags);
1573 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1575 hr = IMFSample_SetSampleTime(input_sample, md->time);
1576 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1578 hr = IMFSample_SetSampleDuration(input_sample, md->duration);
1579 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1582 hr = MFCreateSample(&output_sample);
1583 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
1585 hr = IMFSample_SetSampleFlags(output_sample, ~0u);
1586 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1588 hr = IMFSample_SetSampleTime(output_sample, ~0u);
1589 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1591 hr = IMFSample_SetSampleDuration(output_sample, ~0u);
1592 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1594 hr = IMFSample_AddBuffer(input_sample, input_buffer);
1595 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1597 hr = IMFSample_AddBuffer(output_sample, output_buffer);
1598 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1600 hr = IMFTransform_ProcessInput(copier, 0, input_sample, 0);
1601 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
1603 hr = check_mft_process_output(copier, output_sample, &output_status);
1604 ok(hr == S_OK, "Failed to get output, hr %#lx.\n", hr);
1605 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
1607 if (!md) md = &zero_md;
1609 hr = IMFSample_GetSampleFlags(output_sample, &flags);
1610 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1611 ok(md->flags == flags, "Unexpected flags.\n");
1612 hr = IMFSample_GetSampleTime(output_sample, &time);
1613 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1614 ok(md->time == time, "Unexpected time.\n");
1615 hr = IMFSample_GetSampleDuration(output_sample, &time);
1616 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1617 ok(md->duration == time, "Unexpected duration.\n");
1619 ref = IMFSample_Release(input_sample);
1620 ok(ref == 0, "Release returned %ld\n", ref);
1621 ref = IMFSample_Release(output_sample);
1622 ok(ref == 0, "Release returned %ld\n", ref);
1625 static void test_sample_copier_output_processing(void)
1627 IMFMediaBuffer *input_buffer, *output_buffer;
1628 MFT_OUTPUT_STREAM_INFO output_info;
1629 struct sample_metadata md;
1630 IMFMediaType *mediatype;
1631 IMFTransform *copier;
1632 DWORD max_length;
1633 HRESULT hr;
1634 BYTE *ptr;
1635 LONG ref;
1637 if (!pMFCreateSampleCopierMFT)
1638 return;
1640 hr = pMFCreateSampleCopierMFT(&copier);
1641 ok(hr == S_OK, "Failed to create sample copier, hr %#lx.\n", hr);
1643 /* Configure for 16 x 16 of D3DFMT_X8R8G8B8. */
1644 hr = MFCreateMediaType(&mediatype);
1645 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
1647 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
1648 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1650 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
1651 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1653 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
1654 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1656 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
1657 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
1659 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
1660 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
1662 /* Source and destination are linear buffers, destination is twice as large. */
1663 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
1664 ok(hr == S_OK, "Failed to get output info, hr %#lx.\n", hr);
1666 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &output_buffer);
1667 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
1669 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
1670 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1671 memset(ptr, 0xcc, max_length);
1672 hr = IMFMediaBuffer_Unlock(output_buffer);
1673 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1675 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &input_buffer);
1676 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
1678 hr = IMFMediaBuffer_Lock(input_buffer, &ptr, &max_length, NULL);
1679 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1680 memset(ptr, 0xaa, max_length);
1681 hr = IMFMediaBuffer_Unlock(input_buffer);
1682 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1683 hr = IMFMediaBuffer_SetCurrentLength(input_buffer, 4);
1684 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1686 sample_copier_process(copier, input_buffer, output_buffer, NULL);
1688 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
1689 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1690 ok(ptr[0] == 0xaa && ptr[4] == 0xcc, "Unexpected buffer contents.\n");
1692 hr = IMFMediaBuffer_Unlock(output_buffer);
1693 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1695 md.flags = 123;
1696 md.time = 10;
1697 md.duration = 2;
1698 sample_copier_process(copier, input_buffer, output_buffer, &md);
1700 ref = IMFMediaBuffer_Release(input_buffer);
1701 ok(ref == 0, "Release returned %ld\n", ref);
1702 ref = IMFMediaBuffer_Release(output_buffer);
1703 ok(ref == 0, "Release returned %ld\n", ref);
1705 ref = IMFTransform_Release(copier);
1706 ok(ref == 0, "Release returned %ld\n", ref);
1707 ref = IMFMediaType_Release(mediatype);
1708 ok(ref == 0, "Release returned %ld\n", ref);
1711 static IMFSample *create_sample(const BYTE *data, ULONG size)
1713 IMFMediaBuffer *media_buffer;
1714 IMFSample *sample;
1715 DWORD length;
1716 BYTE *buffer;
1717 HRESULT hr;
1718 ULONG ret;
1720 hr = MFCreateSample(&sample);
1721 ok(hr == S_OK, "MFCreateSample returned %#lx\n", hr);
1722 hr = MFCreateMemoryBuffer(size, &media_buffer);
1723 ok(hr == S_OK, "MFCreateMemoryBuffer returned %#lx\n", hr);
1724 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
1725 ok(hr == S_OK, "Lock returned %#lx\n", hr);
1726 ok(length == 0, "got length %lu\n", length);
1727 if (!data) memset(buffer, 0xcd, size);
1728 else memcpy(buffer, data, size);
1729 hr = IMFMediaBuffer_Unlock(media_buffer);
1730 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
1731 hr = IMFMediaBuffer_SetCurrentLength(media_buffer, data ? size : 0);
1732 ok(hr == S_OK, "SetCurrentLength returned %#lx\n", hr);
1733 hr = IMFSample_AddBuffer(sample, media_buffer);
1734 ok(hr == S_OK, "AddBuffer returned %#lx\n", hr);
1735 ret = IMFMediaBuffer_Release(media_buffer);
1736 ok(ret == 1, "Release returned %lu\n", ret);
1738 return sample;
1741 static const BYTE aac_codec_data[14] = {0x00,0x00,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x08};
1743 static void test_aac_encoder(void)
1745 const GUID *const class_id = &CLSID_AACMFTEncoder;
1746 const struct transform_info expect_mft_info =
1748 .name = L"Microsoft AAC Audio Encoder MFT",
1749 .major_type = &MFMediaType_Audio,
1750 .inputs =
1752 {.subtype = &MFAudioFormat_PCM},
1754 .outputs =
1756 {.subtype = &MFAudioFormat_AAC},
1760 static const struct attribute_desc input_type_desc[] =
1762 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
1763 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM, .required = TRUE),
1764 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1, .required = TRUE),
1765 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
1766 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .required = TRUE),
1767 {0},
1769 const struct attribute_desc output_type_desc[] =
1771 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
1772 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC, .required = TRUE),
1773 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1, .required = TRUE),
1774 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
1775 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .required = TRUE),
1776 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 12000, .required = TRUE),
1777 {0},
1780 static const struct attribute_desc expect_input_type_desc[] =
1782 ATTR_GUID(MF_MT_AM_FORMAT_TYPE, FORMAT_WaveFormatEx),
1783 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1784 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1785 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
1786 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1787 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2),
1788 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1789 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 * 2),
1790 ATTR_UINT32(MF_MT_AVG_BITRATE, 44100 * 2 * 8),
1791 ATTR_UINT32(MF_MT_COMPRESSED, 0),
1792 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
1793 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
1794 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
1795 {0},
1797 const struct attribute_desc expect_output_type_desc[] =
1799 ATTR_GUID(MF_MT_AM_FORMAT_TYPE, FORMAT_WaveFormatEx),
1800 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1801 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC),
1802 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
1803 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1804 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1805 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1806 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 12000),
1807 ATTR_UINT32(MF_MT_AVG_BITRATE, 96000),
1808 ATTR_UINT32(MF_MT_COMPRESSED, 1),
1809 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 0),
1810 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
1811 ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 41),
1812 ATTR_UINT32(MF_MT_AAC_PAYLOAD_TYPE, 0),
1813 ATTR_BLOB(MF_MT_USER_DATA, aac_codec_data, sizeof(aac_codec_data)),
1814 {0},
1816 const MFT_OUTPUT_STREAM_INFO initial_output_info = {0}, output_info = {.cbSize = 0x600};
1817 const MFT_INPUT_STREAM_INFO input_info = {0};
1819 const struct buffer_desc output_buffer_desc[] =
1821 {.length = -1 /* variable */},
1823 const struct attribute_desc output_sample_attributes[] =
1825 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
1826 {0},
1828 const struct sample_desc output_sample_desc[] =
1831 .repeat_count = 88,
1832 .attributes = output_sample_attributes,
1833 .sample_time = 0, .sample_duration = 113823,
1834 .buffer_count = 1, .buffers = output_buffer_desc,
1838 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_AAC};
1839 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_PCM};
1840 IMFSample *input_sample, *output_sample;
1841 IMFCollection *output_samples;
1842 ULONG i, ret, audio_data_len;
1843 DWORD length, output_status;
1844 IMFTransform *transform;
1845 const BYTE *audio_data;
1846 HRESULT hr;
1847 LONG ref;
1849 hr = CoInitialize(NULL);
1850 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
1852 winetest_push_context("aacenc");
1854 if (!check_mft_enum(MFT_CATEGORY_AUDIO_ENCODER, &input_type, &output_type, class_id))
1855 goto failed;
1856 check_mft_get_info(class_id, &expect_mft_info);
1858 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
1859 &IID_IMFTransform, (void **)&transform)))
1860 goto failed;
1862 check_interface(transform, &IID_IMFTransform, TRUE);
1863 check_interface(transform, &IID_IMediaObject, FALSE);
1864 check_interface(transform, &IID_IPropertyStore, FALSE);
1865 check_interface(transform, &IID_IPropertyBag, FALSE);
1867 check_mft_optional_methods(transform, 1);
1868 check_mft_get_attributes(transform, NULL, FALSE);
1869 check_mft_get_input_stream_info(transform, S_OK, &input_info);
1870 check_mft_get_output_stream_info(transform, S_OK, &initial_output_info);
1872 check_mft_set_output_type_required(transform, output_type_desc);
1873 check_mft_set_output_type(transform, output_type_desc, S_OK);
1874 check_mft_get_output_current_type(transform, expect_output_type_desc);
1876 check_mft_set_input_type_required(transform, input_type_desc);
1877 check_mft_set_input_type(transform, input_type_desc);
1878 check_mft_get_input_current_type(transform, expect_input_type_desc);
1880 check_mft_get_input_stream_info(transform, S_OK, &input_info);
1881 check_mft_get_output_stream_info(transform, S_OK, &output_info);
1883 if (!has_video_processor)
1885 win_skip("Skipping AAC encoder tests on Win7\n");
1886 goto done;
1889 load_resource(L"audiodata.bin", &audio_data, &audio_data_len);
1890 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
1892 input_sample = create_sample(audio_data, audio_data_len);
1893 hr = IMFSample_SetSampleTime(input_sample, 0);
1894 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
1895 hr = IMFSample_SetSampleDuration(input_sample, 10000000);
1896 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
1897 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
1898 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
1899 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
1900 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
1901 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
1902 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
1903 ref = IMFSample_Release(input_sample);
1904 ok(ref <= 1, "Release returned %ld\n", ref);
1906 hr = MFCreateCollection(&output_samples);
1907 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
1909 output_sample = create_sample(NULL, output_info.cbSize);
1910 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
1912 winetest_push_context("%lu", i);
1913 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
1914 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
1915 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
1916 ref = IMFSample_Release(output_sample);
1917 ok(ref == 1, "Release returned %ld\n", ref);
1918 output_sample = create_sample(NULL, output_info.cbSize);
1919 winetest_pop_context();
1921 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
1922 ret = IMFSample_Release(output_sample);
1923 ok(ret == 0, "Release returned %lu\n", ret);
1924 ok(i == 88, "got %lu output samples\n", i);
1926 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"aacencdata.bin");
1927 ok(ret == 0, "got %lu%% diff\n", ret);
1928 IMFCollection_Release(output_samples);
1930 output_sample = create_sample(NULL, output_info.cbSize);
1931 hr = check_mft_process_output(transform, output_sample, &output_status);
1932 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
1933 hr = IMFSample_GetTotalLength(output_sample, &length);
1934 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
1935 ok(length == 0, "got length %lu\n", length);
1936 ret = IMFSample_Release(output_sample);
1937 ok(ret == 0, "Release returned %lu\n", ret);
1939 done:
1940 ret = IMFTransform_Release(transform);
1941 ok(ret == 0, "Release returned %lu\n", ret);
1943 failed:
1944 winetest_pop_context();
1945 CoUninitialize();
1948 static void test_aac_decoder(void)
1950 const GUID *const class_id = &CLSID_MSAACDecMFT;
1951 const struct transform_info expect_mft_info =
1953 .name = L"Microsoft AAC Audio Decoder MFT",
1954 .major_type = &MFMediaType_Audio,
1955 .inputs =
1957 {.subtype = &MFAudioFormat_AAC},
1958 {.subtype = &MFAudioFormat_RAW_AAC1},
1959 {.subtype = &MFAudioFormat_ADTS, .broken = TRUE /* <= w8 */},
1961 .outputs =
1963 {.subtype = &MFAudioFormat_Float},
1964 {.subtype = &MFAudioFormat_PCM},
1968 static const struct attribute_desc expect_input_attributes[] =
1970 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1971 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
1972 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
1973 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 6),
1974 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 24),
1975 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
1976 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 1152000),
1977 {0},
1979 static const media_type_desc expect_available_inputs[] =
1982 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC),
1983 ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 0),
1984 ATTR_UINT32(MF_MT_AAC_PAYLOAD_TYPE, 0),
1985 /* MF_MT_USER_DATA with some AAC codec data */
1988 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_RAW_AAC1),
1991 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC),
1992 ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 0),
1993 ATTR_UINT32(MF_MT_AAC_PAYLOAD_TYPE, 1),
1994 /* MF_MT_USER_DATA with some AAC codec data */
1997 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC),
1998 ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 0),
1999 ATTR_UINT32(MF_MT_AAC_PAYLOAD_TYPE, 3),
2000 /* MF_MT_USER_DATA with some AAC codec data */
2003 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_ADTS),
2006 static const struct attribute_desc expect_output_attributes[] =
2008 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2009 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2010 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2011 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2012 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2013 {0},
2015 static const media_type_desc expect_available_outputs[] =
2018 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2019 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
2020 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
2021 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
2022 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4 * 44100),
2025 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2026 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2027 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
2028 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2),
2029 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * 44100),
2032 const struct attribute_desc expect_transform_attributes[] =
2034 ATTR_UINT32(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, !has_video_processor /* 1 on W7 */, .todo = TRUE),
2035 /* more AAC decoder specific attributes from CODECAPI */
2036 {0},
2038 const struct attribute_desc input_type_desc[] =
2040 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2041 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC, .required = TRUE),
2042 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .required = TRUE),
2043 ATTR_BLOB(MF_MT_USER_DATA, aac_codec_data, sizeof(aac_codec_data), .required = TRUE),
2044 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
2045 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2046 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 12000),
2047 ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 41),
2048 ATTR_UINT32(MF_MT_AAC_PAYLOAD_TYPE, 0),
2049 {0},
2051 static const struct attribute_desc output_type_desc[] =
2053 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2054 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM, .required = TRUE),
2055 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1, .required = TRUE),
2056 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
2057 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .required = TRUE),
2058 {0},
2060 const MFT_OUTPUT_STREAM_INFO output_info =
2062 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES,
2063 .cbSize = 0xc000,
2065 const MFT_INPUT_STREAM_INFO input_info =
2067 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
2068 MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE | MFT_INPUT_STREAM_HOLDS_BUFFERS,
2071 const struct buffer_desc output_buffer_desc[] =
2073 {.length = 0x800},
2075 const struct attribute_desc output_sample_attributes[] =
2077 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
2078 {0},
2080 const struct sample_desc output_sample_desc[] =
2083 .attributes = output_sample_attributes + (has_video_processor ? 0 : 1) /* MFSampleExtension_CleanPoint missing on Win7 */,
2084 .sample_time = 0, .sample_duration = 232200,
2085 .buffer_count = 1, .buffers = output_buffer_desc,
2089 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_Float};
2090 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_AAC};
2091 IMFSample *input_sample, *output_sample;
2092 ULONG i, ret, ref, aacenc_data_len;
2093 IMFCollection *output_samples;
2094 DWORD length, output_status;
2095 IMFMediaType *media_type;
2096 IMFTransform *transform;
2097 const BYTE *aacenc_data;
2098 HRESULT hr;
2100 hr = CoInitialize(NULL);
2101 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
2103 winetest_push_context("aacdec");
2105 if (!check_mft_enum(MFT_CATEGORY_AUDIO_DECODER, &input_type, &output_type, class_id))
2106 goto failed;
2107 check_mft_get_info(class_id, &expect_mft_info);
2109 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
2110 &IID_IMFTransform, (void **)&transform)))
2111 goto failed;
2113 check_interface(transform, &IID_IMFTransform, TRUE);
2114 check_interface(transform, &IID_IMediaObject, FALSE);
2115 check_interface(transform, &IID_IPropertyStore, FALSE);
2116 check_interface(transform, &IID_IPropertyBag, FALSE);
2118 check_mft_optional_methods(transform, 1);
2119 check_mft_get_attributes(transform, expect_transform_attributes, FALSE);
2120 check_mft_get_input_stream_info(transform, S_OK, &input_info);
2121 check_mft_get_output_stream_info(transform, S_OK, &output_info);
2123 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
2124 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
2126 i = -1;
2127 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
2129 winetest_push_context("in %lu", i);
2130 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
2131 check_media_type(media_type, expect_input_attributes, -1);
2132 check_media_type(media_type, expect_available_inputs[i], -1);
2133 ret = IMFMediaType_Release(media_type);
2134 ok(ret <= 1, "Release returned %lu\n", ret);
2135 winetest_pop_context();
2137 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
2138 ok(i == ARRAY_SIZE(expect_available_inputs)
2139 || broken(i == 2) /* w7 */ || broken(i == 4) /* w8 */,
2140 "%lu input media types\n", i);
2142 /* setting output media type first doesn't work */
2143 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
2144 check_mft_get_output_current_type(transform, NULL);
2146 check_mft_set_input_type_required(transform, input_type_desc);
2147 check_mft_set_input_type(transform, input_type_desc);
2148 check_mft_get_input_current_type(transform, input_type_desc);
2150 /* check new output media types */
2152 i = -1;
2153 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
2155 winetest_push_context("out %lu", i);
2156 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
2157 check_media_type(media_type, expect_output_attributes, -1);
2158 check_media_type(media_type, expect_available_outputs[i], -1);
2159 ret = IMFMediaType_Release(media_type);
2160 ok(ret <= 1, "Release returned %lu\n", ret);
2161 winetest_pop_context();
2163 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
2164 ok(i == ARRAY_SIZE(expect_available_outputs), "%lu input media types\n", i);
2166 check_mft_set_output_type_required(transform, output_type_desc);
2167 check_mft_set_output_type(transform, output_type_desc, S_OK);
2168 check_mft_get_output_current_type(transform, output_type_desc);
2170 check_mft_get_input_stream_info(transform, S_OK, &input_info);
2171 check_mft_get_output_stream_info(transform, S_OK, &output_info);
2173 load_resource(L"aacencdata.bin", &aacenc_data, &aacenc_data_len);
2174 ok(aacenc_data_len == 24861, "got length %lu\n", aacenc_data_len);
2176 input_sample = create_sample(aacenc_data + sizeof(DWORD), *(DWORD *)aacenc_data);
2177 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2178 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2179 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2180 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2182 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
2183 * IMFTransform_ProcessOutput needs a sample or returns MF_E_TRANSFORM_NEED_MORE_INPUT */
2185 hr = check_mft_process_output(transform, NULL, &output_status);
2186 ok(hr == E_INVALIDARG, "ProcessOutput returned %#lx\n", hr);
2187 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
2188 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2189 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2191 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
2192 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
2193 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2194 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2196 hr = MFCreateCollection(&output_samples);
2197 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
2199 output_sample = create_sample(NULL, output_info.cbSize);
2200 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
2202 winetest_push_context("%lu", i);
2203 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
2204 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
2205 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
2206 ref = IMFSample_Release(output_sample);
2207 ok(ref == 1, "Release returned %ld\n", ref);
2208 output_sample = create_sample(NULL, output_info.cbSize);
2209 winetest_pop_context();
2211 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2212 ok(output_status == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE, "got output[0].dwStatus %#lx\n", output_status);
2213 ret = IMFSample_Release(output_sample);
2214 ok(ret == 0, "Release returned %lu\n", ret);
2215 ok(i == 1, "got %lu output samples\n", i);
2217 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"aacdecdata.bin");
2218 todo_wine_if(ret <= 5)
2219 ok(ret == 0, "got %lu%% diff\n", ret);
2220 IMFCollection_Release(output_samples);
2222 output_sample = create_sample(NULL, output_info.cbSize);
2223 hr = check_mft_process_output(transform, output_sample, &output_status);
2224 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2225 ok(output_status == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE, "got output[0].dwStatus %#lx\n", output_status);
2226 hr = IMFSample_GetTotalLength(output_sample, &length);
2227 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
2228 ok(length == 0, "got length %lu\n", length);
2229 ret = IMFSample_Release(output_sample);
2230 ok(ret == 0, "Release returned %lu\n", ret);
2232 ret = IMFSample_Release(input_sample);
2233 ok(ret == 0, "Release returned %lu\n", ret);
2234 ret = IMFTransform_Release(transform);
2235 ok(ret == 0, "Release returned %lu\n", ret);
2237 failed:
2238 winetest_pop_context();
2239 CoUninitialize();
2242 static const BYTE wma_codec_data[10] = {0, 0x44, 0, 0, 0x17, 0, 0, 0, 0, 0};
2243 static const ULONG wmaenc_block_size = 1487;
2244 static const ULONG wmadec_block_size = 0x2000;
2246 static void test_wma_encoder(void)
2248 const GUID *const class_id = &CLSID_CWMAEncMediaObject;
2249 const struct transform_info expect_mft_info =
2251 .name = L"WMAudio Encoder MFT",
2252 .major_type = &MFMediaType_Audio,
2253 .inputs =
2255 {.subtype = &MFAudioFormat_PCM},
2256 {.subtype = &MFAudioFormat_Float},
2258 .outputs =
2260 {.subtype = &MFAudioFormat_WMAudioV8},
2261 {.subtype = &MFAudioFormat_WMAudioV9},
2262 {.subtype = &MFAudioFormat_WMAudio_Lossless},
2265 const struct transform_info expect_dmo_info =
2267 .name = L"WMAudio Encoder DMO",
2268 .major_type = &MEDIATYPE_Audio,
2269 .inputs =
2271 {.subtype = &MEDIASUBTYPE_PCM},
2273 .outputs =
2275 {.subtype = &MEDIASUBTYPE_WMAUDIO2},
2276 {.subtype = &MEDIASUBTYPE_WMAUDIO3},
2277 {.subtype = &MEDIASUBTYPE_WMAUDIO_LOSSLESS},
2281 static const struct attribute_desc input_type_desc[] =
2283 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2284 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float, .required = TRUE),
2285 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
2286 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32, .required = TRUE),
2287 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
2288 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2 * (32 / 8), .required = TRUE),
2289 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * (32 / 8) * 22050, .required = TRUE),
2290 {0},
2292 const struct attribute_desc output_type_desc[] =
2294 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2295 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8, .required = TRUE),
2296 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
2297 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
2298 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003, .required = TRUE),
2299 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size, .required = TRUE),
2300 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data), .required = TRUE),
2301 {0},
2303 static const struct attribute_desc expect_input_type_desc[] =
2305 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2306 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
2307 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
2308 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2309 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
2310 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
2311 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 22050 * 8),
2312 ATTR_UINT32(MF_MT_AUDIO_CHANNEL_MASK, 3),
2313 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2314 {0},
2316 const struct attribute_desc expect_output_type_desc[] =
2318 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2319 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
2320 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2321 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
2322 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003),
2323 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size),
2324 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)),
2325 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2326 {0},
2328 const MFT_OUTPUT_STREAM_INFO output_info =
2330 .cbSize = wmaenc_block_size,
2331 .cbAlignment = 1,
2333 const MFT_INPUT_STREAM_INFO input_info =
2335 .hnsMaxLatency = 19969161,
2336 .cbSize = 8,
2337 .cbAlignment = 1,
2340 const struct buffer_desc output_buffer_desc[] =
2342 {.length = wmaenc_block_size},
2344 const struct attribute_desc output_sample_attributes[] =
2346 ATTR_UINT32(mft_output_sample_incomplete, 1),
2347 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
2348 {0},
2350 const struct sample_desc output_sample_desc[] =
2353 .attributes = output_sample_attributes,
2354 .sample_time = 0, .sample_duration = 3250794,
2355 .buffer_count = 1, .buffers = output_buffer_desc,
2358 .attributes = output_sample_attributes,
2359 .sample_time = 3250794, .sample_duration = 3715193,
2360 .buffer_count = 1, .buffers = output_buffer_desc,
2363 .attributes = output_sample_attributes,
2364 .sample_time = 6965986, .sample_duration = 3366893,
2365 .buffer_count = 1, .buffers = output_buffer_desc,
2369 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8};
2370 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_Float};
2371 IMFSample *input_sample, *output_sample;
2372 IMFCollection *output_samples;
2373 DWORD length, output_status;
2374 IMFMediaType *media_type;
2375 IMFTransform *transform;
2376 const BYTE *audio_data;
2377 ULONG audio_data_len;
2378 ULONG i, ret;
2379 HRESULT hr;
2380 LONG ref;
2382 hr = CoInitialize(NULL);
2383 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
2385 winetest_push_context("wmaenc");
2387 if (!check_mft_enum(MFT_CATEGORY_AUDIO_ENCODER, &input_type, &output_type, class_id))
2388 goto failed;
2389 check_mft_get_info(class_id, &expect_mft_info);
2390 check_dmo_get_info(class_id, &expect_dmo_info);
2392 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
2393 &IID_IMFTransform, (void **)&transform)))
2394 goto failed;
2396 check_interface(transform, &IID_IMFTransform, TRUE);
2397 check_interface(transform, &IID_IMediaObject, TRUE);
2398 check_interface(transform, &IID_IPropertyStore, TRUE);
2399 check_interface(transform, &IID_IPropertyBag, TRUE);
2401 check_mft_optional_methods(transform, 1);
2402 check_mft_get_attributes(transform, NULL, FALSE);
2403 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
2404 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
2406 check_mft_set_input_type_required(transform, input_type_desc);
2408 hr = MFCreateMediaType(&media_type);
2409 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
2410 init_media_type(media_type, input_type_desc, -1);
2411 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
2412 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
2413 ret = IMFMediaType_Release(media_type);
2414 ok(ret == 0, "Release returned %lu\n", ret);
2416 check_mft_set_output_type_required(transform, output_type_desc);
2417 check_mft_set_output_type(transform, output_type_desc, S_OK);
2418 check_mft_get_output_current_type(transform, expect_output_type_desc);
2420 check_mft_set_input_type_required(transform, input_type_desc);
2421 check_mft_set_input_type(transform, input_type_desc);
2422 check_mft_get_input_current_type(transform, expect_input_type_desc);
2424 check_mft_get_input_stream_info(transform, S_OK, &input_info);
2425 check_mft_get_output_stream_info(transform, S_OK, &output_info);
2427 load_resource(L"audiodata.bin", &audio_data, &audio_data_len);
2428 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
2430 input_sample = create_sample(audio_data, audio_data_len);
2431 hr = IMFSample_SetSampleTime(input_sample, 0);
2432 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
2433 hr = IMFSample_SetSampleDuration(input_sample, 10000000);
2434 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
2435 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2436 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2437 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
2438 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
2439 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2440 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2441 ref = IMFSample_Release(input_sample);
2442 ok(ref <= 1, "Release returned %ld\n", ref);
2444 hr = MFCreateCollection(&output_samples);
2445 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
2447 output_sample = create_sample(NULL, output_info.cbSize);
2448 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
2450 winetest_push_context("%lu", i);
2451 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
2452 ok(output_status == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE, "got output[0].dwStatus %#lx\n", output_status);
2453 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
2454 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
2455 ref = IMFSample_Release(output_sample);
2456 ok(ref == 1, "Release returned %ld\n", ref);
2457 output_sample = create_sample(NULL, output_info.cbSize);
2458 winetest_pop_context();
2460 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2461 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
2462 ret = IMFSample_Release(output_sample);
2463 ok(ret == 0, "Release returned %lu\n", ret);
2464 ok(i == 3, "got %lu output samples\n", i);
2466 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"wmaencdata.bin");
2467 ok(ret == 0, "got %lu%% diff\n", ret);
2468 IMFCollection_Release(output_samples);
2470 output_sample = create_sample(NULL, output_info.cbSize);
2471 hr = check_mft_process_output(transform, output_sample, &output_status);
2472 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2473 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
2474 hr = IMFSample_GetTotalLength(output_sample, &length);
2475 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
2476 ok(length == 0, "got length %lu\n", length);
2477 ret = IMFSample_Release(output_sample);
2478 ok(ret == 0, "Release returned %lu\n", ret);
2480 ret = IMFTransform_Release(transform);
2481 ok(ret == 0, "Release returned %lu\n", ret);
2483 failed:
2484 winetest_pop_context();
2485 CoUninitialize();
2488 static void test_wma_decoder(void)
2490 const GUID *const class_id = &CLSID_CWMADecMediaObject;
2491 const struct transform_info expect_mft_info =
2493 .name = L"WMAudio Decoder MFT",
2494 .major_type = &MFMediaType_Audio,
2495 .inputs =
2497 {.subtype = &MEDIASUBTYPE_MSAUDIO1},
2498 {.subtype = &MFAudioFormat_WMAudioV8},
2499 {.subtype = &MFAudioFormat_WMAudioV9},
2500 {.subtype = &MFAudioFormat_WMAudio_Lossless},
2502 .outputs =
2504 {.subtype = &MFAudioFormat_PCM},
2505 {.subtype = &MFAudioFormat_Float},
2508 const struct transform_info expect_dmo_info =
2510 .name = L"WMAudio Decoder DMO",
2511 .major_type = &MEDIATYPE_Audio,
2512 .inputs =
2514 {.subtype = &MEDIASUBTYPE_MSAUDIO1},
2515 {.subtype = &MEDIASUBTYPE_WMAUDIO2},
2516 {.subtype = &MEDIASUBTYPE_WMAUDIO3},
2517 {.subtype = &MEDIASUBTYPE_WMAUDIO_LOSSLESS},
2519 .outputs =
2521 {.subtype = &MEDIASUBTYPE_PCM},
2522 {.subtype = &MEDIASUBTYPE_IEEE_FLOAT},
2526 static const media_type_desc expect_available_inputs[] =
2529 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2530 ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_MSAUDIO1),
2531 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2534 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2535 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
2536 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2539 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2540 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV9),
2541 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2544 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2545 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudio_Lossless),
2546 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2549 static const media_type_desc expect_available_outputs[] =
2552 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2553 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
2554 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
2555 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2556 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
2557 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
2558 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
2559 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2560 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2561 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2564 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2565 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2566 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
2567 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2568 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
2569 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
2570 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
2571 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2572 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2573 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2577 const struct attribute_desc input_type_desc[] =
2579 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2580 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8, .required = TRUE),
2581 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data), .required = TRUE),
2582 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size, .required = TRUE),
2583 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
2584 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
2585 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003), /* not required by SetInputType, but needed for the transform to work */
2586 {0},
2588 static const struct attribute_desc output_type_desc[] =
2590 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2591 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM, .required = TRUE),
2592 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
2593 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
2594 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
2595 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2 * (16 / 8), .required = TRUE),
2596 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * (16 / 8) * 22050, .required = TRUE),
2597 {0},
2599 const struct attribute_desc expect_input_type_desc[] =
2601 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2602 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
2603 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)),
2604 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size),
2605 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
2606 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2607 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003),
2608 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2609 {0},
2611 static const struct attribute_desc expect_output_type_desc[] =
2613 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2614 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2615 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 22050 * 4),
2616 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
2617 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2618 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
2619 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
2620 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2621 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2622 {0},
2624 const MFT_INPUT_STREAM_INFO input_info =
2626 .cbSize = wmaenc_block_size,
2627 .cbAlignment = 1,
2629 const MFT_OUTPUT_STREAM_INFO output_info =
2631 .cbSize = wmadec_block_size,
2632 .cbAlignment = 1,
2635 const struct buffer_desc output_buffer_desc[] =
2637 {.length = wmadec_block_size, .compare = compare_pcm16},
2638 {.length = wmadec_block_size / 2, .compare = compare_pcm16, .todo_length = TRUE},
2640 const struct attribute_desc output_sample_attributes[] =
2642 ATTR_UINT32(mft_output_sample_incomplete, 1),
2643 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
2644 {0},
2646 const struct attribute_desc output_sample_attributes_todo[] =
2648 ATTR_UINT32(mft_output_sample_incomplete, 1, .todo = TRUE),
2649 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
2650 {0},
2652 struct sample_desc output_sample_desc[] =
2655 .attributes = output_sample_attributes + 0,
2656 .sample_time = 0, .sample_duration = 928798,
2657 .buffer_count = 1, .buffers = output_buffer_desc + 0, .repeat_count = 1,
2660 .attributes = output_sample_attributes + 0,
2661 .sample_time = 1857596, .sample_duration = 928798,
2662 .buffer_count = 1, .buffers = output_buffer_desc + 0,
2665 .attributes = output_sample_attributes + 1, /* not MFT_OUTPUT_DATA_BUFFER_INCOMPLETE */
2666 .sample_time = 2786394, .sample_duration = 464399,
2667 .buffer_count = 1, .buffers = output_buffer_desc + 1, .todo_length = TRUE,
2671 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8};
2672 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_Float};
2673 IUnknown *unknown, *tmp_unknown, outer = {&test_unk_vtbl};
2674 IMFSample *input_sample, *output_sample;
2675 IMFCollection *output_samples;
2676 DWORD length, output_status;
2677 IMediaObject *media_object;
2678 IPropertyBag *property_bag;
2679 IMFMediaType *media_type;
2680 IMFTransform *transform;
2681 const BYTE *wmaenc_data;
2682 ULONG wmaenc_data_len;
2683 ULONG i, ret, ref;
2684 HRESULT hr;
2686 hr = CoInitialize(NULL);
2687 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
2689 winetest_push_context("wmadec");
2691 if (!check_mft_enum(MFT_CATEGORY_AUDIO_DECODER, &input_type, &output_type, class_id))
2692 goto failed;
2693 check_mft_get_info(class_id, &expect_mft_info);
2694 check_dmo_get_info(class_id, &expect_dmo_info);
2696 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
2697 &IID_IMFTransform, (void **)&transform)))
2698 goto failed;
2700 check_interface(transform, &IID_IMFTransform, TRUE);
2701 check_interface(transform, &IID_IMediaObject, TRUE);
2702 todo_wine
2703 check_interface(transform, &IID_IPropertyStore, TRUE);
2704 check_interface(transform, &IID_IPropertyBag, TRUE);
2706 check_mft_optional_methods(transform, 1);
2707 check_mft_get_attributes(transform, NULL, FALSE);
2708 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
2709 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
2711 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
2712 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
2714 i = -1;
2715 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
2717 winetest_push_context("in %lu", i);
2718 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
2719 check_media_type(media_type, expect_available_inputs[i], -1);
2720 ret = IMFMediaType_Release(media_type);
2721 ok(ret == 0, "Release returned %lu\n", ret);
2722 winetest_pop_context();
2724 todo_wine
2725 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
2726 todo_wine
2727 ok(i == 4, "%lu input media types\n", i);
2729 /* setting output media type first doesn't work */
2730 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
2731 check_mft_get_output_current_type_(transform, NULL, TRUE, FALSE);
2733 check_mft_set_input_type_required(transform, input_type_desc);
2734 check_mft_set_input_type(transform, input_type_desc);
2735 check_mft_get_input_current_type_(transform, expect_input_type_desc, TRUE, FALSE);
2737 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
2738 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
2740 /* check new output media types */
2742 i = -1;
2743 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
2745 winetest_push_context("out %lu", i);
2746 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
2747 check_media_type(media_type, expect_available_outputs[i], -1);
2748 ret = IMFMediaType_Release(media_type);
2749 ok(ret == 0, "Release returned %lu\n", ret);
2750 winetest_pop_context();
2752 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
2753 ok(i == 2, "%lu output media types\n", i);
2755 check_mft_set_output_type_required(transform, output_type_desc);
2756 check_mft_set_output_type(transform, output_type_desc, S_OK);
2757 check_mft_get_output_current_type_(transform, expect_output_type_desc, TRUE, FALSE);
2759 check_mft_get_input_stream_info(transform, S_OK, &input_info);
2760 check_mft_get_output_stream_info(transform, S_OK, &output_info);
2762 load_resource(L"wmaencdata.bin", &wmaenc_data, &wmaenc_data_len);
2763 ok(wmaenc_data_len % wmaenc_block_size == 0, "got length %lu\n", wmaenc_data_len);
2765 input_sample = create_sample(wmaenc_data, wmaenc_block_size / 2);
2766 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2767 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2768 ret = IMFSample_Release(input_sample);
2769 ok(ret == 0, "Release returned %lu\n", ret);
2770 input_sample = create_sample(wmaenc_data, wmaenc_block_size + 1);
2771 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2772 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2773 ret = IMFSample_Release(input_sample);
2774 ok(ret == 0, "Release returned %lu\n", ret);
2775 input_sample = create_sample(wmaenc_data, wmaenc_block_size);
2776 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2777 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2778 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2779 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2780 ret = IMFSample_Release(input_sample);
2781 ok(ret == 1, "Release returned %lu\n", ret);
2783 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
2784 * IMFTransform_ProcessOutput needs a sample or returns MF_E_TRANSFORM_NEED_MORE_INPUT */
2786 hr = check_mft_process_output(transform, NULL, &output_status);
2787 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2788 ok(output_status == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE
2789 || broken(output_status == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
2790 "got output[0].dwStatus %#lx\n", output_status);
2792 input_sample = create_sample(wmaenc_data, wmaenc_block_size);
2793 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2794 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2795 ret = IMFSample_Release(input_sample);
2796 ok(ret == 0, "Release returned %lu\n", ret);
2798 hr = check_mft_process_output(transform, NULL, &output_status);
2799 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2800 ok(output_status == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE
2801 || broken(output_status == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
2802 "got output[0].dwStatus %#lx\n", output_status);
2804 hr = MFCreateCollection(&output_samples);
2805 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
2807 output_sample = create_sample(NULL, output_info.cbSize);
2808 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
2810 winetest_push_context("%lu", i);
2811 ok(!(output_status & ~MFT_OUTPUT_DATA_BUFFER_INCOMPLETE), "got output[0].dwStatus %#lx\n", output_status);
2812 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
2813 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
2814 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
2815 ref = IMFSample_Release(output_sample);
2816 ok(ref == 1, "Release returned %ld\n", ref);
2817 output_sample = create_sample(NULL, output_info.cbSize);
2818 winetest_pop_context();
2820 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2821 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
2822 ret = IMFSample_Release(output_sample);
2823 ok(ret == 0, "Release returned %lu\n", ret);
2824 todo_wine_if(i == 3) /* wmadec output depends on ffmpeg version used */
2825 ok(i == 4, "got %lu output samples\n", i);
2827 if (!strcmp(winetest_platform, "wine") && i == 3)
2828 output_sample_desc[1].attributes = output_sample_attributes_todo;
2830 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"wmadecdata.bin");
2831 todo_wine_if(ret > 0 && ret <= 10) /* ffmpeg sometimes offsets the decoded data */
2832 ok(ret == 0, "got %lu%% diff\n", ret);
2833 IMFCollection_Release(output_samples);
2835 output_sample = create_sample(NULL, output_info.cbSize);
2836 hr = check_mft_process_output(transform, output_sample, &output_status);
2837 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2838 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
2839 hr = IMFSample_GetTotalLength(output_sample, &length);
2840 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
2841 ok(length == 0, "got length %lu\n", length);
2842 ret = IMFSample_Release(output_sample);
2843 ok(ret == 0, "Release returned %lu\n", ret);
2845 input_sample = create_sample(wmaenc_data, wmaenc_block_size);
2846 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2847 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2849 ret = IMFTransform_Release(transform);
2850 ok(ret == 0, "Release returned %lu\n", ret);
2851 ret = IMFSample_Release(input_sample);
2852 ok(ret == 0, "Release returned %lu\n", ret);
2854 hr = CoCreateInstance( &CLSID_CWMADecMediaObject, &outer, CLSCTX_INPROC_SERVER, &IID_IUnknown,
2855 (void **)&unknown );
2856 ok( hr == S_OK, "CoCreateInstance returned %#lx\n", hr );
2857 hr = IUnknown_QueryInterface( unknown, &IID_IMFTransform, (void **)&transform );
2858 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
2859 hr = IUnknown_QueryInterface( unknown, &IID_IMediaObject, (void **)&media_object );
2860 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
2861 hr = IUnknown_QueryInterface( unknown, &IID_IPropertyBag, (void **)&property_bag );
2862 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
2863 hr = IUnknown_QueryInterface( media_object, &IID_IUnknown, (void **)&tmp_unknown );
2864 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
2866 ok( unknown != &outer, "got outer IUnknown\n" );
2867 ok( transform != (void *)unknown, "got IUnknown == IMFTransform\n" );
2868 ok( media_object != (void *)unknown, "got IUnknown == IMediaObject\n" );
2869 ok( property_bag != (void *)unknown, "got IUnknown == IPropertyBag\n" );
2870 ok( tmp_unknown != unknown, "got inner IUnknown\n" );
2872 check_interface( unknown, &IID_IPersistPropertyBag, FALSE );
2873 check_interface( unknown, &IID_IAMFilterMiscFlags, FALSE );
2874 check_interface( unknown, &IID_IMediaSeeking, FALSE );
2875 check_interface( unknown, &IID_IMediaPosition, FALSE );
2876 check_interface( unknown, &IID_IReferenceClock, FALSE );
2877 check_interface( unknown, &IID_IBasicAudio, FALSE );
2879 ref = IUnknown_Release( tmp_unknown );
2880 ok( ref == 1, "Release returned %lu\n", ref );
2881 ref = IPropertyBag_Release( property_bag );
2882 ok( ref == 1, "Release returned %lu\n", ref );
2883 ref = IMediaObject_Release( media_object );
2884 ok( ref == 1, "Release returned %lu\n", ref );
2885 ref = IMFTransform_Release( transform );
2886 ok( ref == 1, "Release returned %lu\n", ref );
2887 ref = IUnknown_Release( unknown );
2888 ok( ref == 0, "Release returned %lu\n", ref );
2890 failed:
2891 winetest_pop_context();
2892 CoUninitialize();
2895 #define next_h264_sample(a, b) next_h264_sample_(__LINE__, a, b)
2896 static IMFSample *next_h264_sample_(int line, const BYTE **h264_buf, ULONG *h264_len)
2898 const BYTE *sample_data;
2900 ok_(__FILE__, line)(*h264_len > 4, "invalid h264 length\n");
2901 ok_(__FILE__, line)(*(UINT32 *)*h264_buf == 0x01000000, "invalid h264 buffer\n");
2902 sample_data = *h264_buf;
2904 (*h264_len) -= 4;
2905 (*h264_buf) += 4;
2907 while (*h264_len >= 4 && *(UINT32 *)*h264_buf != 0x01000000)
2909 (*h264_len)--;
2910 (*h264_buf)++;
2913 return create_sample(sample_data, *h264_buf - sample_data);
2916 static void test_h264_decoder(void)
2918 const GUID *const class_id = &CLSID_MSH264DecoderMFT;
2919 const struct transform_info expect_mft_info =
2921 .name = L"Microsoft H264 Video Decoder MFT",
2922 .major_type = &MFMediaType_Video,
2923 .inputs =
2925 {.subtype = &MFVideoFormat_H264},
2926 {.subtype = &MFVideoFormat_H264_ES},
2928 .outputs =
2930 {.subtype = &MFVideoFormat_NV12},
2931 {.subtype = &MFVideoFormat_YV12},
2932 {.subtype = &MFVideoFormat_IYUV},
2933 {.subtype = &MFVideoFormat_I420},
2934 {.subtype = &MFVideoFormat_YUY2},
2937 static const media_type_desc default_inputs[] =
2940 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2941 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
2944 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2945 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264_ES),
2948 static const struct attribute_desc expect_transform_attributes[] =
2950 ATTR_UINT32(MF_LOW_LATENCY, 0),
2951 ATTR_UINT32(MF_SA_D3D_AWARE, 1, .todo = TRUE),
2952 ATTR_UINT32(MF_SA_D3D11_AWARE, 1, .todo = TRUE),
2953 ATTR_UINT32(MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER, 0, .todo = TRUE),
2954 /* more H264 decoder specific attributes from CODECAPI */
2955 {0},
2957 static const DWORD input_width = 120, input_height = 248;
2958 const media_type_desc default_outputs[] =
2961 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2962 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
2963 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
2964 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
2965 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
2966 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
2967 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2968 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2969 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
2970 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
2971 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
2974 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2975 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
2976 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
2977 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
2978 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
2979 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
2980 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2981 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2982 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
2983 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
2984 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
2987 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2988 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
2989 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
2990 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
2991 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
2992 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
2993 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2994 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2995 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
2996 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
2997 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3000 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3001 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
3002 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3003 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
3004 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
3005 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3006 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3007 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3008 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
3009 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
3010 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3013 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3014 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
3015 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3016 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
3017 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width * 2),
3018 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3019 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3020 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3021 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
3022 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 2),
3023 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3026 const struct attribute_desc input_type_desc[] =
3028 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
3029 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264, .required = TRUE),
3030 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
3031 {0},
3033 const struct attribute_desc output_type_desc[] =
3035 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
3036 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE),
3037 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height, .required = TRUE),
3038 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
3039 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 2, 1),
3040 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
3041 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * input_height * 3 / 2),
3042 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
3043 {0},
3045 const struct attribute_desc expect_input_type_desc[] =
3047 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3048 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
3049 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
3050 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 0),
3051 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 0),
3052 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 0),
3053 ATTR_UINT32(MF_MT_AVG_BIT_ERROR_RATE, 0),
3054 ATTR_UINT32(MF_MT_COMPRESSED, 1),
3055 {0},
3057 const struct attribute_desc expect_output_type_desc[] =
3059 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3060 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
3061 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
3062 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
3063 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 2, 1),
3064 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
3065 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * input_height * 3 / 2),
3066 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
3067 ATTR_UINT32(MF_MT_AVG_BIT_ERROR_RATE, 0),
3068 ATTR_UINT32(MF_MT_COMPRESSED, 0),
3069 {0},
3071 static const struct attribute_desc new_output_type_desc[] =
3073 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3074 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
3075 ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96),
3076 ATTR_RATIO(MF_MT_FRAME_RATE, 1, 1),
3077 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 2),
3078 {0},
3080 static const struct attribute_desc expect_new_output_type_desc[] =
3082 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3083 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
3084 ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96),
3085 ATTR_RATIO(MF_MT_FRAME_RATE, 1, 1),
3086 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 2),
3087 ATTR_UINT32(MF_MT_COMPRESSED, 0),
3088 ATTR_UINT32(MF_MT_AVG_BIT_ERROR_RATE, 0),
3089 {0},
3091 static const MFVideoArea actual_aperture = {.Area={82,84}};
3092 static const DWORD actual_width = 96, actual_height = 96;
3093 const media_type_desc actual_outputs[] =
3096 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3097 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
3098 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3099 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
3100 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3101 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
3102 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
3103 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3104 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3105 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3106 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3107 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
3110 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3111 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
3112 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3113 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
3114 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3115 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
3116 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
3117 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3118 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3119 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3120 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3121 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
3124 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3125 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
3126 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3127 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
3128 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3129 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
3130 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
3131 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3132 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3133 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3134 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3135 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
3138 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3139 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
3140 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3141 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
3142 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3143 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
3144 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
3145 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3146 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3147 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3148 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3149 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
3152 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3153 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
3154 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3155 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
3156 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3157 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
3158 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
3159 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3160 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3161 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3162 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3163 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
3166 const MFT_OUTPUT_STREAM_INFO initial_output_info =
3168 .dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
3169 MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE,
3170 .cbSize = 1920 * 1088 * 2,
3172 const MFT_OUTPUT_STREAM_INFO output_info =
3174 .dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
3175 MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE,
3176 .cbSize = input_width * input_height * 2,
3178 const MFT_OUTPUT_STREAM_INFO actual_output_info =
3180 .dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
3181 MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE,
3182 .cbSize = actual_width * actual_height * 2,
3184 const MFT_INPUT_STREAM_INFO input_info =
3186 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
3187 MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE,
3188 .cbSize = 0x1000,
3191 const struct attribute_desc output_sample_attributes[] =
3193 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
3194 {0},
3196 const struct buffer_desc output_buffer_desc_nv12 =
3198 .length = actual_width * actual_height * 3 / 2,
3199 .compare = compare_nv12, .dump = dump_nv12, .rect = {.right = 82, .bottom = 84},
3201 const struct sample_desc output_sample_desc_nv12 =
3203 .attributes = output_sample_attributes,
3204 .sample_time = 0, .sample_duration = 333667,
3205 .buffer_count = 1, .buffers = &output_buffer_desc_nv12,
3207 const struct buffer_desc output_buffer_desc_i420 =
3209 .length = actual_width * actual_height * 3 / 2,
3210 .compare = compare_i420, .dump = dump_i420, .rect = {.right = 82, .bottom = 84},
3212 const struct sample_desc expect_output_sample_i420 =
3214 .attributes = output_sample_attributes,
3215 .sample_time = 333667, .sample_duration = 333667, .todo_time = 1334666 /* with VA-API */,
3216 .buffer_count = 1, .buffers = &output_buffer_desc_i420,
3219 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_H264};
3220 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
3221 IMFSample *input_sample, *output_sample;
3222 const BYTE *h264_encoded_data;
3223 IMFCollection *output_samples;
3224 ULONG h264_encoded_data_len;
3225 DWORD length, output_status;
3226 IMFAttributes *attributes;
3227 IMFMediaType *media_type;
3228 IMFTransform *transform;
3229 ULONG i, ret, ref;
3230 HRESULT hr;
3232 hr = CoInitialize(NULL);
3233 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
3235 winetest_push_context("h264dec");
3237 if (!check_mft_enum(MFT_CATEGORY_VIDEO_DECODER, &input_type, &output_type, class_id))
3238 goto failed;
3239 check_mft_get_info(class_id, &expect_mft_info);
3241 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
3242 &IID_IMFTransform, (void **)&transform)))
3243 goto failed;
3245 check_interface(transform, &IID_IMFTransform, TRUE);
3246 check_interface(transform, &IID_IMediaObject, FALSE);
3247 check_interface(transform, &IID_IPropertyStore, FALSE);
3248 check_interface(transform, &IID_IPropertyBag, FALSE);
3250 check_mft_optional_methods(transform, 1);
3251 check_mft_get_attributes(transform, expect_transform_attributes, TRUE);
3252 check_mft_get_input_stream_info(transform, S_OK, &input_info);
3253 check_mft_get_output_stream_info(transform, S_OK, &initial_output_info);
3255 hr = IMFTransform_GetAttributes(transform, &attributes);
3256 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
3257 hr = IMFAttributes_SetUINT32(attributes, &MF_LOW_LATENCY, 1);
3258 ok(hr == S_OK, "SetUINT32 returned %#lx\n", hr);
3259 IMFAttributes_Release(attributes);
3261 /* no output type is available before an input type is set */
3263 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
3264 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
3266 /* setting output media type first doesn't work */
3267 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
3268 check_mft_get_output_current_type(transform, NULL);
3270 /* check available input types */
3272 i = -1;
3273 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
3275 winetest_push_context("in %lu", i);
3276 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
3277 check_media_type(media_type, default_inputs[i], -1);
3278 ret = IMFMediaType_Release(media_type);
3279 ok(ret == 0, "Release returned %lu\n", ret);
3280 winetest_pop_context();
3282 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
3283 ok(i == 2 || broken(i == 1) /* Win7 */, "%lu input media types\n", i);
3285 check_mft_set_input_type_required(transform, input_type_desc);
3286 check_mft_set_input_type(transform, input_type_desc);
3287 check_mft_get_input_current_type_(transform, expect_input_type_desc, TRUE, FALSE);
3289 check_mft_get_input_stream_info(transform, S_OK, &input_info);
3290 check_mft_get_output_stream_info(transform, S_OK, &output_info);
3292 /* output types can now be enumerated (though they are actually the same for all input types) */
3294 i = -1;
3295 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
3297 winetest_push_context("out %lu", i);
3298 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3299 check_media_type(media_type, default_outputs[i], -1);
3300 ret = IMFMediaType_Release(media_type);
3301 ok(ret == 0, "Release returned %lu\n", ret);
3302 winetest_pop_context();
3304 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3305 ok(i == 5, "%lu output media types\n", i);
3307 check_mft_set_output_type_required(transform, output_type_desc);
3308 check_mft_set_output_type(transform, output_type_desc, S_OK);
3309 check_mft_get_output_current_type_(transform, expect_output_type_desc, FALSE, TRUE);
3311 /* check that the output media type we've selected don't change the enumeration */
3313 i = -1;
3314 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
3316 winetest_push_context("out %lu", i);
3317 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3318 check_media_type(media_type, default_outputs[i], -1);
3319 ret = IMFMediaType_Release(media_type);
3320 ok(ret == 0, "Release returned %lu\n", ret);
3321 winetest_pop_context();
3323 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3324 ok(i == 5, "%lu output media types\n", i);
3326 check_mft_get_input_stream_info(transform, S_OK, &input_info);
3327 check_mft_get_output_stream_info(transform, S_OK, &output_info);
3329 load_resource(L"h264data.bin", &h264_encoded_data, &h264_encoded_data_len);
3331 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
3332 * IMFTransform_ProcessOutput needs a sample or returns an error */
3334 hr = check_mft_process_output(transform, NULL, &output_status);
3335 ok(hr == E_INVALIDARG || hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3336 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3338 i = 0;
3339 input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
3340 while (1)
3342 output_sample = create_sample(NULL, output_info.cbSize);
3343 hr = check_mft_process_output(transform, output_sample, &output_status);
3344 if (hr != MF_E_TRANSFORM_NEED_MORE_INPUT) break;
3346 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3347 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3348 hr = IMFSample_GetTotalLength(output_sample, &length);
3349 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
3350 ok(length == 0, "got length %lu\n", length);
3351 ret = IMFSample_Release(output_sample);
3352 ok(ret == 0, "Release returned %lu\n", ret);
3354 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3355 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3356 ret = IMFSample_Release(input_sample);
3357 ok(ret <= 1, "Release returned %lu\n", ret);
3358 input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
3360 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3361 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3362 ret = IMFSample_Release(input_sample);
3363 ok(ret <= 1, "Release returned %lu\n", ret);
3364 input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
3365 i++;
3367 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
3368 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
3370 todo_wine
3371 ok(i == 2, "got %lu iterations\n", i);
3372 todo_wine
3373 ok(h264_encoded_data_len == 1180, "got h264_encoded_data_len %lu\n", h264_encoded_data_len);
3374 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
3375 ok(output_status == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got output[0].dwStatus %#lx\n", output_status);
3376 hr = IMFSample_GetTotalLength(output_sample, &length);
3377 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
3378 ok(length == 0, "got length %lu\n", length);
3379 ret = IMFSample_Release(output_sample);
3380 ok(ret == 0, "Release returned %lu\n", ret);
3382 check_mft_get_input_stream_info(transform, S_OK, &input_info);
3383 check_mft_get_output_stream_info(transform, S_OK, &actual_output_info);
3385 i = -1;
3386 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
3388 winetest_push_context("out %lu", i);
3389 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3390 check_media_type(media_type, actual_outputs[i], -1);
3391 ret = IMFMediaType_Release(media_type);
3392 ok(ret == 0, "Release returned %lu\n", ret);
3393 winetest_pop_context();
3395 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3396 ok(i == 5, "%lu output media types\n", i);
3398 /* current output type is still the one we selected */
3399 check_mft_get_output_current_type_(transform, expect_output_type_desc, FALSE, TRUE);
3401 hr = MFCreateCollection(&output_samples);
3402 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
3404 output_sample = create_sample(NULL, output_info.cbSize);
3405 hr = check_mft_process_output(transform, output_sample, &output_status);
3406 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
3407 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3408 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
3409 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
3410 ref = IMFSample_Release(output_sample);
3411 ok(ref == 1, "Release returned %ld\n", ref);
3413 ret = check_mf_sample_collection(output_samples, &output_sample_desc_nv12, L"nv12frame.bmp");
3414 ok(ret == 0, "got %lu%% diff\n", ret);
3415 IMFCollection_Release(output_samples);
3417 /* we can change it, but only with the correct frame size */
3418 hr = MFCreateMediaType(&media_type);
3419 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
3420 init_media_type(media_type, output_type_desc, -1);
3421 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3422 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
3423 init_media_type(media_type, new_output_type_desc, -1);
3424 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3425 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
3426 ret = IMFMediaType_Release(media_type);
3427 ok(ret == 1, "Release returned %lu\n", ret);
3429 check_mft_get_output_current_type_(transform, expect_new_output_type_desc, FALSE, TRUE);
3431 output_sample = create_sample(NULL, actual_width * actual_height * 2);
3432 hr = check_mft_process_output(transform, output_sample, &output_status);
3433 todo_wine
3434 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
3435 todo_wine
3436 ok(output_status == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got output[0].dwStatus %#lx\n", output_status);
3438 while (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
3440 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3441 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3442 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3443 ret = IMFSample_Release(input_sample);
3444 ok(ret <= 1, "Release returned %lu\n", ret);
3445 input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
3446 hr = check_mft_process_output(transform, output_sample, &output_status);
3449 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
3450 ok(output_status == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got output[0].dwStatus %#lx\n", output_status);
3452 hr = IMFSample_GetTotalLength(output_sample, &length);
3453 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
3454 ok(length == 0, "got length %lu\n", length);
3455 ret = IMFSample_Release(output_sample);
3456 ok(ret == 0, "Release returned %lu\n", ret);
3458 hr = MFCreateCollection(&output_samples);
3459 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
3461 output_sample = create_sample(NULL, actual_width * actual_height * 2);
3462 hr = check_mft_process_output(transform, output_sample, &output_status);
3463 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
3464 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3465 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
3466 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
3467 ref = IMFSample_Release(output_sample);
3468 ok(ref == 1, "Release returned %ld\n", ref);
3470 ret = check_mf_sample_collection(output_samples, &expect_output_sample_i420, L"i420frame.bmp");
3471 ok(ret == 0, "got %lu%% diff\n", ret);
3472 IMFCollection_Release(output_samples);
3474 output_sample = create_sample(NULL, actual_width * actual_height * 2);
3475 hr = check_mft_process_output(transform, output_sample, &output_status);
3476 todo_wine_if(hr == S_OK) /* when VA-API plugin is used */
3477 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3478 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3479 ret = IMFSample_Release(output_sample);
3480 ok(ret == 0, "Release returned %lu\n", ret);
3482 ret = IMFTransform_Release(transform);
3483 ok(ret == 0, "Release returned %lu\n", ret);
3484 ret = IMFSample_Release(input_sample);
3485 ok(ret == 0, "Release returned %lu\n", ret);
3487 failed:
3488 winetest_pop_context();
3489 CoUninitialize();
3492 static void test_audio_convert(void)
3494 const GUID *const class_id = &CLSID_CResamplerMediaObject;
3495 const struct transform_info expect_mft_info =
3497 .name = L"Resampler MFT",
3498 .major_type = &MFMediaType_Audio,
3499 .inputs =
3501 {.subtype = &MFAudioFormat_PCM},
3502 {.subtype = &MFAudioFormat_Float},
3504 .outputs =
3506 {.subtype = &MFAudioFormat_PCM},
3507 {.subtype = &MFAudioFormat_Float},
3510 const struct transform_info expect_dmo_info =
3512 .name = L"Resampler DMO",
3513 .major_type = &MEDIATYPE_Audio,
3514 .inputs =
3516 {.subtype = &MEDIASUBTYPE_PCM},
3517 {.subtype = &MEDIASUBTYPE_IEEE_FLOAT},
3519 .outputs =
3521 {.subtype = &MEDIASUBTYPE_PCM},
3522 {.subtype = &MEDIASUBTYPE_IEEE_FLOAT},
3526 static const media_type_desc expect_available_inputs[] =
3529 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3530 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
3531 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3534 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3535 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
3536 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3539 static const media_type_desc expect_available_outputs[] =
3542 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3543 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
3544 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3547 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3548 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
3549 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3552 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3553 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
3554 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
3555 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
3556 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
3557 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 384000),
3558 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
3559 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3560 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
3563 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3564 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
3565 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
3566 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
3567 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
3568 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 192000),
3569 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
3570 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3571 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
3575 static const struct attribute_desc input_type_desc[] =
3577 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
3578 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float, .required = TRUE),
3579 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
3580 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32, .required = TRUE),
3581 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
3582 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2 * (32 / 8), .required = TRUE),
3583 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * (32 / 8) * 22050, .required = TRUE),
3584 {0},
3586 const struct attribute_desc output_type_desc[] =
3588 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
3589 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM, .required = TRUE),
3590 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
3591 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
3592 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .required = TRUE),
3593 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2 * (16 / 8), .required = TRUE),
3594 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * (16 / 8) * 44100, .required = TRUE),
3595 {0},
3597 static const struct attribute_desc expect_input_type_desc[] =
3599 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3600 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
3601 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
3602 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
3603 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
3604 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
3605 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 22050 * 8),
3606 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3607 ATTR_UINT32(MF_MT_AUDIO_CHANNEL_MASK, 3),
3608 {0},
3610 const struct attribute_desc expect_output_type_desc[] =
3612 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3613 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
3614 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
3615 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
3616 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
3617 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
3618 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 * 4),
3619 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3620 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
3621 {0},
3623 const MFT_OUTPUT_STREAM_INFO output_info =
3625 .cbSize = 4,
3626 .cbAlignment = 1,
3628 const MFT_INPUT_STREAM_INFO input_info =
3630 .cbSize = 8,
3631 .cbAlignment = 1,
3634 static const ULONG audioconv_block_size = 0x4000;
3635 const struct buffer_desc output_buffer_desc[] =
3637 {.length = audioconv_block_size, .compare = compare_pcm16},
3638 {.length = 0x3dd8, .compare = compare_pcm16, .todo_length = TRUE},
3639 {.length = 0xfc, .compare = compare_pcm16},
3641 const struct attribute_desc output_sample_attributes[] =
3643 ATTR_UINT32(mft_output_sample_incomplete, 1),
3644 ATTR_UINT32(MFSampleExtension_CleanPoint, has_video_processor /* 0 on Win7 */, .todo = TRUE),
3645 {0},
3647 const struct sample_desc output_sample_desc[] =
3650 .attributes = output_sample_attributes + 0,
3651 .sample_time = 0, .sample_duration = 928798,
3652 .buffer_count = 1, .buffers = output_buffer_desc + 0, .repeat_count = 9,
3655 .attributes = output_sample_attributes + 1, /* not MFT_OUTPUT_DATA_BUFFER_INCOMPLETE */
3656 .sample_time = 9287980, .sample_duration = 897506,
3657 .buffer_count = 1, .buffers = output_buffer_desc + 1, .todo_length = TRUE,
3660 .attributes = output_sample_attributes + 0,
3661 .sample_time = 10185486, .sample_duration = 14286,
3662 .buffer_count = 1, .buffers = output_buffer_desc + 2,
3666 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_PCM};
3667 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_Float};
3668 IMFSample *input_sample, *output_sample;
3669 IMFCollection *output_samples;
3670 DWORD length, output_status;
3671 IMFMediaType *media_type;
3672 IMFTransform *transform;
3673 const BYTE *audio_data;
3674 ULONG audio_data_len;
3675 ULONG i, ret, ref;
3676 HRESULT hr;
3678 hr = CoInitialize(NULL);
3679 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
3681 winetest_push_context("resampler");
3683 if (!check_mft_enum(MFT_CATEGORY_AUDIO_EFFECT, &input_type, &output_type, class_id))
3684 goto failed;
3685 check_mft_get_info(class_id, &expect_mft_info);
3686 check_dmo_get_info(class_id, &expect_dmo_info);
3688 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
3689 &IID_IMFTransform, (void **)&transform)))
3690 goto failed;
3692 check_interface(transform, &IID_IMFTransform, TRUE);
3693 check_interface(transform, &IID_IMediaObject, TRUE);
3694 check_interface(transform, &IID_IPropertyStore, TRUE);
3695 check_interface(transform, &IID_IPropertyBag, TRUE);
3696 /* check_interface(transform, &IID_IWMResamplerProps, TRUE); */
3698 check_mft_optional_methods(transform, 1);
3699 check_mft_get_attributes(transform, NULL, FALSE);
3700 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
3701 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
3703 i = -1;
3704 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
3706 winetest_push_context("out %lu", i);
3707 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3708 check_media_type(media_type, expect_available_outputs[i], -1);
3709 ret = IMFMediaType_Release(media_type);
3710 ok(ret == 0, "Release returned %lu\n", ret);
3711 winetest_pop_context();
3713 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3714 ok(i == 4, "%lu output media types\n", i);
3716 i = -1;
3717 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
3719 winetest_push_context("in %lu", i);
3720 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
3721 check_media_type(media_type, expect_available_inputs[i], -1);
3722 ret = IMFMediaType_Release(media_type);
3723 ok(ret == 0, "Release returned %lu\n", ret);
3724 winetest_pop_context();
3726 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
3727 ok(i == 2, "%lu input media types\n", i);
3729 /* setting output media type first doesn't work */
3730 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
3731 check_mft_get_output_current_type(transform, NULL);
3733 check_mft_set_input_type_required(transform, input_type_desc);
3734 check_mft_set_input_type(transform, input_type_desc);
3735 check_mft_get_input_current_type_(transform, expect_input_type_desc, FALSE, TRUE);
3737 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
3738 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
3740 /* check new output media types */
3742 i = -1;
3743 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
3745 winetest_push_context("out %lu", i);
3746 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3747 check_media_type(media_type, expect_available_outputs[i], -1);
3748 ret = IMFMediaType_Release(media_type);
3749 ok(ret == 0, "Release returned %lu\n", ret);
3750 winetest_pop_context();
3752 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3753 ok(i == 4, "%lu output media types\n", i);
3755 check_mft_set_output_type_required(transform, output_type_desc);
3756 check_mft_set_output_type(transform, output_type_desc, S_OK);
3757 check_mft_get_output_current_type_(transform, expect_output_type_desc, FALSE, TRUE);
3759 check_mft_get_input_stream_info(transform, S_OK, &input_info);
3760 check_mft_get_output_stream_info(transform, S_OK, &output_info);
3762 load_resource(L"audiodata.bin", &audio_data, &audio_data_len);
3763 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
3765 input_sample = create_sample(audio_data, audio_data_len);
3766 hr = IMFSample_SetSampleTime(input_sample, 0);
3767 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
3768 hr = IMFSample_SetSampleDuration(input_sample, 10000000);
3769 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
3770 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3771 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3772 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
3773 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
3774 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3775 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
3776 ret = IMFSample_Release(input_sample);
3777 ok(ret <= 1, "Release returned %ld\n", ret);
3779 hr = MFCreateCollection(&output_samples);
3780 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
3782 output_sample = create_sample(NULL, audioconv_block_size);
3783 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
3785 winetest_push_context("%lu", i);
3786 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
3787 ok(!(output_status & ~MFT_OUTPUT_DATA_BUFFER_INCOMPLETE), "got output[0].dwStatus %#lx\n", output_status);
3788 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
3789 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
3790 ref = IMFSample_Release(output_sample);
3791 ok(ref == 1, "Release returned %ld\n", ref);
3792 output_sample = create_sample(NULL, audioconv_block_size);
3793 winetest_pop_context();
3795 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3796 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3797 ret = IMFSample_Release(output_sample);
3798 ok(ret == 0, "Release returned %lu\n", ret);
3799 todo_wine
3800 ok(i == 12 || broken(i == 11) /* Win7 */, "got %lu output samples\n", i);
3802 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"audioconvdata.bin");
3803 ok(ret == 0, "got %lu%% diff\n", ret);
3804 IMFCollection_Release(output_samples);
3806 output_sample = create_sample(NULL, audioconv_block_size);
3807 hr = check_mft_process_output(transform, output_sample, &output_status);
3808 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3809 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3810 hr = IMFSample_GetTotalLength(output_sample, &length);
3811 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
3812 ok(length == 0, "got length %lu\n", length);
3813 ret = IMFSample_Release(output_sample);
3814 ok(ret == 0, "Release returned %lu\n", ret);
3816 ret = IMFTransform_Release(transform);
3817 ok(ret == 0, "Release returned %lu\n", ret);
3819 failed:
3820 winetest_pop_context();
3821 CoUninitialize();
3824 static void test_wmv_encoder(void)
3826 const GUID *const class_id = &CLSID_CWMVXEncMediaObject;
3827 const struct transform_info expect_mft_info =
3829 .name = L"WMVideo8 Encoder MFT",
3830 .major_type = &MFMediaType_Video,
3831 .inputs =
3833 {.subtype = &MFVideoFormat_IYUV},
3834 {.subtype = &MFVideoFormat_I420},
3835 {.subtype = &MFVideoFormat_YV12},
3836 {.subtype = &MFVideoFormat_NV11},
3837 {.subtype = &MFVideoFormat_NV12},
3838 {.subtype = &MFVideoFormat_YUY2},
3839 {.subtype = &MFVideoFormat_UYVY},
3840 {.subtype = &MFVideoFormat_YVYU},
3841 {.subtype = &MFVideoFormat_YVU9},
3842 {.subtype = &DMOVideoFormat_RGB32},
3843 {.subtype = &DMOVideoFormat_RGB24},
3844 {.subtype = &DMOVideoFormat_RGB565},
3845 {.subtype = &DMOVideoFormat_RGB555},
3846 {.subtype = &DMOVideoFormat_RGB8},
3848 .outputs =
3850 {.subtype = &MFVideoFormat_WMV1},
3851 {.subtype = &MFVideoFormat_WMV2},
3854 const struct transform_info expect_dmo_info =
3856 .name = L"WMVideo8 Encoder DMO",
3857 .major_type = &MEDIATYPE_Video,
3858 .inputs =
3860 {.subtype = &MEDIASUBTYPE_IYUV},
3861 {.subtype = &MEDIASUBTYPE_I420},
3862 {.subtype = &MEDIASUBTYPE_YV12},
3863 {.subtype = &MEDIASUBTYPE_NV11},
3864 {.subtype = &MEDIASUBTYPE_NV12},
3865 {.subtype = &MEDIASUBTYPE_YUY2},
3866 {.subtype = &MEDIASUBTYPE_UYVY},
3867 {.subtype = &MEDIASUBTYPE_YVYU},
3868 {.subtype = &MEDIASUBTYPE_YVU9},
3869 {.subtype = &MEDIASUBTYPE_RGB32},
3870 {.subtype = &MEDIASUBTYPE_RGB24},
3871 {.subtype = &MEDIASUBTYPE_RGB565},
3872 {.subtype = &MEDIASUBTYPE_RGB555},
3873 {.subtype = &MEDIASUBTYPE_RGB8},
3875 .outputs =
3877 {.subtype = &MEDIASUBTYPE_WMV1},
3878 {.subtype = &MEDIASUBTYPE_WMV2},
3882 static const media_type_desc expect_available_inputs[] =
3885 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3886 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
3887 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3888 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3889 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3890 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
3891 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
3892 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
3895 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3896 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
3897 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3898 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3899 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3900 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
3901 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
3902 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
3905 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3906 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
3907 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3908 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3909 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3910 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
3911 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
3912 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
3915 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3916 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11),
3917 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3918 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3919 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3920 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
3921 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
3922 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
3925 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3926 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
3927 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3928 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3929 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3930 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
3931 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
3932 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
3935 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3936 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
3937 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3938 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3939 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3940 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
3941 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
3942 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
3945 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3946 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY),
3947 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3948 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3949 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3950 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
3951 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
3952 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
3955 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3956 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU),
3957 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3958 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3959 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3960 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
3961 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
3962 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
3965 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3966 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
3967 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3968 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3969 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3970 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
3971 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
3972 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
3975 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3976 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24),
3977 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3978 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3979 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3980 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
3981 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
3982 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
3985 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3986 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565),
3987 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3988 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3989 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3990 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
3991 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
3992 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
3995 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3996 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555),
3997 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3998 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3999 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4000 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4001 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4002 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4005 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4006 ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_RGB8),
4007 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4008 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4009 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4010 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4011 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4012 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4015 static const media_type_desc expect_available_outputs[] =
4018 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4019 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1),
4020 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4021 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4022 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4023 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4026 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4027 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV2),
4028 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4029 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4030 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4031 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4035 static const DWORD actual_width = 96, actual_height = 96;
4036 const struct attribute_desc input_type_desc[] =
4038 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
4039 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE),
4040 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001, .required = TRUE),
4041 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height), /* required for SetOutputType */
4042 {0},
4044 const struct attribute_desc output_type_desc[] =
4046 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
4047 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1, .required = TRUE),
4048 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
4049 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001, .required = TRUE),
4050 ATTR_UINT32(MF_MT_AVG_BITRATE, 193540, .required = TRUE),
4051 {0},
4054 const struct attribute_desc expect_input_type_desc[] =
4056 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4057 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
4058 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
4059 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4060 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
4061 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
4062 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4063 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4064 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4065 {0},
4067 const struct attribute_desc expect_output_type_desc[] =
4069 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4070 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1),
4071 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4072 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
4073 ATTR_UINT32(MF_MT_AVG_BITRATE, 193540),
4074 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4075 {0},
4077 static const MFT_OUTPUT_STREAM_INFO empty_output_info =
4079 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER,
4081 static const MFT_INPUT_STREAM_INFO empty_input_info =
4083 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER,
4085 static const MFT_OUTPUT_STREAM_INFO expect_output_info =
4087 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER,
4088 .cbSize = 0x8000,
4089 .cbAlignment = 1,
4091 static const MFT_INPUT_STREAM_INFO expect_input_info =
4093 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER,
4094 .cbSize = 0x3600,
4095 .cbAlignment = 1,
4098 const struct buffer_desc output_buffer_desc[] =
4100 {.length = -1 /* variable */},
4102 const struct attribute_desc output_sample_attributes_key[] =
4104 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
4105 {0},
4107 const struct attribute_desc output_sample_attributes[] =
4109 ATTR_UINT32(MFSampleExtension_CleanPoint, 0),
4110 {0},
4112 const struct sample_desc output_sample_desc[] =
4115 .attributes = output_sample_attributes_key,
4116 .sample_time = 0, .sample_duration = 333333,
4117 .buffer_count = 1, .buffers = output_buffer_desc,
4120 .attributes = output_sample_attributes,
4121 .sample_time = 333333, .sample_duration = 333333,
4122 .buffer_count = 1, .buffers = output_buffer_desc, .repeat_count = 4
4126 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_WMV1};
4127 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_NV12};
4128 IMFSample *input_sample, *output_sample;
4129 DWORD status, length, output_status;
4130 MFT_OUTPUT_DATA_BUFFER output;
4131 IMFCollection *output_samples;
4132 const BYTE *nv12frame_data;
4133 IMFMediaType *media_type;
4134 ULONG nv12frame_data_len;
4135 IMFTransform *transform;
4136 ULONG i, ret;
4137 HRESULT hr;
4138 LONG ref;
4140 hr = CoInitialize(NULL);
4141 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
4143 winetest_push_context("wmvenc");
4145 if (!check_mft_enum(MFT_CATEGORY_VIDEO_ENCODER, &input_type, &output_type, class_id))
4146 goto failed;
4147 check_mft_get_info(class_id, &expect_mft_info);
4148 check_dmo_get_info(class_id, &expect_dmo_info);
4150 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
4151 &IID_IMFTransform, (void **)&transform)))
4152 goto failed;
4154 check_interface(transform, &IID_IMFTransform, TRUE);
4155 check_interface(transform, &IID_IMediaObject, TRUE);
4156 check_interface(transform, &IID_IPropertyStore, TRUE);
4157 check_interface(transform, &IID_IPropertyBag, TRUE);
4159 check_mft_optional_methods(transform, 2);
4160 check_mft_get_attributes(transform, NULL, FALSE);
4161 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, &empty_input_info);
4162 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, &empty_output_info);
4164 i = -1;
4165 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
4167 winetest_push_context("in 0 %lu", i);
4168 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
4169 ret = IMFMediaType_Release(media_type);
4170 ok(ret <= 1, "Release returned %lu\n", ret);
4171 winetest_pop_context();
4173 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
4174 ok(i == ARRAY_SIZE(expect_available_inputs), "%lu input media types\n", i);
4176 i = -1;
4177 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
4179 winetest_push_context("out %lu", i);
4180 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
4181 ret = IMFMediaType_Release(media_type);
4182 ok(ret <= 1, "Release returned %lu\n", ret);
4183 winetest_pop_context();
4185 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
4186 ok(i == ARRAY_SIZE(expect_available_outputs), "%lu output media types\n", i);
4188 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
4189 check_mft_get_output_current_type(transform, NULL);
4191 check_mft_set_input_type_required(transform, input_type_desc);
4192 check_mft_set_input_type(transform, input_type_desc);
4193 check_mft_get_input_current_type_(transform, expect_input_type_desc, FALSE, TRUE);
4195 check_mft_set_output_type_required(transform, output_type_desc);
4196 check_mft_set_output_type(transform, output_type_desc, S_OK);
4197 check_mft_get_output_current_type_(transform, expect_output_type_desc, FALSE, TRUE);
4199 check_mft_get_input_stream_info(transform, S_OK, &expect_input_info);
4200 check_mft_get_output_stream_info(transform, S_OK, &expect_output_info);
4202 if (!has_video_processor)
4204 win_skip("Skipping WMV encoder tests on Win7\n");
4205 goto done;
4208 load_resource(L"nv12frame.bmp", &nv12frame_data, &nv12frame_data_len);
4209 /* skip BMP header and RGB data from the dump */
4210 length = *(DWORD *)(nv12frame_data + 2);
4211 nv12frame_data_len = nv12frame_data_len - length;
4212 nv12frame_data = nv12frame_data + length;
4213 ok(nv12frame_data_len == 13824, "got length %lu\n", nv12frame_data_len);
4215 hr = MFCreateCollection(&output_samples);
4216 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
4218 for (i = 0; i < 5; i++)
4220 input_sample = create_sample(nv12frame_data, nv12frame_data_len);
4221 hr = IMFSample_SetSampleTime(input_sample, i * 333333);
4222 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
4223 hr = IMFSample_SetSampleDuration(input_sample, 333333);
4224 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
4225 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
4226 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
4227 ref = IMFSample_Release(input_sample);
4228 ok(ref <= 1, "Release returned %ld\n", ref);
4230 output_sample = create_sample(NULL, expect_output_info.cbSize);
4231 hr = check_mft_process_output(transform, output_sample, &output_status);
4232 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
4233 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
4234 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
4235 ref = IMFSample_Release(output_sample);
4236 ok(ref == 1, "Release returned %ld\n", ref);
4239 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"wmvencdata.bin");
4240 ok(ret == 0, "got %lu%% diff\n", ret);
4241 IMFCollection_Release(output_samples);
4243 output_sample = create_sample(NULL, expect_output_info.cbSize);
4244 status = 0xdeadbeef;
4245 memset(&output, 0, sizeof(output));
4246 output.pSample = output_sample;
4247 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
4248 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
4249 ok(output.pSample == output_sample, "got pSample %p\n", output.pSample);
4250 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
4251 ok(status == 0, "got status %#lx\n", status);
4252 hr = IMFSample_GetTotalLength(output.pSample, &length);
4253 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
4254 ok(length == 0, "got length %lu\n", length);
4255 ret = IMFSample_Release(output_sample);
4256 ok(ret == 0, "Release returned %lu\n", ret);
4258 done:
4259 ret = IMFTransform_Release(transform);
4260 ok(ret == 0, "Release returned %lu\n", ret);
4262 failed:
4263 winetest_pop_context();
4264 CoUninitialize();
4267 static void test_wmv_decoder(void)
4269 const GUID *const class_id = &CLSID_CWMVDecMediaObject;
4270 const struct transform_info expect_mft_info =
4272 .name = L"WMVideo Decoder MFT",
4273 .major_type = &MFMediaType_Video,
4274 .inputs =
4276 {.subtype = &MFVideoFormat_WMV1},
4277 {.subtype = &MFVideoFormat_WMV2},
4278 {.subtype = &MFVideoFormat_WMV3},
4279 {.subtype = &MEDIASUBTYPE_WMVP},
4280 {.subtype = &MEDIASUBTYPE_WVP2},
4281 {.subtype = &MEDIASUBTYPE_WMVR},
4282 {.subtype = &MEDIASUBTYPE_WMVA},
4283 {.subtype = &MFVideoFormat_WVC1},
4284 {.subtype = &MFVideoFormat_VC1S},
4286 .outputs =
4288 {.subtype = &MFVideoFormat_YV12},
4289 {.subtype = &MFVideoFormat_YUY2},
4290 {.subtype = &MFVideoFormat_UYVY},
4291 {.subtype = &MFVideoFormat_YVYU},
4292 {.subtype = &MFVideoFormat_NV11},
4293 {.subtype = &MFVideoFormat_NV12},
4294 {.subtype = &DMOVideoFormat_RGB32},
4295 {.subtype = &DMOVideoFormat_RGB24},
4296 {.subtype = &DMOVideoFormat_RGB565},
4297 {.subtype = &DMOVideoFormat_RGB555},
4298 {.subtype = &DMOVideoFormat_RGB8},
4301 const struct transform_info expect_dmo_info =
4303 .name = L"WMVideo Decoder DMO",
4304 .major_type = &MEDIATYPE_Video,
4305 .inputs =
4307 {.subtype = &MEDIASUBTYPE_WMV1},
4308 {.subtype = &MEDIASUBTYPE_WMV2},
4309 {.subtype = &MEDIASUBTYPE_WMV3},
4310 {.subtype = &MEDIASUBTYPE_WMVA},
4311 {.subtype = &MEDIASUBTYPE_WVC1},
4312 {.subtype = &MEDIASUBTYPE_WMVP},
4313 {.subtype = &MEDIASUBTYPE_WVP2},
4314 {.subtype = &MFVideoFormat_VC1S},
4316 .outputs =
4318 {.subtype = &MEDIASUBTYPE_YV12},
4319 {.subtype = &MEDIASUBTYPE_YUY2},
4320 {.subtype = &MEDIASUBTYPE_UYVY},
4321 {.subtype = &MEDIASUBTYPE_YVYU},
4322 {.subtype = &MEDIASUBTYPE_NV11},
4323 {.subtype = &MEDIASUBTYPE_NV12},
4324 {.subtype = &MEDIASUBTYPE_RGB32},
4325 {.subtype = &MEDIASUBTYPE_RGB24},
4326 {.subtype = &MEDIASUBTYPE_RGB565},
4327 {.subtype = &MEDIASUBTYPE_RGB555},
4328 {.subtype = &MEDIASUBTYPE_RGB8},
4332 static const struct attribute_desc expect_common_attributes[] =
4334 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4335 {0},
4337 static const media_type_desc expect_available_inputs[] =
4339 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1)},
4340 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV2)},
4341 {ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_WMVA)},
4342 {ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_WMVP)},
4343 {ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_WVP2)},
4344 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV_Unknown)},
4345 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WVC1)},
4346 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV3)},
4347 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_VC1S)},
4349 static const MFVideoArea actual_aperture = {.Area={96,96}};
4350 static const DWORD actual_width = 96, actual_height = 96;
4351 const struct attribute_desc expect_output_attributes[] =
4353 ATTR_BLOB(MF_MT_GEOMETRIC_APERTURE, &actual_aperture, sizeof(actual_aperture)),
4354 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, sizeof(actual_aperture)),
4355 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4356 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4357 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4358 ATTR_UINT32(MF_MT_INTERLACE_MODE, 2),
4359 {0},
4361 const media_type_desc expect_available_outputs[] =
4364 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4365 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
4366 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4367 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
4368 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
4371 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4372 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
4373 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4374 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
4375 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
4378 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4379 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
4380 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4381 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
4382 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
4385 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4386 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
4387 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4388 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
4389 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
4392 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4393 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
4394 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4395 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
4396 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
4399 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4400 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY),
4401 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4402 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
4403 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
4406 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4407 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU),
4408 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4409 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
4410 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
4413 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4414 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11),
4415 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4416 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
4417 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
4420 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4421 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
4422 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4423 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 4),
4424 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 4),
4427 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4428 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24),
4429 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4430 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 3),
4431 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3),
4434 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4435 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565),
4436 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4437 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
4438 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
4439 /* ATTR_BLOB(MF_MT_PALETTE, ... with 12 elements), */
4442 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4443 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555),
4444 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4445 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
4446 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
4449 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4450 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB8),
4451 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4452 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
4453 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height),
4454 /* ATTR_BLOB(MF_MT_PALETTE, ... with 904 elements), */
4457 const struct attribute_desc expect_attributes[] =
4459 ATTR_UINT32(MF_LOW_LATENCY, 0),
4460 ATTR_UINT32(MF_SA_D3D11_AWARE, 1),
4461 ATTR_UINT32(MF_SA_D3D_AWARE, 1),
4462 ATTR_UINT32(MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER, 0),
4463 /* more attributes from CODECAPI */
4464 {0},
4466 const struct attribute_desc input_type_desc[] =
4468 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
4469 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1, .required = TRUE),
4470 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
4471 {0},
4473 const struct attribute_desc output_type_desc[] =
4475 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
4476 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE),
4477 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
4478 {0},
4480 const struct attribute_desc expect_input_type_desc[] =
4482 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4483 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1),
4484 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4485 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4486 {0},
4488 const struct attribute_desc expect_output_type_desc[] =
4490 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4491 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
4492 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4493 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
4494 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
4495 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4496 ATTR_UINT32(MF_MT_VIDEO_NOMINAL_RANGE, 2),
4497 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4498 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4499 {0},
4501 const MFT_OUTPUT_STREAM_INFO expect_output_info =
4503 .dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_DISCARDABLE,
4504 .cbSize = 0x3600,
4505 .cbAlignment = 1,
4507 const MFT_OUTPUT_STREAM_INFO empty_output_info =
4509 .dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_DISCARDABLE,
4511 const MFT_INPUT_STREAM_INFO expect_input_info =
4513 .cbSize = 0x3600,
4514 .cbAlignment = 1,
4517 const struct attribute_desc output_sample_attributes[] =
4519 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
4520 {0},
4522 const struct buffer_desc output_buffer_desc_nv12 =
4524 .length = actual_width * actual_height * 3 / 2,
4525 .compare = compare_nv12, .dump = dump_nv12, .rect = {.right = 82, .bottom = 84},
4527 const struct sample_desc output_sample_desc_nv12 =
4529 .attributes = output_sample_attributes,
4530 .sample_time = 0, .sample_duration = 333333,
4531 .buffer_count = 1, .buffers = &output_buffer_desc_nv12,
4534 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
4535 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_WMV1};
4536 IMFSample *input_sample, *output_sample;
4537 IMFCollection *output_samples;
4538 IMFMediaType *media_type;
4539 IMFTransform *transform;
4540 const BYTE *wmvenc_data;
4541 ULONG wmvenc_data_len;
4542 DWORD output_status;
4543 ULONG i, ret, ref;
4544 HRESULT hr;
4546 hr = CoInitialize(NULL);
4547 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
4549 winetest_push_context("wmvdec");
4551 if (!has_video_processor)
4553 win_skip("Skipping inconsistent WMV decoder tests on Win7\n");
4554 goto failed;
4557 if (!check_mft_enum(MFT_CATEGORY_VIDEO_DECODER, &input_type, &output_type, class_id))
4558 goto failed;
4559 check_mft_get_info(class_id, &expect_mft_info);
4560 check_dmo_get_info(class_id, &expect_dmo_info);
4562 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
4563 &IID_IMFTransform, (void **)&transform)))
4564 goto failed;
4566 check_interface(transform, &IID_IMFTransform, TRUE);
4567 check_interface(transform, &IID_IMediaObject, TRUE);
4568 check_interface(transform, &IID_IPropertyStore, TRUE);
4569 check_interface(transform, &IID_IPropertyBag, TRUE);
4571 check_mft_optional_methods(transform, 1);
4572 check_mft_get_attributes(transform, expect_attributes, TRUE);
4573 todo_wine
4574 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
4575 todo_wine
4576 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, &empty_output_info);
4578 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
4579 todo_wine
4580 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
4582 i = -1;
4583 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
4585 winetest_push_context("in %lu", i);
4586 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
4587 check_media_type(media_type, expect_common_attributes, -1);
4588 check_media_type(media_type, expect_available_inputs[i], -1);
4589 ret = IMFMediaType_Release(media_type);
4590 ok(!ret, "Release returned %lu\n", ret);
4591 winetest_pop_context();
4593 todo_wine
4594 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
4595 todo_wine
4596 ok(i == ARRAY_SIZE(expect_available_inputs), "%lu input media types\n", i);
4598 if (hr == E_NOTIMPL)
4599 goto skip_tests;
4601 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
4602 check_mft_get_output_current_type(transform, NULL);
4604 check_mft_set_input_type_required(transform, input_type_desc);
4605 check_mft_set_input_type(transform, input_type_desc);
4606 check_mft_get_input_current_type_(transform, expect_input_type_desc, FALSE, TRUE);
4608 i = -1;
4609 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
4611 winetest_push_context("out %lu", i);
4612 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
4613 check_media_type(media_type, expect_common_attributes, -1);
4614 check_media_type(media_type, expect_output_attributes, -1);
4615 check_media_type(media_type, expect_available_outputs[i], -1);
4616 ret = IMFMediaType_Release(media_type);
4617 ok(!ret, "Release returned %lu\n", ret);
4618 winetest_pop_context();
4620 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
4621 ok(i == ARRAY_SIZE(expect_available_outputs), "%lu input media types\n", i);
4623 check_mft_set_output_type_required(transform, output_type_desc);
4624 check_mft_set_output_type(transform, output_type_desc, S_OK);
4625 check_mft_get_output_current_type_(transform, expect_output_type_desc, FALSE, TRUE);
4627 check_mft_get_input_stream_info(transform, S_OK, &expect_input_info);
4628 check_mft_get_output_stream_info(transform, S_OK, &expect_output_info);
4630 load_resource(L"wmvencdata.bin", &wmvenc_data, &wmvenc_data_len);
4632 input_sample = create_sample(wmvenc_data + sizeof(DWORD), *(DWORD *)wmvenc_data);
4633 wmvenc_data_len -= *(DWORD *)wmvenc_data + sizeof(DWORD);
4634 wmvenc_data += *(DWORD *)wmvenc_data + sizeof(DWORD);
4635 hr = IMFSample_SetSampleTime(input_sample, 0);
4636 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
4637 hr = IMFSample_SetSampleDuration(input_sample, 333333);
4638 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
4639 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
4640 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
4641 ret = IMFSample_Release(input_sample);
4642 ok(ret <= 1, "Release returned %ld\n", ret);
4644 hr = MFCreateCollection(&output_samples);
4645 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
4647 output_sample = create_sample(NULL, expect_output_info.cbSize);
4648 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
4650 winetest_push_context("%lu", i);
4651 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
4652 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
4653 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
4654 ref = IMFSample_Release(output_sample);
4655 ok(ref == 1, "Release returned %ld\n", ref);
4656 output_sample = create_sample(NULL, expect_output_info.cbSize);
4657 winetest_pop_context();
4659 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
4660 ret = IMFSample_Release(output_sample);
4661 ok(ret == 0, "Release returned %lu\n", ret);
4662 ok(i == 1, "got %lu output samples\n", i);
4664 ret = check_mf_sample_collection(output_samples, &output_sample_desc_nv12, L"nv12frame.bmp");
4665 ok(ret == 0, "got %lu%% diff\n", ret);
4666 IMFCollection_Release(output_samples);
4668 skip_tests:
4669 ret = IMFTransform_Release(transform);
4670 ok(ret == 0, "Release returned %lu\n", ret);
4672 failed:
4673 winetest_pop_context();
4674 CoUninitialize();
4677 static void test_wmv_decoder_media_object(void)
4679 const GUID *const class_id = &CLSID_CWMVDecMediaObject;
4680 const DMO_MEDIA_TYPE expected_input_types[] =
4682 {MFMediaType_Video, MEDIASUBTYPE_WMV1, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
4683 {MFMediaType_Video, MEDIASUBTYPE_WMV2, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
4684 {MFMediaType_Video, MEDIASUBTYPE_WMVA, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
4685 {MFMediaType_Video, MEDIASUBTYPE_WMVP, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
4686 {MFMediaType_Video, MEDIASUBTYPE_WVP2, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
4687 {MFMediaType_Video, MFVideoFormat_WMV_Unknown, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
4688 {MFMediaType_Video, MEDIASUBTYPE_WVC1, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
4689 {MFMediaType_Video, MEDIASUBTYPE_WMV3, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
4690 {MFMediaType_Video, MFVideoFormat_VC1S, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
4692 const VIDEOINFOHEADER expected_output_info[] =
4694 {{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}},
4695 {{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}},
4696 {{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}},
4697 {{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}},
4698 {{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}},
4699 {{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}},
4700 {{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}},
4701 {{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}},
4702 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 32, BI_RGB, 1024, 0, 0, 0, 0}},
4703 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 24, BI_RGB, 768, 0, 0, 0, 0}},
4704 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 16, BI_BITFIELDS, 512, 0, 0, 0, 0}},
4705 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 16, BI_RGB, 512, 0, 0, 0, 0}},
4706 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 8, BI_RGB, 256, 0, 0, 226, 226}},
4708 const DMO_MEDIA_TYPE expected_output_types[] =
4710 {MFMediaType_Video, MEDIASUBTYPE_NV12, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[0]},
4711 {MFMediaType_Video, MEDIASUBTYPE_YV12, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[1]},
4712 {MFMediaType_Video, MEDIASUBTYPE_IYUV, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[2]},
4713 {MFMediaType_Video, MEDIASUBTYPE_I420, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[3]},
4714 {MFMediaType_Video, MEDIASUBTYPE_YUY2, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[4]},
4715 {MFMediaType_Video, MEDIASUBTYPE_UYVY, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[5]},
4716 {MFMediaType_Video, MEDIASUBTYPE_YVYU, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[6]},
4717 {MFMediaType_Video, MEDIASUBTYPE_NV11, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[7]},
4718 {MFMediaType_Video, MEDIASUBTYPE_RGB32, TRUE, FALSE, 1024, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[8]},
4719 {MFMediaType_Video, MEDIASUBTYPE_RGB24, TRUE, FALSE, 768, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[9]},
4720 {MFMediaType_Video, MEDIASUBTYPE_RGB565, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 100, (BYTE *)&expected_output_info[10]},
4721 {MFMediaType_Video, MEDIASUBTYPE_RGB555, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[11]},
4722 {MFMediaType_Video, MEDIASUBTYPE_RGB8, TRUE, FALSE, 256, FORMAT_VideoInfo, NULL, 1112, (BYTE *)&expected_output_info[12]},
4724 const struct set_type_arg
4726 DWORD stream_index;
4727 enum
4729 MEDIA_TYPE_NULL = 0,
4730 MEDIA_TYPE_GOOD = 1,
4731 MEDIA_TYPE_BAD = 2,
4732 } media_type;
4733 DWORD flags;
4734 HRESULT hr;
4736 set_type_arg_tests[] =
4738 {1, MEDIA_TYPE_NULL, 0, DMO_E_INVALIDSTREAMINDEX},
4739 {1, MEDIA_TYPE_NULL, 0x4, DMO_E_INVALIDSTREAMINDEX},
4740 {1, MEDIA_TYPE_NULL, DMO_SET_TYPEF_CLEAR, DMO_E_INVALIDSTREAMINDEX},
4741 {1, MEDIA_TYPE_NULL, DMO_SET_TYPEF_TEST_ONLY, DMO_E_INVALIDSTREAMINDEX},
4742 {1, MEDIA_TYPE_GOOD, 0, DMO_E_INVALIDSTREAMINDEX},
4743 {1, MEDIA_TYPE_GOOD, 0x4, DMO_E_INVALIDSTREAMINDEX},
4744 {1, MEDIA_TYPE_GOOD, DMO_SET_TYPEF_CLEAR, DMO_E_INVALIDSTREAMINDEX},
4745 {1, MEDIA_TYPE_GOOD, DMO_SET_TYPEF_TEST_ONLY, DMO_E_INVALIDSTREAMINDEX},
4746 {1, MEDIA_TYPE_BAD, 0, DMO_E_INVALIDSTREAMINDEX},
4747 {1, MEDIA_TYPE_BAD, 0x4, DMO_E_INVALIDSTREAMINDEX},
4748 {1, MEDIA_TYPE_BAD, DMO_SET_TYPEF_CLEAR, DMO_E_INVALIDSTREAMINDEX},
4749 {1, MEDIA_TYPE_BAD, DMO_SET_TYPEF_TEST_ONLY, DMO_E_INVALIDSTREAMINDEX},
4750 {0, MEDIA_TYPE_BAD, 0, DMO_E_TYPE_NOT_ACCEPTED},
4751 {0, MEDIA_TYPE_BAD, 0x4, DMO_E_TYPE_NOT_ACCEPTED},
4752 {0, MEDIA_TYPE_BAD, DMO_SET_TYPEF_CLEAR, DMO_E_TYPE_NOT_ACCEPTED},
4753 {0, MEDIA_TYPE_BAD, DMO_SET_TYPEF_TEST_ONLY, DMO_E_TYPE_NOT_ACCEPTED},
4754 {0, MEDIA_TYPE_NULL, 0, DMO_E_TYPE_NOT_ACCEPTED},
4755 {0, MEDIA_TYPE_NULL, 0x4, DMO_E_TYPE_NOT_ACCEPTED},
4756 {0, MEDIA_TYPE_NULL, DMO_SET_TYPEF_TEST_ONLY, DMO_E_TYPE_NOT_ACCEPTED},
4757 {0, MEDIA_TYPE_NULL, DMO_SET_TYPEF_CLEAR, S_OK},
4758 {0, MEDIA_TYPE_NULL, DMO_SET_TYPEF_CLEAR | 0x4, S_OK},
4759 {0, MEDIA_TYPE_NULL, DMO_SET_TYPEF_CLEAR | DMO_SET_TYPEF_TEST_ONLY, S_OK},
4760 {0, MEDIA_TYPE_NULL, DMO_SET_TYPEF_CLEAR | DMO_SET_TYPEF_TEST_ONLY | 0x4, S_OK},
4761 {0, MEDIA_TYPE_GOOD, 0x4, S_OK},
4762 {0, MEDIA_TYPE_GOOD, DMO_SET_TYPEF_CLEAR, S_OK},
4763 {0, MEDIA_TYPE_GOOD, DMO_SET_TYPEF_CLEAR | DMO_SET_TYPEF_TEST_ONLY, S_OK},
4765 DMO_MEDIA_TYPE media_type, *input_type;
4766 IMediaObject *media_object;
4767 DWORD in_count, out_count;
4768 VIDEOINFOHEADER *header;
4769 char buffer[1024];
4770 ULONG ret, i;
4771 HRESULT hr;
4773 winetest_push_context("wmvdec");
4775 if (!has_video_processor)
4777 win_skip("Skipping inconsistent WMV decoder media object tests on Win7.\n");
4778 winetest_pop_context();
4779 return;
4782 hr = CoInitialize(NULL);
4783 ok(hr == S_OK, "CoInitialize failed, hr %#lx.\n", hr);
4785 hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER, &IID_IMediaObject, (void **)&media_object);
4786 ok(hr == S_OK, "CoCreateInstance returned %#lx.\n", hr);
4788 /* Test GetStreamCount. */
4789 in_count = out_count = 0xdeadbeef;
4790 hr = IMediaObject_GetStreamCount(media_object, &in_count, &out_count);
4791 ok(hr == S_OK, "GetStreamCount returned %#lx.\n", hr);
4792 ok(in_count == 1, "Got unexpected in_count %lu.\n", in_count);
4793 ok(out_count == 1, "Got unexpected in_count %lu.\n", out_count);
4795 /* Test GetStreamCount with invalid arguments. */
4796 in_count = out_count = 0xdeadbeef;
4797 hr = IMediaObject_GetStreamCount(media_object, NULL, &out_count);
4798 ok(hr == E_POINTER, "GetStreamCount returned %#lx.\n", hr);
4799 ok(out_count == 0xdeadbeef, "Got unexpected out_count %lu.\n", out_count);
4800 hr = IMediaObject_GetStreamCount(media_object, &in_count, NULL);
4801 ok(hr == E_POINTER, "GetStreamCount returned %#lx.\n", hr);
4802 ok(in_count == 0xdeadbeef, "Got unexpected in_count %lu.\n", in_count);
4804 /* Test GetInputType. */
4805 check_dmo_get_input_type(media_object, expected_input_types, ARRAY_SIZE(expected_input_types));
4807 /* Test SetInputType. */
4808 input_type = (DMO_MEDIA_TYPE *)buffer;
4809 header = (VIDEOINFOHEADER *)(input_type + 1);
4810 for (i = 0; i < ARRAY_SIZE(expected_input_types); ++i)
4812 const GUID *subtype = &expected_input_types[i].subtype;
4814 if (IsEqualGUID(subtype, &MEDIASUBTYPE_WMV2)
4815 || IsEqualGUID(subtype, &MEDIASUBTYPE_WMVA)
4816 || IsEqualGUID(subtype, &MEDIASUBTYPE_WVP2)
4817 || IsEqualGUID(subtype, &MEDIASUBTYPE_WVC1)
4818 || IsEqualGUID(subtype, &MFVideoFormat_VC1S))
4820 skip("Skipping SetInputType tests for video subtype %s.\n", debugstr_guid(subtype));
4821 continue;
4824 winetest_push_context("in %lu", i);
4826 /* Test setting the type. */
4827 init_dmo_media_type_video(input_type, subtype, 96, 96);
4828 hr = IMediaObject_SetInputType(media_object, 0, input_type, DMO_SET_TYPEF_TEST_ONLY);
4829 ok(hr == S_OK, "SetInputType returned unexpected hr %#lx.\n", hr);
4830 hr = IMediaObject_SetInputType(media_object, 0, input_type, 0);
4831 ok(hr == S_OK, "SetInputType returned unexpected hr %#lx.\n", hr);
4832 header->dwBitRate = 0xdeadbeef;
4833 header->dwBitErrorRate = 0xdeadbeef;
4834 header->AvgTimePerFrame = 0xdeadbeef;
4835 header->bmiHeader.biPlanes = 0xdead;
4836 header->bmiHeader.biBitCount = 0xdead;
4837 header->bmiHeader.biSizeImage = 0xdeadbeef;
4838 header->bmiHeader.biXPelsPerMeter = 0xdead;
4839 header->bmiHeader.biYPelsPerMeter = 0xdead;
4840 hr = IMediaObject_SetInputType(media_object, 0, input_type, 0);
4841 ok(hr == S_OK, "SetInputType returned unexpected hr %#lx.\n", hr);
4843 /* Test invalid major type. */
4844 init_dmo_media_type_video(input_type, subtype, 96, 96);
4845 input_type->majortype = MFMediaType_Default;
4846 hr = IMediaObject_SetInputType(media_object, 0, input_type, DMO_SET_TYPEF_TEST_ONLY);
4847 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned unexpected hr %#lx.\n", hr);
4849 /* Test invalid subtype. */
4850 init_dmo_media_type_video(input_type, &MEDIASUBTYPE_None, 96, 96);
4851 hr = IMediaObject_SetInputType(media_object, 0, input_type, DMO_SET_TYPEF_TEST_ONLY);
4852 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned unexpected hr %#lx.\n", hr);
4854 /* Test invalid format type. */
4855 init_dmo_media_type_video(input_type, subtype, 96, 96);
4856 input_type->formattype = FORMAT_None;
4857 hr = IMediaObject_SetInputType(media_object, 0, input_type, DMO_SET_TYPEF_TEST_ONLY);
4858 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned unexpected hr %#lx.\n", hr);
4860 /* Test invalid format size. */
4861 init_dmo_media_type_video(input_type, subtype, 96, 96);
4862 input_type->cbFormat = 1;
4863 hr = IMediaObject_SetInputType(media_object, 0, input_type, DMO_SET_TYPEF_TEST_ONLY);
4864 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned unexpected hr %#lx.\n", hr);
4866 /* Test NULL format pointer. */
4867 init_dmo_media_type_video(input_type, subtype, 96, 96);
4868 input_type->pbFormat = NULL;
4869 hr = IMediaObject_SetInputType(media_object, 0, input_type, DMO_SET_TYPEF_TEST_ONLY);
4870 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned unexpected hr %#lx.\n", hr);
4872 /* Test video header struct size. */
4873 init_dmo_media_type_video(input_type, subtype, 96, 96);
4874 header->bmiHeader.biSize = 0;
4875 hr = IMediaObject_SetInputType(media_object, 0, input_type, DMO_SET_TYPEF_TEST_ONLY);
4876 todo_wine
4877 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned unexpected hr %#lx.\n", hr);
4878 header->bmiHeader.biSize = 1;
4879 hr = IMediaObject_SetInputType(media_object, 0, input_type, DMO_SET_TYPEF_TEST_ONLY);
4880 todo_wine
4881 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned unexpected hr %#lx.\n", hr);
4882 header->bmiHeader.biSize = 0xdeadbeef;
4883 hr = IMediaObject_SetInputType(media_object, 0, input_type, DMO_SET_TYPEF_TEST_ONLY);
4884 todo_wine
4885 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned unexpected hr %#lx.\n", hr);
4887 /* Test width. */
4888 init_dmo_media_type_video(input_type, subtype, 96, 96);
4889 header->bmiHeader.biWidth = 0;
4890 hr = IMediaObject_SetInputType(media_object, 0, input_type, DMO_SET_TYPEF_TEST_ONLY);
4891 todo_wine
4892 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned unexpected hr %#lx.\n", hr);
4893 header->bmiHeader.biWidth = -1;
4894 hr = IMediaObject_SetInputType(media_object, 0, input_type, DMO_SET_TYPEF_TEST_ONLY);
4895 todo_wine
4896 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned unexpected hr %#lx.\n", hr);
4897 header->bmiHeader.biWidth = 4096 + 1;
4898 hr = IMediaObject_SetInputType(media_object, 0, input_type, DMO_SET_TYPEF_TEST_ONLY);
4899 todo_wine
4900 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned unexpected hr %#lx.\n", hr);
4901 header->bmiHeader.biWidth = 4096;
4902 hr = IMediaObject_SetInputType(media_object, 0, input_type, DMO_SET_TYPEF_TEST_ONLY);
4903 ok(hr == S_OK, "SetInputType returned unexpected hr %#lx.\n", hr);
4905 /* Test height. */
4906 init_dmo_media_type_video(input_type, subtype, 96, 96);
4907 header->bmiHeader.biHeight = 0;
4908 hr = IMediaObject_SetInputType(media_object, 0, input_type, DMO_SET_TYPEF_TEST_ONLY);
4909 todo_wine
4910 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned unexpected hr %#lx.\n", hr);
4911 header->bmiHeader.biHeight = 4096 + 1;
4912 hr = IMediaObject_SetInputType(media_object, 0, input_type, DMO_SET_TYPEF_TEST_ONLY);
4913 todo_wine
4914 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned unexpected hr %#lx.\n", hr);
4915 header->bmiHeader.biHeight = 4096;
4916 hr = IMediaObject_SetInputType(media_object, 0, input_type, DMO_SET_TYPEF_TEST_ONLY);
4917 ok(hr == S_OK, "SetInputType returned unexpected hr %#lx.\n", hr);
4918 header->bmiHeader.biHeight = -4096;
4919 hr = IMediaObject_SetInputType(media_object, 0, input_type, DMO_SET_TYPEF_TEST_ONLY);
4920 ok(hr == S_OK, "SetInputType returned unexpected hr %#lx.\n", hr);
4922 /* Test compression. */
4923 init_dmo_media_type_video(input_type, subtype, 96, 96);
4924 header->bmiHeader.biCompression = 0;
4925 hr = IMediaObject_SetInputType(media_object, 0, input_type, DMO_SET_TYPEF_TEST_ONLY);
4926 todo_wine
4927 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned unexpected hr %#lx.\n", hr);
4928 header->bmiHeader.biCompression = 1;
4929 hr = IMediaObject_SetInputType(media_object, 0, input_type, DMO_SET_TYPEF_TEST_ONLY);
4930 ok(hr == S_OK, "SetInputType returned unexpected hr %#lx.\n", hr);
4931 header->bmiHeader.biCompression = 2;
4932 hr = IMediaObject_SetInputType(media_object, 0, input_type, DMO_SET_TYPEF_TEST_ONLY);
4933 ok(hr == S_OK, "SetInputType returned unexpected hr %#lx.\n", hr);
4934 header->bmiHeader.biCompression = 0xdeadbeef;
4935 hr = IMediaObject_SetInputType(media_object, 0, input_type, DMO_SET_TYPEF_TEST_ONLY);
4936 ok(hr == S_OK, "SetInputType returned unexpected hr %#lx.\n", hr);
4938 winetest_pop_context();
4941 /* Test SetInputType arguments. */
4942 memset(&media_type, 0, sizeof(media_type));
4943 init_dmo_media_type_video(input_type, &expected_input_types[0].subtype, 96, 96);
4944 for (i = 0; i < ARRAY_SIZE(set_type_arg_tests); ++i)
4946 const struct set_type_arg *test = &set_type_arg_tests[i];
4947 DMO_MEDIA_TYPE *type;
4949 winetest_push_context("Test %lu", i);
4951 if (test->media_type == MEDIA_TYPE_GOOD)
4952 type = input_type;
4953 else if (test->media_type == MEDIA_TYPE_BAD)
4954 type = &media_type;
4955 else
4956 type = NULL;
4958 hr = IMediaObject_SetInputType(media_object, test->stream_index, type, test->flags);
4959 ok(hr == test->hr, "SetInputType returned unexpected hr %#lx, expected %#lx.\n", hr, test->hr);
4961 winetest_pop_context();
4964 /* Test GetOutputType without setting input type. */
4965 hr = IMediaObject_SetInputType(media_object, 0, NULL, DMO_SET_TYPEF_CLEAR);
4966 ok(hr == S_OK, "SetInputType returned unexpected hr %#lx.\n", hr);
4967 hr = IMediaObject_GetOutputType(media_object, 0, 0, &media_type);
4968 todo_wine
4969 ok(hr == DMO_E_TYPE_NOT_SET, "GetOutputType returned unexpected hr %#lx.\n", hr);
4971 /* Test GetOutputType after setting input type. */
4972 for (i = 0; i < ARRAY_SIZE(expected_input_types); ++i)
4974 const GUID *subtype = &expected_input_types[i].subtype;
4975 if (IsEqualGUID(subtype, &MEDIASUBTYPE_WMV2)
4976 || IsEqualGUID(subtype, &MEDIASUBTYPE_WMVA)
4977 || IsEqualGUID(subtype, &MEDIASUBTYPE_WVP2)
4978 || IsEqualGUID(subtype, &MEDIASUBTYPE_WVC1)
4979 || IsEqualGUID(subtype, &MFVideoFormat_VC1S))
4981 skip("Skipping GetOutputType tests for input subtype %s.\n", debugstr_guid(subtype));
4982 continue;
4985 winetest_push_context("in %lu", i);
4987 init_dmo_media_type_video(input_type, &expected_input_types[i].subtype, 16, 16);
4988 hr = IMediaObject_SetInputType(media_object, 0, input_type, 0);
4989 ok(hr == S_OK, "SetInputType returned unexpected hr %#lx.\n", hr);
4991 todo_wine
4992 check_dmo_get_output_type(media_object, expected_output_types, ARRAY_SIZE(expected_output_types));
4994 winetest_pop_context();
4997 ret = IMediaObject_Release(media_object);
4998 ok(ret == 0, "Release returned %lu\n", ret);
4999 CoUninitialize();
5000 winetest_pop_context();
5003 static void test_color_convert(void)
5005 const GUID *const class_id = &CLSID_CColorConvertDMO;
5006 const struct transform_info expect_mft_info =
5008 .name = L"Color Converter MFT",
5009 .major_type = &MFMediaType_Video,
5010 .inputs =
5012 {.subtype = &MFVideoFormat_YV12},
5013 {.subtype = &MFVideoFormat_YUY2},
5014 {.subtype = &MFVideoFormat_UYVY},
5015 {.subtype = &MFVideoFormat_AYUV},
5016 {.subtype = &MFVideoFormat_NV12},
5017 {.subtype = &DMOVideoFormat_RGB32},
5018 {.subtype = &DMOVideoFormat_RGB565},
5019 {.subtype = &MFVideoFormat_I420},
5020 {.subtype = &MFVideoFormat_IYUV},
5021 {.subtype = &MFVideoFormat_YVYU},
5022 {.subtype = &DMOVideoFormat_RGB24},
5023 {.subtype = &DMOVideoFormat_RGB555},
5024 {.subtype = &DMOVideoFormat_RGB8},
5025 {.subtype = &MEDIASUBTYPE_V216},
5026 {.subtype = &MEDIASUBTYPE_V410},
5027 {.subtype = &MFVideoFormat_NV11},
5028 {.subtype = &MFVideoFormat_Y41P},
5029 {.subtype = &MFVideoFormat_Y41T},
5030 {.subtype = &MFVideoFormat_Y42T},
5031 {.subtype = &MFVideoFormat_YVU9},
5033 .outputs =
5035 {.subtype = &MFVideoFormat_YV12},
5036 {.subtype = &MFVideoFormat_YUY2},
5037 {.subtype = &MFVideoFormat_UYVY},
5038 {.subtype = &MFVideoFormat_AYUV},
5039 {.subtype = &MFVideoFormat_NV12},
5040 {.subtype = &DMOVideoFormat_RGB32},
5041 {.subtype = &DMOVideoFormat_RGB565},
5042 {.subtype = &MFVideoFormat_I420},
5043 {.subtype = &MFVideoFormat_IYUV},
5044 {.subtype = &MFVideoFormat_YVYU},
5045 {.subtype = &DMOVideoFormat_RGB24},
5046 {.subtype = &DMOVideoFormat_RGB555},
5047 {.subtype = &DMOVideoFormat_RGB8},
5048 {.subtype = &MEDIASUBTYPE_V216},
5049 {.subtype = &MEDIASUBTYPE_V410},
5050 {.subtype = &MFVideoFormat_NV11},
5053 const struct transform_info expect_dmo_info =
5055 .name = L"Color Converter DMO",
5056 .major_type = &MEDIATYPE_Video,
5057 .inputs =
5059 {.subtype = &MEDIASUBTYPE_YV12},
5060 {.subtype = &MEDIASUBTYPE_YUY2},
5061 {.subtype = &MEDIASUBTYPE_UYVY},
5062 {.subtype = &MEDIASUBTYPE_AYUV},
5063 {.subtype = &MEDIASUBTYPE_NV12},
5064 {.subtype = &MEDIASUBTYPE_RGB32},
5065 {.subtype = &MEDIASUBTYPE_RGB565},
5066 {.subtype = &MEDIASUBTYPE_I420},
5067 {.subtype = &MEDIASUBTYPE_IYUV},
5068 {.subtype = &MEDIASUBTYPE_YVYU},
5069 {.subtype = &MEDIASUBTYPE_RGB24},
5070 {.subtype = &MEDIASUBTYPE_RGB555},
5071 {.subtype = &MEDIASUBTYPE_RGB8},
5072 {.subtype = &MEDIASUBTYPE_V216},
5073 {.subtype = &MEDIASUBTYPE_V410},
5074 {.subtype = &MEDIASUBTYPE_NV11},
5075 {.subtype = &MEDIASUBTYPE_Y41P},
5076 {.subtype = &MEDIASUBTYPE_Y41T},
5077 {.subtype = &MEDIASUBTYPE_Y42T},
5078 {.subtype = &MEDIASUBTYPE_YVU9},
5080 .outputs =
5082 {.subtype = &MEDIASUBTYPE_YV12},
5083 {.subtype = &MEDIASUBTYPE_YUY2},
5084 {.subtype = &MEDIASUBTYPE_UYVY},
5085 {.subtype = &MEDIASUBTYPE_AYUV},
5086 {.subtype = &MEDIASUBTYPE_NV12},
5087 {.subtype = &MEDIASUBTYPE_RGB32},
5088 {.subtype = &MEDIASUBTYPE_RGB565},
5089 {.subtype = &MEDIASUBTYPE_I420},
5090 {.subtype = &MEDIASUBTYPE_IYUV},
5091 {.subtype = &MEDIASUBTYPE_YVYU},
5092 {.subtype = &MEDIASUBTYPE_RGB24},
5093 {.subtype = &MEDIASUBTYPE_RGB555},
5094 {.subtype = &MEDIASUBTYPE_RGB8},
5095 {.subtype = &MEDIASUBTYPE_V216},
5096 {.subtype = &MEDIASUBTYPE_V410},
5097 {.subtype = &MEDIASUBTYPE_NV11},
5101 static const media_type_desc expect_available_inputs[20] =
5103 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12), },
5104 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), },
5105 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY), },
5106 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_AYUV), },
5107 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), },
5108 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), },
5109 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565), },
5110 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420), },
5111 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV), },
5112 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU), },
5113 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24), },
5114 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555), },
5115 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_RGB8), },
5116 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V216), },
5117 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V410), },
5118 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11), },
5119 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y41P), },
5120 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y41T), },
5121 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y42T), },
5122 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVU9), },
5124 static const media_type_desc expect_available_outputs[16] =
5126 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12), },
5127 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), },
5128 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY), },
5129 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_AYUV), },
5130 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), },
5131 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), },
5132 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565), },
5133 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420), },
5134 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV), },
5135 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU), },
5136 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24), },
5137 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555), },
5138 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_RGB8), },
5139 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V216), },
5140 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V410), },
5141 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11), },
5143 static const media_type_desc expect_available_common =
5145 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5146 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
5147 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
5150 static const MFVideoArea actual_aperture = {.Area={82,84}};
5151 static const DWORD actual_width = 96, actual_height = 96;
5152 const struct attribute_desc input_type_desc[] =
5154 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
5155 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE),
5156 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
5157 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
5158 {0},
5160 const struct attribute_desc output_type_desc[] =
5162 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
5163 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32, .required = TRUE),
5164 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
5165 {0},
5167 const struct attribute_desc expect_input_type_desc[] =
5169 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5170 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
5171 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
5172 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
5173 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
5174 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
5175 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
5176 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
5177 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
5178 {0},
5180 const struct attribute_desc expect_output_type_desc[] =
5182 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5183 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
5184 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
5185 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 4),
5186 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 4),
5187 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
5188 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
5189 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
5190 {0},
5192 const MFT_OUTPUT_STREAM_INFO output_info =
5194 .cbSize = actual_width * actual_height * 4,
5195 .cbAlignment = 1,
5197 const MFT_INPUT_STREAM_INFO input_info =
5199 .cbSize = actual_width * actual_height * 3 / 2,
5200 .cbAlignment = 1,
5203 const struct buffer_desc output_buffer_desc =
5205 .length = actual_width * actual_height * 4,
5206 .compare = compare_rgb32, .dump = dump_rgb32, .rect = {.right = 82, .bottom = 84},
5208 const struct attribute_desc output_sample_attributes[] =
5210 ATTR_UINT32(MFSampleExtension_CleanPoint, 0, .todo = TRUE),
5211 {0},
5213 const struct sample_desc output_sample_desc =
5215 .attributes = output_sample_attributes,
5216 .sample_time = 0, .sample_duration = 10000000,
5217 .buffer_count = 1, .buffers = &output_buffer_desc,
5220 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
5221 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_I420};
5222 IMFSample *input_sample, *output_sample;
5223 IMFCollection *output_samples;
5224 DWORD length, output_status;
5225 const BYTE *nv12frame_data;
5226 ULONG nv12frame_data_len;
5227 IMFMediaType *media_type;
5228 IMFTransform *transform;
5229 ULONG i, ret, ref;
5230 HRESULT hr;
5232 hr = CoInitialize(NULL);
5233 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
5235 winetest_push_context("colorconv");
5237 if (!check_mft_enum(MFT_CATEGORY_VIDEO_EFFECT, &input_type, &output_type, class_id))
5238 goto failed;
5239 check_mft_get_info(class_id, &expect_mft_info);
5240 check_dmo_get_info(class_id, &expect_dmo_info);
5242 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
5243 &IID_IMFTransform, (void **)&transform)))
5244 goto failed;
5246 check_interface(transform, &IID_IMFTransform, TRUE);
5247 check_interface(transform, &IID_IMediaObject, TRUE);
5248 check_interface(transform, &IID_IPropertyStore, TRUE);
5249 todo_wine
5250 check_interface(transform, &IID_IPropertyBag, FALSE);
5251 todo_wine
5252 check_interface(transform, &IID_IMFRealTimeClient, TRUE);
5253 /* check_interface(transform, &IID_IWMColorConvProps, TRUE); */
5255 check_mft_optional_methods(transform, 1);
5256 check_mft_get_attributes(transform, NULL, FALSE);
5257 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
5258 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
5260 i = -1;
5261 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
5263 winetest_push_context("out %lu", i);
5264 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
5265 check_media_type(media_type, expect_available_common, -1);
5266 check_media_type(media_type, expect_available_outputs[i], -1);
5267 ret = IMFMediaType_Release(media_type);
5268 ok(ret == 0, "Release returned %lu\n", ret);
5269 winetest_pop_context();
5271 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
5272 ok(i == 16, "%lu output media types\n", i);
5274 i = -1;
5275 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
5277 winetest_push_context("in %lu", i);
5278 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
5279 check_media_type(media_type, expect_available_common, -1);
5280 check_media_type(media_type, expect_available_inputs[i], -1);
5281 ret = IMFMediaType_Release(media_type);
5282 ok(ret == 0, "Release returned %lu\n", ret);
5283 winetest_pop_context();
5285 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
5286 ok(i == 20, "%lu input media types\n", i);
5288 check_mft_set_output_type_required(transform, output_type_desc);
5289 check_mft_set_output_type(transform, output_type_desc, S_OK);
5290 check_mft_get_output_current_type_(transform, expect_output_type_desc, FALSE, TRUE);
5292 check_mft_set_input_type_required(transform, input_type_desc);
5293 check_mft_set_input_type(transform, input_type_desc);
5294 check_mft_get_input_current_type_(transform, expect_input_type_desc, FALSE, TRUE);
5296 check_mft_get_input_stream_info(transform, S_OK, &input_info);
5297 check_mft_get_output_stream_info(transform, S_OK, &output_info);
5299 load_resource(L"nv12frame.bmp", &nv12frame_data, &nv12frame_data_len);
5300 /* skip BMP header and RGB data from the dump */
5301 length = *(DWORD *)(nv12frame_data + 2);
5302 nv12frame_data_len = nv12frame_data_len - length;
5303 nv12frame_data = nv12frame_data + length;
5304 ok(nv12frame_data_len == 13824, "got length %lu\n", nv12frame_data_len);
5306 input_sample = create_sample(nv12frame_data, nv12frame_data_len);
5307 hr = IMFSample_SetSampleTime(input_sample, 0);
5308 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
5309 hr = IMFSample_SetSampleDuration(input_sample, 10000000);
5310 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
5311 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
5312 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
5313 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
5314 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
5315 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
5316 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
5317 ret = IMFSample_Release(input_sample);
5318 ok(ret <= 1, "Release returned %ld\n", ret);
5320 hr = MFCreateCollection(&output_samples);
5321 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
5323 output_sample = create_sample(NULL, output_info.cbSize);
5324 hr = check_mft_process_output(transform, output_sample, &output_status);
5325 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
5326 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
5327 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
5328 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
5329 ref = IMFSample_Release(output_sample);
5330 ok(ref == 1, "Release returned %ld\n", ref);
5332 ret = check_mf_sample_collection(output_samples, &output_sample_desc, L"rgb32frame.bmp");
5333 ok(ret <= 4 /* small and harmless diff in Wine vs Windows */, "got %lu%% diff\n", ret);
5334 IMFCollection_Release(output_samples);
5336 output_sample = create_sample(NULL, output_info.cbSize);
5337 hr = check_mft_process_output(transform, output_sample, &output_status);
5338 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
5339 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
5340 hr = IMFSample_GetTotalLength(output_sample, &length);
5341 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
5342 ok(length == 0, "got length %lu\n", length);
5343 ret = IMFSample_Release(output_sample);
5344 ok(ret == 0, "Release returned %lu\n", ret);
5346 ret = IMFTransform_Release(transform);
5347 ok(ret == 0, "Release returned %ld\n", ret);
5349 failed:
5350 winetest_pop_context();
5351 CoUninitialize();
5354 static void test_video_processor(void)
5356 const GUID *const class_id = &CLSID_VideoProcessorMFT;
5357 const struct transform_info expect_mft_info =
5359 .name = L"Microsoft Video Processor MFT",
5360 .major_type = &MFMediaType_Video,
5361 .inputs =
5363 {.subtype = &MFVideoFormat_IYUV},
5364 {.subtype = &MFVideoFormat_YV12},
5365 {.subtype = &MFVideoFormat_NV12},
5366 {.subtype = &MFVideoFormat_YUY2},
5367 {.subtype = &MFVideoFormat_ARGB32},
5368 {.subtype = &MFVideoFormat_RGB32},
5369 {.subtype = &MFVideoFormat_NV11},
5370 {.subtype = &MFVideoFormat_AYUV},
5371 {.subtype = &MFVideoFormat_UYVY},
5372 {.subtype = &MEDIASUBTYPE_P208},
5373 {.subtype = &MFVideoFormat_RGB24},
5374 {.subtype = &MFVideoFormat_RGB555},
5375 {.subtype = &MFVideoFormat_RGB565},
5376 {.subtype = &MFVideoFormat_RGB8},
5377 {.subtype = &MFVideoFormat_I420},
5378 {.subtype = &MFVideoFormat_Y216},
5379 {.subtype = &MFVideoFormat_v410},
5380 {.subtype = &MFVideoFormat_Y41P},
5381 {.subtype = &MFVideoFormat_Y41T},
5382 {.subtype = &MFVideoFormat_Y42T},
5383 {.subtype = &MFVideoFormat_YVYU},
5384 {.subtype = &MFVideoFormat_420O},
5386 .outputs =
5388 {.subtype = &MFVideoFormat_IYUV},
5389 {.subtype = &MFVideoFormat_YV12},
5390 {.subtype = &MFVideoFormat_NV12},
5391 {.subtype = &MFVideoFormat_YUY2},
5392 {.subtype = &MFVideoFormat_ARGB32},
5393 {.subtype = &MFVideoFormat_RGB32},
5394 {.subtype = &MFVideoFormat_NV11},
5395 {.subtype = &MFVideoFormat_AYUV},
5396 {.subtype = &MFVideoFormat_UYVY},
5397 {.subtype = &MEDIASUBTYPE_P208},
5398 {.subtype = &MFVideoFormat_RGB24},
5399 {.subtype = &MFVideoFormat_RGB555},
5400 {.subtype = &MFVideoFormat_RGB565},
5401 {.subtype = &MFVideoFormat_RGB8},
5402 {.subtype = &MFVideoFormat_I420},
5403 {.subtype = &MFVideoFormat_Y216},
5404 {.subtype = &MFVideoFormat_v410},
5405 {.subtype = &MFVideoFormat_Y41P},
5406 {.subtype = &MFVideoFormat_Y41T},
5407 {.subtype = &MFVideoFormat_Y42T},
5408 {.subtype = &MFVideoFormat_YVYU},
5411 const GUID expect_available_inputs_w8[] =
5413 MFVideoFormat_IYUV,
5414 MFVideoFormat_YV12,
5415 MFVideoFormat_NV12,
5416 MFVideoFormat_420O,
5417 MFVideoFormat_UYVY,
5418 MFVideoFormat_YUY2,
5419 MFVideoFormat_P208,
5420 MFVideoFormat_NV11,
5421 MFVideoFormat_AYUV,
5422 MFVideoFormat_ARGB32,
5423 MFVideoFormat_RGB32,
5424 MFVideoFormat_RGB24,
5425 MFVideoFormat_I420,
5426 MFVideoFormat_YVYU,
5427 MFVideoFormat_RGB555,
5428 MFVideoFormat_RGB565,
5429 MFVideoFormat_RGB8,
5430 MFVideoFormat_Y216,
5431 MFVideoFormat_v410,
5432 MFVideoFormat_Y41P,
5433 MFVideoFormat_Y41T,
5434 MFVideoFormat_Y42T,
5436 const GUID expect_available_inputs_w10[] =
5438 MFVideoFormat_L8,
5439 MFVideoFormat_L16,
5440 MFAudioFormat_MPEG,
5441 MFVideoFormat_IYUV,
5442 MFVideoFormat_YV12,
5443 MFVideoFormat_NV12,
5444 MFVideoFormat_420O,
5445 MFVideoFormat_P010,
5446 MFVideoFormat_P016,
5447 MFVideoFormat_UYVY,
5448 MFVideoFormat_YUY2,
5449 MFVideoFormat_P208,
5450 MFVideoFormat_NV11,
5451 MFVideoFormat_AYUV,
5452 MFVideoFormat_ARGB32,
5453 MFVideoFormat_ABGR32,
5454 MFVideoFormat_RGB32,
5455 MFVideoFormat_A2R10G10B10,
5456 MFVideoFormat_A16B16G16R16F,
5457 MFVideoFormat_RGB24,
5458 MFVideoFormat_I420,
5459 MFVideoFormat_YVYU,
5460 MFVideoFormat_RGB555,
5461 MFVideoFormat_RGB565,
5462 MFVideoFormat_RGB8,
5463 MFVideoFormat_Y216,
5464 MFVideoFormat_v410,
5465 MFVideoFormat_Y41P,
5466 MFVideoFormat_Y41T,
5467 MFVideoFormat_Y42T,
5469 const GUID expect_available_outputs[] =
5471 MFVideoFormat_A2R10G10B10, /* enumerated with MFVideoFormat_P010 input */
5472 MFVideoFormat_P010, /* enumerated with MFVideoFormat_A2R10G10B10 input */
5473 MFVideoFormat_YUY2,
5474 MFVideoFormat_IYUV,
5475 MFVideoFormat_I420,
5476 MFVideoFormat_NV12,
5477 MFVideoFormat_RGB24,
5478 MFVideoFormat_ARGB32,
5479 MFVideoFormat_RGB32,
5480 MFVideoFormat_YV12,
5481 MFVideoFormat_Y216, /* enumerated with some input formats */
5482 MFVideoFormat_UYVY, /* enumerated with some input formats */
5483 MFVideoFormat_YVYU, /* enumerated with some input formats */
5484 MFVideoFormat_AYUV,
5485 MFVideoFormat_RGB555,
5486 MFVideoFormat_RGB565,
5487 MFVideoFormat_AYUV, /* some inputs enumerate MFVideoFormat_AYUV after RGB565 */
5488 MFVideoFormat_NV12, /* P010 enumerates NV12 after (A)RGB32 formats */
5489 MFVideoFormat_A16B16G16R16F, /* enumerated with MFVideoFormat_P010 input */
5491 static const media_type_desc expect_available_common =
5493 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5495 static const struct attribute_desc expect_transform_attributes[] =
5497 ATTR_UINT32(MFT_SUPPORT_3DVIDEO, 1, .todo = TRUE),
5498 /* ATTR_UINT32(MF_SA_D3D_AWARE, 1), only on W7 */
5499 {0},
5502 static const MFVideoArea actual_aperture = {.Area={82,84}};
5503 static const DWORD actual_width = 96, actual_height = 96;
5504 const struct attribute_desc input_type_desc[] =
5506 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
5507 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE),
5508 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
5509 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
5510 {0},
5512 const struct attribute_desc output_type_desc[] =
5514 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
5515 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32, .required = TRUE),
5516 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
5517 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
5518 {0},
5520 const MFT_OUTPUT_STREAM_INFO initial_output_info = {0};
5521 const MFT_INPUT_STREAM_INFO initial_input_info = {0};
5522 MFT_OUTPUT_STREAM_INFO output_info = {0};
5523 MFT_INPUT_STREAM_INFO input_info = {0};
5525 const struct buffer_desc output_buffer_desc =
5527 .length = actual_width * actual_height * 4,
5528 .compare = compare_rgb32, .dump = dump_rgb32, .rect = {.top = 12, .right = 82, .bottom = 96},
5530 const struct attribute_desc output_sample_attributes[] =
5532 ATTR_UINT32(MFSampleExtension_CleanPoint, 1, .todo = TRUE),
5533 {0},
5535 const struct sample_desc output_sample_desc =
5537 .attributes = output_sample_attributes,
5538 .sample_time = 0, .sample_duration = 10000000,
5539 .buffer_count = 1, .buffers = &output_buffer_desc,
5542 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
5543 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_I420};
5544 DWORD i, j, k, flags, length, output_status;
5545 IMFSample *input_sample, *output_sample;
5546 IMFMediaType *media_type, *media_type2;
5547 const GUID *expect_available_inputs;
5548 IMFCollection *output_samples;
5549 const BYTE *nv12frame_data;
5550 ULONG nv12frame_data_len;
5551 IMFTransform *transform;
5552 IMFMediaBuffer *buffer;
5553 UINT32 count;
5554 HRESULT hr;
5555 ULONG ret;
5556 GUID guid;
5557 LONG ref;
5559 hr = CoInitialize(NULL);
5560 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
5562 winetest_push_context("videoproc");
5564 if (!check_mft_enum(MFT_CATEGORY_VIDEO_PROCESSOR, &input_type, &output_type, class_id))
5565 goto failed;
5566 check_mft_get_info(class_id, &expect_mft_info);
5568 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
5569 &IID_IMFTransform, (void **)&transform)))
5570 goto failed;
5572 todo_wine
5573 check_interface(transform, &IID_IMFVideoProcessorControl, TRUE);
5574 todo_wine
5575 check_interface(transform, &IID_IMFRealTimeClientEx, TRUE);
5576 check_interface(transform, &IID_IMFMediaEventGenerator, FALSE);
5577 check_interface(transform, &IID_IMFShutdown, FALSE);
5579 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
5580 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5582 hr = IMFTransform_GetOutputStatus(transform, &flags);
5583 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5585 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
5586 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5588 check_mft_get_input_current_type(transform, NULL);
5589 check_mft_get_output_current_type(transform, NULL);
5591 check_mft_get_input_stream_info(transform, S_OK, &initial_input_info);
5592 check_mft_get_output_stream_info(transform, S_OK, &initial_output_info);
5594 /* Configure stream types. */
5595 for (i = 0;;++i)
5597 if (FAILED(hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type)))
5599 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5600 break;
5603 hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type2);
5604 ok(hr == S_OK, "Failed to get available type, hr %#lx.\n", hr);
5605 ok(media_type != media_type2, "Unexpected instance.\n");
5606 ref = IMFMediaType_Release(media_type2);
5607 ok(ref == 0, "Release returned %ld\n", ref);
5609 hr = IMFMediaType_GetMajorType(media_type, &guid);
5610 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
5611 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type.\n");
5613 hr = IMFMediaType_GetCount(media_type, &count);
5614 ok(hr == S_OK, "Failed to get attributes count, hr %#lx.\n", hr);
5615 ok(count == 2, "Unexpected count %u.\n", count);
5617 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
5618 ok(hr == S_OK, "Failed to get subtype, hr %#lx.\n", hr);
5619 ok(is_supported_video_type(&guid), "Unexpected media type %s.\n", wine_dbgstr_guid(&guid));
5621 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
5622 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
5624 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
5625 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
5627 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type2);
5628 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5630 /* FIXME: figure out if those require additional attributes or simply advertised but not supported */
5631 if (IsEqualGUID(&guid, &MFVideoFormat_L8) || IsEqualGUID(&guid, &MFVideoFormat_L16)
5632 || IsEqualGUID(&guid, &MFVideoFormat_D16) || IsEqualGUID(&guid, &MFVideoFormat_420O)
5633 || IsEqualGUID(&guid, &MFVideoFormat_A16B16G16R16F))
5635 ref = IMFMediaType_Release(media_type);
5636 ok(ref == 0, "Release returned %ld\n", ref);
5637 continue;
5640 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
5641 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5643 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
5644 ok(hr == S_OK, "Failed to test input type %s, hr %#lx.\n", wine_dbgstr_guid(&guid), hr);
5646 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
5647 ok(hr == S_OK, "Failed to test input type, hr %#lx.\n", hr);
5649 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type2);
5650 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
5651 ok(media_type != media_type2, "Unexpected instance.\n");
5652 IMFMediaType_Release(media_type2);
5654 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
5655 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
5656 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected input status %#lx.\n", flags);
5658 input_info.cbSize = 0;
5659 if (!IsEqualGUID(&guid, &MFVideoFormat_P208) && !IsEqualGUID(&guid, &MEDIASUBTYPE_Y41T)
5660 && !IsEqualGUID(&guid, &MEDIASUBTYPE_Y42T))
5662 hr = MFCalculateImageSize(&guid, 16, 16, (UINT32 *)&input_info.cbSize);
5663 todo_wine_if(IsEqualGUID(&guid, &MFVideoFormat_NV11) || IsEqualGUID(&guid, &MFVideoFormat_YVYU)
5664 || IsEqualGUID(&guid, &MFVideoFormat_Y216) || IsEqualGUID(&guid, &MFVideoFormat_v410)
5665 || IsEqualGUID(&guid, &MFVideoFormat_Y41P))
5666 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5668 check_mft_get_input_stream_info(transform, S_OK, &input_info);
5669 check_mft_get_output_stream_info(transform, S_OK, &initial_output_info);
5671 IMFMediaType_Release(media_type);
5674 /* IYUV -> RGB32 */
5675 hr = MFCreateMediaType(&media_type);
5676 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5678 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5679 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5681 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_IYUV);
5682 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5684 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
5685 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5687 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
5688 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5690 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
5691 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5693 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
5694 ok(hr == S_OK, "Failed to set output type, hr %#lx.\n", hr);
5696 hr = MFCalculateImageSize(&MFVideoFormat_IYUV, 16, 16, (UINT32 *)&input_info.cbSize);
5697 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5698 hr = MFCalculateImageSize(&MFVideoFormat_RGB32, 16, 16, (UINT32 *)&output_info.cbSize);
5699 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5700 check_mft_get_input_stream_info(transform, S_OK, &input_info);
5701 check_mft_get_output_stream_info(transform, S_OK, &output_info);
5703 hr = MFCreateSample(&input_sample);
5704 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5706 hr = MFCreateSample(&output_sample);
5707 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5709 hr = check_mft_process_output(transform, output_sample, &output_status);
5710 todo_wine
5711 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#lx.\n", hr);
5713 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
5714 todo_wine
5715 ok(hr == S_OK, "Failed to push a sample, hr %#lx.\n", hr);
5717 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
5718 todo_wine
5719 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#lx.\n", hr);
5721 hr = check_mft_process_output(transform, output_sample, &output_status);
5722 todo_wine
5723 ok(hr == MF_E_NO_SAMPLE_TIMESTAMP, "Unexpected hr %#lx.\n", hr);
5725 hr = IMFSample_SetSampleTime(input_sample, 0);
5726 ok(hr == S_OK, "Failed to set sample time, hr %#lx.\n", hr);
5727 hr = check_mft_process_output(transform, output_sample, &output_status);
5728 todo_wine
5729 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5731 hr = MFCreateMemoryBuffer(1024 * 1024, &buffer);
5732 ok(hr == S_OK, "Failed to create a buffer, hr %#lx.\n", hr);
5734 hr = IMFSample_AddBuffer(input_sample, buffer);
5735 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
5737 hr = IMFSample_AddBuffer(output_sample, buffer);
5738 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
5740 hr = check_mft_process_output(transform, output_sample, &output_status);
5741 todo_wine
5742 ok(hr == S_OK || broken(FAILED(hr)) /* Win8 */, "Failed to get output buffer, hr %#lx.\n", hr);
5744 if (SUCCEEDED(hr))
5746 hr = check_mft_process_output(transform, output_sample, &output_status);
5747 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#lx.\n", hr);
5750 ref = IMFTransform_Release(transform);
5751 ok(ref == 0, "Release returned %ld\n", ref);
5753 ref = IMFMediaType_Release(media_type);
5754 ok(ref == 0, "Release returned %ld\n", ref);
5755 ref = IMFSample_Release(input_sample);
5756 ok(ref == 0, "Release returned %ld\n", ref);
5757 ref = IMFSample_Release(output_sample);
5758 ok(ref == 0, "Release returned %ld\n", ref);
5759 ref = IMFMediaBuffer_Release(buffer);
5760 ok(ref == 0, "Release returned %ld\n", ref);
5763 hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)&transform);
5764 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5766 check_interface(transform, &IID_IMFTransform, TRUE);
5767 check_interface(transform, &IID_IMediaObject, FALSE);
5768 check_interface(transform, &IID_IPropertyStore, FALSE);
5769 check_interface(transform, &IID_IPropertyBag, FALSE);
5771 check_mft_optional_methods(transform, 1);
5772 check_mft_get_attributes(transform, expect_transform_attributes, TRUE);
5773 check_mft_get_input_stream_info(transform, S_OK, &initial_input_info);
5774 check_mft_get_output_stream_info(transform, S_OK, &initial_output_info);
5776 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
5777 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
5779 hr = IMFTransform_GetInputAvailableType(transform, 0, 23, &media_type);
5780 ok(hr == S_OK || hr == MF_E_NO_MORE_TYPES /* w8 */, "GetOutputAvailableType returned %#lx\n", hr);
5781 if (hr == MF_E_NO_MORE_TYPES)
5782 expect_available_inputs = expect_available_inputs_w8;
5783 else
5785 hr = IMFTransform_GetInputAvailableType(transform, 0, 27, &media_type);
5786 ok(hr == S_OK || broken(hr == MF_E_NO_MORE_TYPES) /* w1064v1507 */, "GetOutputAvailableType returned %#lx\n", hr);
5787 if (hr == MF_E_NO_MORE_TYPES)
5788 expect_available_inputs = expect_available_inputs_w10 + 3;
5789 else
5790 expect_available_inputs = expect_available_inputs_w10;
5793 i = -1;
5794 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
5796 /* FIXME: Skip exotic input types which aren't directly accepted */
5797 if (IsEqualGUID(&expect_available_inputs[i], &MFVideoFormat_L8)
5798 || IsEqualGUID(&expect_available_inputs[i], &MFVideoFormat_L16)
5799 || IsEqualGUID(&expect_available_inputs[i], &MFAudioFormat_MPEG)
5800 || IsEqualGUID(&expect_available_inputs[i], &MFVideoFormat_420O)
5801 || IsEqualGUID(&expect_available_inputs[i], &MFVideoFormat_A16B16G16R16F) /* w1064v1507 */)
5802 continue;
5804 winetest_push_context("in %lu", i);
5805 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
5806 check_media_type(media_type, expect_available_common, -1);
5808 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
5809 ok(hr == S_OK, "GetGUID returned %#lx\n", hr);
5811 /* w1064v1507 doesn't expose MFVideoFormat_ABGR32 input */
5812 if (broken(IsEqualGUID(&expect_available_inputs[i], &MFVideoFormat_ABGR32)
5813 && IsEqualGUID(&guid, &MFVideoFormat_RGB32)))
5814 expect_available_inputs++;
5816 ok(IsEqualGUID(&expect_available_inputs[i], &guid), "got subtype %s\n", debugstr_guid(&guid));
5818 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
5819 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
5821 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)actual_width << 32 | actual_height);
5822 ok(hr == S_OK, "SetUINT64 returned %#lx.\n", hr);
5823 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
5824 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
5826 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type2);
5827 ok(hr == S_OK, "GetOutputAvailableType returned %#lx.\n", hr);
5828 hr = IMFMediaType_IsEqual(media_type, media_type2, &flags);
5829 ok(hr == S_OK, "IsEqual returned %#lx.\n", hr);
5830 IMFMediaType_Release(media_type2);
5832 ret = IMFMediaType_Release(media_type);
5833 ok(ret == 1, "Release returned %lu\n", ret);
5835 j = k = 0;
5836 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++j, &media_type)))
5838 winetest_push_context("out %lu", j);
5839 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
5840 check_media_type(media_type, expect_available_common, -1);
5842 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
5843 ok(hr == S_OK, "GetGUID returned %#lx\n", hr);
5845 for (; k < ARRAY_SIZE(expect_available_outputs); k++)
5846 if (IsEqualGUID(&expect_available_outputs[k], &guid))
5847 break;
5848 ok(k < ARRAY_SIZE(expect_available_outputs), "got subtype %s\n", debugstr_guid(&guid));
5850 ret = IMFMediaType_Release(media_type);
5851 ok(ret == 0, "Release returned %lu\n", ret);
5852 winetest_pop_context();
5854 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
5856 winetest_pop_context();
5858 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
5859 ok(i == 22 || i == 30 || broken(i == 26) /* w1064v1507 */, "%lu input media types\n", i);
5861 check_mft_set_input_type_required(transform, input_type_desc);
5862 check_mft_set_input_type(transform, input_type_desc);
5863 check_mft_get_input_current_type(transform, input_type_desc);
5865 check_mft_set_output_type_required(transform, output_type_desc);
5866 check_mft_set_output_type(transform, output_type_desc, S_OK);
5867 check_mft_get_output_current_type(transform, output_type_desc);
5869 input_info.cbSize = actual_width * actual_height * 3 / 2;
5870 output_info.cbSize = actual_width * actual_height * 4;
5871 check_mft_get_input_stream_info(transform, S_OK, &input_info);
5872 check_mft_get_output_stream_info(transform, S_OK, &output_info);
5874 load_resource(L"nv12frame.bmp", &nv12frame_data, &nv12frame_data_len);
5875 /* skip BMP header and RGB data from the dump */
5876 length = *(DWORD *)(nv12frame_data + 2);
5877 nv12frame_data_len = nv12frame_data_len - length;
5878 nv12frame_data = nv12frame_data + length;
5879 ok(nv12frame_data_len == 13824, "got length %lu\n", nv12frame_data_len);
5881 input_sample = create_sample(nv12frame_data, nv12frame_data_len);
5882 hr = IMFSample_SetSampleTime(input_sample, 0);
5883 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
5884 hr = IMFSample_SetSampleDuration(input_sample, 10000000);
5885 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
5886 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
5887 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
5888 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
5889 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
5890 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
5891 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
5892 ret = IMFSample_Release(input_sample);
5893 ok(ret <= 1, "Release returned %ld\n", ret);
5895 hr = MFCreateCollection(&output_samples);
5896 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
5898 output_sample = create_sample(NULL, output_info.cbSize);
5899 hr = check_mft_process_output(transform, output_sample, &output_status);
5900 ok(hr == S_OK || broken(hr == MF_E_SHUTDOWN) /* w8 */, "ProcessOutput returned %#lx\n", hr);
5901 if (hr != S_OK)
5903 win_skip("ProcessOutput returned MF_E_SHUTDOWN, skipping tests.\n");
5904 goto skip_output;
5906 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
5908 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
5909 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
5910 ref = IMFSample_Release(output_sample);
5911 ok(ref == 1, "Release returned %ld\n", ref);
5913 ret = check_mf_sample_collection(output_samples, &output_sample_desc, L"rgb32frame-vp.bmp");
5914 todo_wine
5915 ok(ret == 0 || broken(ret == 25) /* w1064v1507 / w1064v1809 incorrectly rescale */, "got %lu%% diff\n", ret);
5916 IMFCollection_Release(output_samples);
5918 output_sample = create_sample(NULL, output_info.cbSize);
5919 hr = check_mft_process_output(transform, output_sample, &output_status);
5920 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
5921 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
5922 hr = IMFSample_GetTotalLength(output_sample, &length);
5923 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
5924 ok(length == 0, "got length %lu\n", length);
5926 skip_output:
5927 ret = IMFSample_Release(output_sample);
5928 ok(ret == 0, "Release returned %lu\n", ret);
5930 ret = IMFTransform_Release(transform);
5931 ok(ret == 0, "Release returned %ld\n", ret);
5933 failed:
5934 winetest_pop_context();
5935 CoUninitialize();
5938 static void test_mp3_decoder(void)
5940 const GUID *const class_id = &CLSID_CMP3DecMediaObject;
5941 const struct transform_info expect_mft_info =
5943 .name = L"MP3 Decoder MFT",
5944 .major_type = &MFMediaType_Audio,
5945 .inputs =
5947 {.subtype = &MFAudioFormat_MP3},
5949 .outputs =
5951 {.subtype = &MFAudioFormat_PCM},
5954 const struct transform_info expect_dmo_info =
5956 .name = L"MP3 Decoder DMO",
5957 .major_type = &MEDIATYPE_Audio,
5958 .inputs =
5960 {.subtype = &MFAudioFormat_MP3},
5962 .outputs =
5964 {.subtype = &MEDIASUBTYPE_PCM},
5968 static const ULONG mp3dec_block_size = 0x1200;
5969 static const media_type_desc expect_available_inputs[] =
5972 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5973 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3),
5974 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
5977 static const media_type_desc expect_available_outputs[] =
5980 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5981 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
5982 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
5983 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
5984 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
5985 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
5986 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
5987 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
5990 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5991 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
5992 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
5993 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
5994 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
5995 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
5996 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
5997 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6000 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6001 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
6002 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
6003 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6004 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6005 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
6006 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2),
6007 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6010 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6011 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
6012 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
6013 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
6014 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6015 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
6016 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
6017 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6020 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6021 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
6022 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
6023 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
6024 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6025 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
6026 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2),
6027 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6030 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6031 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
6032 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
6033 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
6034 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6035 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 22050),
6036 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
6037 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6041 const struct attribute_desc input_type_desc[] =
6043 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
6044 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3, .required = TRUE),
6045 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
6046 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6047 {0},
6049 static const struct attribute_desc output_type_desc[] =
6051 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
6052 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM, .required = TRUE),
6053 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
6054 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
6055 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
6056 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2 * (16 / 8), .required = TRUE),
6057 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * (16 / 8) * 22050, .required = TRUE),
6058 {0},
6060 const struct attribute_desc expect_input_type_desc[] =
6062 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6063 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3),
6064 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6065 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6066 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
6067 {0},
6069 static const struct attribute_desc expect_output_type_desc[] =
6071 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6072 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
6073 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
6074 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6075 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6076 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
6077 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 22050 * 4),
6078 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6079 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
6080 {0},
6082 const MFT_OUTPUT_STREAM_INFO output_info =
6084 .cbSize = mp3dec_block_size,
6085 .cbAlignment = 1,
6087 const MFT_INPUT_STREAM_INFO input_info =
6089 .cbAlignment = 1,
6092 const struct buffer_desc output_buffer_desc[] =
6094 {.length = 0x9c0, .compare = compare_pcm16},
6095 {.length = mp3dec_block_size, .compare = compare_pcm16},
6097 const struct attribute_desc output_sample_attributes[] =
6099 ATTR_UINT32(mft_output_sample_incomplete, 1),
6100 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
6101 {0},
6103 const struct sample_desc output_sample_desc[] =
6106 .attributes = output_sample_attributes + 0,
6107 .sample_time = 0, .sample_duration = 282993,
6108 .buffer_count = 1, .buffers = output_buffer_desc + 0,
6111 .attributes = output_sample_attributes + 0,
6112 .sample_time = 282993, .sample_duration = 522449,
6113 .buffer_count = 1, .buffers = output_buffer_desc + 1, .repeat_count = 18,
6116 .attributes = output_sample_attributes + 1, /* not MFT_OUTPUT_DATA_BUFFER_INCOMPLETE */
6117 .sample_time = 10209524, .sample_duration = 522449,
6118 .buffer_count = 1, .buffers = output_buffer_desc + 1,
6122 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_PCM};
6123 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_MP3};
6124 IMFSample *input_sample, *output_sample;
6125 IMFCollection *output_samples;
6126 DWORD length, output_status;
6127 IMFMediaType *media_type;
6128 IMFTransform *transform;
6129 const BYTE *mp3enc_data;
6130 ULONG mp3enc_data_len;
6131 ULONG i, ret, ref;
6132 HRESULT hr;
6134 hr = CoInitialize(NULL);
6135 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
6137 winetest_push_context("mp3dec");
6139 if (!check_mft_enum(MFT_CATEGORY_AUDIO_DECODER, &input_type, &output_type, class_id))
6140 goto failed;
6141 check_mft_get_info(class_id, &expect_mft_info);
6142 check_dmo_get_info(class_id, &expect_dmo_info);
6144 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
6145 &IID_IMFTransform, (void **)&transform)))
6146 goto failed;
6148 check_interface(transform, &IID_IMFTransform, TRUE);
6149 check_interface(transform, &IID_IMediaObject, TRUE);
6150 todo_wine
6151 check_interface(transform, &IID_IPropertyStore, TRUE);
6152 check_interface(transform, &IID_IPropertyBag, FALSE);
6154 check_mft_optional_methods(transform, 1);
6155 check_mft_get_attributes(transform, NULL, FALSE);
6156 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
6157 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
6159 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
6160 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
6162 i = -1;
6163 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
6165 winetest_push_context("in %lu", i);
6166 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
6167 check_media_type(media_type, expect_available_inputs[i], -1);
6168 ret = IMFMediaType_Release(media_type);
6169 ok(ret == 0, "Release returned %lu\n", ret);
6170 winetest_pop_context();
6172 todo_wine
6173 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
6174 todo_wine
6175 ok(i == ARRAY_SIZE(expect_available_inputs), "%lu input media types\n", i);
6177 /* setting output media type first doesn't work */
6178 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
6179 check_mft_get_output_current_type(transform, NULL);
6181 check_mft_set_input_type_required(transform, input_type_desc);
6182 check_mft_set_input_type(transform, input_type_desc);
6183 check_mft_get_input_current_type(transform, expect_input_type_desc);
6185 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
6186 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
6188 /* check new output media types */
6190 i = -1;
6191 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
6193 winetest_push_context("out %lu", i);
6194 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
6195 check_media_type(media_type, expect_available_outputs[i], -1);
6196 ret = IMFMediaType_Release(media_type);
6197 ok(ret == 0, "Release returned %lu\n", ret);
6198 winetest_pop_context();
6200 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
6201 ok(i == ARRAY_SIZE(expect_available_outputs), "%lu output media types\n", i);
6203 check_mft_set_output_type_required(transform, output_type_desc);
6204 check_mft_set_output_type(transform, output_type_desc, S_OK);
6205 check_mft_get_output_current_type(transform, expect_output_type_desc);
6207 check_mft_get_input_stream_info(transform, S_OK, &input_info);
6208 check_mft_get_output_stream_info(transform, S_OK, &output_info);
6210 load_resource(L"mp3encdata.bin", &mp3enc_data, &mp3enc_data_len);
6211 ok(mp3enc_data_len == 6295, "got length %lu\n", mp3enc_data_len);
6213 input_sample = create_sample(mp3enc_data, mp3enc_data_len);
6214 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
6215 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6216 ret = IMFSample_Release(input_sample);
6217 ok(ret == 1, "Release returned %lu\n", ret);
6219 input_sample = create_sample(mp3enc_data, mp3enc_data_len);
6220 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
6221 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
6222 ret = IMFSample_Release(input_sample);
6223 ok(ret == 0, "Release returned %lu\n", ret);
6225 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
6226 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
6228 hr = MFCreateCollection(&output_samples);
6229 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
6231 /* first sample is broken */
6232 output_sample = create_sample(NULL, output_info.cbSize);
6233 hr = check_mft_process_output(transform, output_sample, &output_status);
6234 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
6235 ok(output_status == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE, "got output[0].dwStatus %#lx\n", output_status);
6236 hr = IMFSample_GetTotalLength(output_sample, &length);
6237 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
6238 ok(length == mp3dec_block_size /* Win8 */ || length == 0x9c0 /* Win10 */ || length == 0x900 /* Win7 */,
6239 "got length %lu\n", length);
6240 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
6241 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
6242 ref = IMFSample_Release(output_sample);
6243 ok(ref == 1, "Release returned %ld\n", ref);
6245 output_sample = create_sample(NULL, output_info.cbSize);
6246 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
6248 winetest_push_context("%lu", i);
6249 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
6250 ok(!(output_status & ~MFT_OUTPUT_DATA_BUFFER_INCOMPLETE), "got output[0].dwStatus %#lx\n", output_status);
6251 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
6252 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
6253 ref = IMFSample_Release(output_sample);
6254 ok(ref == 1, "Release returned %ld\n", ref);
6255 output_sample = create_sample(NULL, output_info.cbSize);
6256 winetest_pop_context();
6258 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6259 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
6260 ret = IMFSample_Release(output_sample);
6261 ok(ret == 0, "Release returned %lu\n", ret);
6262 ok(i == 20 || broken(i == 41) /* Win7 */, "got %lu output samples\n", i);
6264 if (broken(length != 0x9c0))
6265 win_skip("Skipping MP3 decoder output sample checks on Win7 / Win8\n");
6266 else
6268 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"mp3decdata.bin");
6269 ok(ret == 0, "got %lu%% diff\n", ret);
6271 IMFCollection_Release(output_samples);
6273 output_sample = create_sample(NULL, mp3dec_block_size);
6274 hr = check_mft_process_output(transform, output_sample, &output_status);
6275 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6276 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
6277 hr = IMFSample_GetTotalLength(output_sample, &length);
6278 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
6279 ok(length == 0, "got length %lu\n", length);
6280 ret = IMFSample_Release(output_sample);
6281 ok(ret == 0, "Release returned %lu\n", ret);
6283 ret = IMFTransform_Release(transform);
6284 ok(ret == 0, "Release returned %lu\n", ret);
6286 failed:
6287 winetest_pop_context();
6288 CoUninitialize();
6291 START_TEST(transform)
6293 init_functions();
6295 test_sample_copier();
6296 test_sample_copier_output_processing();
6297 test_aac_encoder();
6298 test_aac_decoder();
6299 test_wma_encoder();
6300 test_wma_decoder();
6301 test_h264_decoder();
6302 test_wmv_encoder();
6303 test_wmv_decoder();
6304 test_wmv_decoder_media_object();
6305 test_audio_convert();
6306 test_color_convert();
6307 test_video_processor();
6308 test_mp3_decoder();