mf/tests: Test WMV decoder MFT / DMO presence and media types.
[wine.git] / dlls / mf / tests / transform.c
blob1a75fc009193887ceaa90c2062bb81cacbca289b
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 "dmoreg.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"
37 #include "mf_test.h"
39 #include "wine/test.h"
41 #include "initguid.h"
43 DEFINE_GUID(DMOVideoFormat_RGB24,D3DFMT_R8G8B8,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
44 DEFINE_GUID(DMOVideoFormat_RGB32,D3DFMT_X8R8G8B8,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
45 DEFINE_GUID(DMOVideoFormat_RGB555,D3DFMT_X1R5G5B5,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
46 DEFINE_GUID(DMOVideoFormat_RGB565,D3DFMT_R5G6B5,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
47 DEFINE_GUID(DMOVideoFormat_RGB8,D3DFMT_P8,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
48 DEFINE_GUID(MFAudioFormat_RAW_AAC1,WAVE_FORMAT_RAW_AAC1,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
49 DEFINE_GUID(MFVideoFormat_ABGR32,0x00000020,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
50 DEFINE_GUID(MFVideoFormat_P208,0x38303250,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
51 DEFINE_GUID(MFVideoFormat_VC1S,0x53314356,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
52 DEFINE_GUID(MFVideoFormat_WMV_Unknown,0x7ce12ca9,0xbfbf,0x43d9,0x9d,0x00,0x82,0xb8,0xed,0x54,0x31,0x6b);
54 DEFINE_GUID(mft_output_sample_incomplete,0xffffff,0xffff,0xffff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
56 static void load_resource(const WCHAR *filename, const BYTE **data, DWORD *length)
58 HRSRC resource = FindResourceW(NULL, filename, (const WCHAR *)RT_RCDATA);
59 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
60 *data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
61 *length = SizeofResource(GetModuleHandleW(NULL), resource);
64 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
65 static void _expect_ref(IUnknown* obj, ULONG expected_refcount, int line)
67 ULONG refcount;
68 IUnknown_AddRef(obj);
69 refcount = IUnknown_Release(obj);
70 ok_(__FILE__, line)(refcount == expected_refcount, "Unexpected refcount %ld, expected %ld.\n", refcount,
71 expected_refcount);
74 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
75 static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported)
77 IUnknown *iface = iface_ptr;
78 HRESULT hr, expected_hr;
79 IUnknown *unk;
81 expected_hr = supported ? S_OK : E_NOINTERFACE;
83 hr = IUnknown_QueryInterface(iface, iid, (void **)&unk);
84 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#lx, expected %#lx.\n", hr, expected_hr);
85 if (SUCCEEDED(hr))
86 IUnknown_Release(unk);
89 #define check_member_(file, line, val, exp, fmt, member) \
90 ok_ (file, line)((val).member == (exp).member, "got " #member " " fmt "\n", (val).member)
91 #define check_member(val, exp, fmt, member) check_member_(__FILE__, __LINE__, val, exp, fmt, member)
93 void check_attributes_(int line, IMFAttributes *attributes, const struct attribute_desc *desc, ULONG limit)
95 char buffer[256], *buf = buffer;
96 PROPVARIANT value;
97 int i, j, ret;
98 HRESULT hr;
100 for (i = 0; i < limit && desc[i].key; ++i)
102 hr = IMFAttributes_GetItem(attributes, desc[i].key, &value);
103 todo_wine_if(desc[i].todo)
104 ok_(__FILE__, line)(hr == S_OK, "%s missing, hr %#lx\n", debugstr_a(desc[i].name), hr);
105 if (hr != S_OK) continue;
107 switch (value.vt)
109 default: sprintf(buffer, "??"); break;
110 case VT_CLSID: sprintf(buffer, "%s", debugstr_guid(value.puuid)); break;
111 case VT_UI4: sprintf(buffer, "%lu", value.ulVal); break;
112 case VT_UI8:
113 if (desc[i].ratio)
114 sprintf(buffer, "%lu:%lu", value.uhVal.HighPart, value.uhVal.LowPart);
115 else
116 sprintf(buffer, "%I64u", value.uhVal.QuadPart);
117 break;
118 case VT_VECTOR | VT_UI1:
119 buf += sprintf(buf, "size %lu, data {", value.caub.cElems);
120 for (j = 0; j < 16 && j < value.caub.cElems; ++j)
121 buf += sprintf(buf, "0x%02x,", value.caub.pElems[j]);
122 if (value.caub.cElems > 16)
123 buf += sprintf(buf, "...}");
124 else
125 buf += sprintf(buf - (j ? 1 : 0), "}");
126 break;
129 ret = PropVariantCompareEx(&value, &desc[i].value, 0, 0);
130 todo_wine_if(desc[i].todo_value)
131 ok_(__FILE__, line)(ret == 0, "%s mismatch, type %u, value %s\n",
132 debugstr_a(desc[i].name), value.vt, buffer);
136 struct transform_info
138 const WCHAR *name;
139 const GUID *major_type;
140 struct
142 const GUID *subtype;
143 BOOL broken;
144 } inputs[32], input_end, outputs[32], output_end;
147 static BOOL check_mft_enum(GUID category, MFT_REGISTER_TYPE_INFO *input_type,
148 MFT_REGISTER_TYPE_INFO *output_type, const GUID *expect_class_id)
150 GUID *class_ids = NULL;
151 UINT32 count = 0, i;
152 HRESULT hr;
154 hr = MFTEnum(category, 0, input_type, output_type, NULL, &class_ids, &count);
155 if (FAILED(hr) || count == 0)
157 todo_wine
158 win_skip("MFTEnum returned %#lx, count %u, skipping tests.\n", hr, count);
159 return FALSE;
162 ok(hr == S_OK, "MFTEnum returned %#lx\n", hr);
163 for (i = 0; i < count; ++i)
164 if (IsEqualGUID(expect_class_id, class_ids + i))
165 break;
166 ok(i < count, "Failed to find transform.\n");
167 CoTaskMemFree(class_ids);
169 return i < count;
172 static void check_mft_get_info(const GUID *class_id, const struct transform_info *expect)
174 MFT_REGISTER_TYPE_INFO *input_types = NULL, *output_types = NULL;
175 UINT32 input_count = 0, output_count = 0, i;
176 WCHAR *name;
177 HRESULT hr;
179 hr = MFTGetInfo(*class_id, &name, &input_types, &input_count, &output_types, &output_count, NULL);
180 ok(hr == S_OK, "MFTEnum returned %#lx\n", hr);
181 ok(!wcscmp(name, expect->name), "got name %s\n", debugstr_w(name));
183 for (i = 0; i < input_count && expect->inputs[i].subtype; ++i)
185 ok(IsEqualGUID(&input_types[i].guidMajorType, expect->major_type),
186 "got input[%u] major %s\n", i, debugstr_guid(&input_types[i].guidMajorType));
187 ok(IsEqualGUID(&input_types[i].guidSubtype, expect->inputs[i].subtype),
188 "got input[%u] subtype %s\n", i, debugstr_guid(&input_types[i].guidSubtype));
190 for (; expect->inputs[i].subtype; ++i)
191 ok(broken(expect->inputs[i].broken), "missing input[%u] subtype %s\n",
192 i, debugstr_guid(expect->inputs[i].subtype));
193 for (; i < input_count; ++i)
194 ok(0, "extra input[%u] subtype %s\n", i, debugstr_guid(&input_types[i].guidSubtype));
196 for (i = 0; expect->outputs[i].subtype; ++i)
198 ok(IsEqualGUID(&output_types[i].guidMajorType, expect->major_type),
199 "got output[%u] major %s\n", i, debugstr_guid(&output_types[i].guidMajorType));
200 ok(IsEqualGUID(&output_types[i].guidSubtype, expect->outputs[i].subtype),
201 "got output[%u] subtype %s\n", i, debugstr_guid(&output_types[i].guidSubtype));
203 for (; expect->outputs[i].subtype; ++i)
204 ok(0, "missing output[%u] subtype %s\n", i, debugstr_guid(expect->outputs[i].subtype));
205 for (; i < output_count; ++i)
206 ok(0, "extra output[%u] subtype %s\n", i, debugstr_guid(&output_types[i].guidSubtype));
208 CoTaskMemFree(output_types);
209 CoTaskMemFree(input_types);
210 CoTaskMemFree(name);
213 static void check_dmo_get_info(const GUID *class_id, const struct transform_info *expect)
215 DWORD input_count = 0, output_count = 0;
216 DMO_PARTIAL_MEDIATYPE output[32] = {{{0}}};
217 DMO_PARTIAL_MEDIATYPE input[32] = {{{0}}};
218 WCHAR name[80];
219 HRESULT hr;
220 int i;
222 hr = DMOGetName(class_id, name);
223 ok(hr == S_OK, "DMOGetName returned %#lx\n", hr);
224 ok(!wcscmp(name, expect->name), "got name %s\n", debugstr_w(name));
226 hr = DMOGetTypes(class_id, ARRAY_SIZE(input), &input_count, input,
227 ARRAY_SIZE(output), &output_count, output);
228 ok(hr == S_OK, "DMOGetTypes returned %#lx\n", hr);
230 for (i = 0; i < input_count && expect->inputs[i].subtype; ++i)
232 ok(IsEqualGUID(&input[i].type, expect->major_type),
233 "got input[%u] major %s\n", i, debugstr_guid(&input[i].type));
234 ok(IsEqualGUID(&input[i].subtype, expect->inputs[i].subtype),
235 "got input[%u] subtype %s\n", i, debugstr_guid(&input[i].subtype));
237 for (; expect->inputs[i].subtype; ++i)
238 ok(0, "missing input[%u] subtype %s\n", i, debugstr_guid(expect->inputs[i].subtype));
239 for (; i < input_count; ++i)
240 ok(0, "extra input[%u] subtype %s\n", i, debugstr_guid(&input[i].subtype));
242 for (i = 0; expect->outputs[i].subtype; ++i)
244 ok(IsEqualGUID(&output[i].type, expect->major_type),
245 "got output[%u] major %s\n", i, debugstr_guid(&output[i].type));
246 ok(IsEqualGUID(&output[i].subtype, expect->outputs[i].subtype),
247 "got output[%u] subtype %s\n", i, debugstr_guid(&output[i].subtype));
249 for (; expect->outputs[i].subtype; ++i)
250 ok(0, "missing output[%u] subtype %s\n", i, debugstr_guid(expect->outputs[i].subtype));
251 for (; i < output_count; ++i)
252 ok(0, "extra output[%u] subtype %s\n", i, debugstr_guid(&output[i].subtype));
255 void init_media_type(IMFMediaType *mediatype, const struct attribute_desc *desc, ULONG limit)
257 HRESULT hr;
258 ULONG i;
260 hr = IMFMediaType_DeleteAllItems(mediatype);
261 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
263 for (i = 0; i < limit && desc[i].key; ++i)
265 hr = IMFMediaType_SetItem(mediatype, desc[i].key, &desc[i].value);
266 ok(hr == S_OK, "SetItem %s returned %#lx\n", debugstr_a(desc[i].name), hr);
270 static void check_mft_optional_methods(IMFTransform *transform)
272 DWORD in_id, out_id, in_count, out_count, in_min, in_max, out_min, out_max;
273 PROPVARIANT propvar = {.vt = VT_EMPTY};
274 IMFMediaEvent *event;
275 HRESULT hr;
277 in_min = in_max = out_min = out_max = 0xdeadbeef;
278 hr = IMFTransform_GetStreamLimits(transform, &in_min, &in_max, &out_min, &out_max);
279 ok(hr == S_OK, "GetStreamLimits returned %#lx\n", hr);
280 ok(in_min == 1, "got input_min %lu\n", in_min);
281 ok(in_max == 1, "got input_max %lu\n", in_max);
282 ok(out_min == 1, "got output_min %lu\n", out_min);
283 ok(out_max == 1, "got output_max %lu\n", out_max);
285 in_count = out_count = 0xdeadbeef;
286 hr = IMFTransform_GetStreamCount(transform, &in_count, &out_count);
287 ok(hr == S_OK, "GetStreamCount returned %#lx\n", hr);
288 ok(in_count == 1, "got input_count %lu\n", in_count);
289 ok(out_count == 1, "got output_count %lu\n", out_count);
291 in_count = out_count = 1;
292 in_id = out_id = 0xdeadbeef;
293 hr = IMFTransform_GetStreamIDs(transform, in_count, &in_id, out_count, &out_id);
294 ok(hr == E_NOTIMPL, "GetStreamIDs returned %#lx\n", hr);
296 hr = IMFTransform_DeleteInputStream(transform, 0);
297 ok(hr == E_NOTIMPL, "DeleteInputStream returned %#lx\n", hr);
298 hr = IMFTransform_DeleteInputStream(transform, 1);
299 ok(hr == E_NOTIMPL, "DeleteInputStream returned %#lx\n", hr);
301 hr = IMFTransform_AddInputStreams(transform, 0, NULL);
302 ok(hr == E_NOTIMPL, "AddInputStreams returned %#lx\n", hr);
303 in_id = 0xdeadbeef;
304 hr = IMFTransform_AddInputStreams(transform, 1, &in_id);
305 ok(hr == E_NOTIMPL, "AddInputStreams returned %#lx\n", hr);
307 hr = IMFTransform_SetOutputBounds(transform, 0, 0);
308 ok(hr == E_NOTIMPL || hr == S_OK, "SetOutputBounds returned %#lx\n", hr);
310 hr = MFCreateMediaEvent(MEEndOfStream, &GUID_NULL, S_OK, &propvar, &event);
311 ok(hr == S_OK, "MFCreateMediaEvent returned %#lx\n", hr);
312 hr = IMFTransform_ProcessEvent(transform, 0, NULL);
313 ok(hr == E_NOTIMPL || hr == E_POINTER || hr == E_INVALIDARG, "ProcessEvent returned %#lx\n", hr);
314 hr = IMFTransform_ProcessEvent(transform, 1, event);
315 ok(hr == E_NOTIMPL, "ProcessEvent returned %#lx\n", hr);
316 hr = IMFTransform_ProcessEvent(transform, 0, event);
317 ok(hr == E_NOTIMPL, "ProcessEvent returned %#lx\n", hr);
318 IMFMediaEvent_Release(event);
321 static void check_mft_get_attributes(IMFTransform *transform, const struct attribute_desc *expect_transform_attributes,
322 BOOL expect_output_attributes)
324 IMFAttributes *attributes, *tmp_attributes;
325 UINT32 count;
326 HRESULT hr;
327 ULONG ref;
329 hr = IMFTransform_GetAttributes(transform, &attributes);
330 ok(hr == (expect_transform_attributes ? S_OK : E_NOTIMPL), "GetAttributes returned %#lx\n", hr);
331 if (hr == S_OK)
333 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
334 check_attributes(attributes, expect_transform_attributes, -1);
336 hr = IMFTransform_GetAttributes(transform, &tmp_attributes);
337 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
338 ok(attributes == tmp_attributes, "got attributes %p\n", tmp_attributes);
339 IMFAttributes_Release(tmp_attributes);
341 ref = IMFAttributes_Release(attributes);
342 ok(ref == 1, "Release returned %lu\n", ref);
345 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes);
346 ok(hr == (expect_output_attributes ? S_OK : E_NOTIMPL)
347 || broken(hr == MF_E_UNSUPPORTED_REPRESENTATION) /* Win7 */,
348 "GetOutputStreamAttributes returned %#lx\n", hr);
349 if (hr == S_OK)
351 ok(hr == S_OK, "GetOutputStreamAttributes returned %#lx\n", hr);
353 count = 0xdeadbeef;
354 hr = IMFAttributes_GetCount(attributes, &count);
355 ok(hr == S_OK, "GetCount returned %#lx\n", hr);
356 ok(!count, "got %u attributes\n", count);
358 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &tmp_attributes);
359 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
360 ok(attributes == tmp_attributes, "got attributes %p\n", tmp_attributes);
361 IMFAttributes_Release(tmp_attributes);
363 ref = IMFAttributes_Release(attributes);
364 ok(ref == 1, "Release returned %lu\n", ref);
366 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, NULL);
367 ok(hr == E_NOTIMPL || hr == E_POINTER, "GetOutputStreamAttributes returned %#lx\n", hr);
368 hr = IMFTransform_GetOutputStreamAttributes(transform, 1, &attributes);
369 ok(hr == MF_E_INVALIDSTREAMNUMBER, "GetOutputStreamAttributes returned %#lx\n", hr);
372 hr = IMFTransform_GetInputStreamAttributes(transform, 0, &attributes);
373 ok(hr == E_NOTIMPL || broken(hr == MF_E_UNSUPPORTED_REPRESENTATION) /* Win7 */,
374 "GetInputStreamAttributes returned %#lx\n", hr);
377 #define check_mft_input_stream_info(a, b) check_mft_input_stream_info_(__LINE__, a, b)
378 static void check_mft_input_stream_info_(int line, MFT_INPUT_STREAM_INFO *value, const MFT_INPUT_STREAM_INFO *expect)
380 check_member_(__FILE__, line, *value, *expect, "%I64d", hnsMaxLatency);
381 check_member_(__FILE__, line, *value, *expect, "%#lx", dwFlags);
382 check_member_(__FILE__, line, *value, *expect, "%#lx", cbSize);
383 check_member_(__FILE__, line, *value, *expect, "%#lx", cbMaxLookahead);
384 check_member_(__FILE__, line, *value, *expect, "%#lx", cbAlignment);
387 #define check_mft_get_input_stream_info(a, b, c) check_mft_get_input_stream_info_(__LINE__, a, b, c)
388 static void check_mft_get_input_stream_info_(int line, IMFTransform *transform, HRESULT expect_hr, const MFT_INPUT_STREAM_INFO *expect)
390 MFT_INPUT_STREAM_INFO info, empty = {0};
391 HRESULT hr;
393 memset(&info, 0xcd, sizeof(info));
394 hr = IMFTransform_GetInputStreamInfo(transform, 0, &info);
395 ok_(__FILE__, line)(hr == expect_hr, "GetInputStreamInfo returned %#lx\n", hr);
396 check_mft_input_stream_info_(line, &info, expect ? expect : &empty);
399 #define check_mft_output_stream_info(a, b) check_mft_output_stream_info_(__LINE__, a, b)
400 static void check_mft_output_stream_info_(int line, MFT_OUTPUT_STREAM_INFO *value, const MFT_OUTPUT_STREAM_INFO *expect)
402 check_member_(__FILE__, line, *value, *expect, "%#lx", dwFlags);
403 check_member_(__FILE__, line, *value, *expect, "%#lx", cbSize);
404 check_member_(__FILE__, line, *value, *expect, "%#lx", cbAlignment);
407 #define check_mft_get_output_stream_info(a, b, c) check_mft_get_output_stream_info_(__LINE__, a, b, c)
408 static void check_mft_get_output_stream_info_(int line, IMFTransform *transform, HRESULT expect_hr, const MFT_OUTPUT_STREAM_INFO *expect)
410 MFT_OUTPUT_STREAM_INFO info, empty = {0};
411 HRESULT hr;
413 memset(&info, 0xcd, sizeof(info));
414 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &info);
415 ok_(__FILE__, line)(hr == expect_hr, "GetOutputStreamInfo returned %#lx\n", hr);
416 check_mft_output_stream_info_(line, &info, expect ? expect : &empty);
419 #define check_mft_set_input_type_required(a, b) check_mft_set_input_type_required_(__LINE__, a, b)
420 static void check_mft_set_input_type_required_(int line, IMFTransform *transform, const struct attribute_desc *attributes)
422 const struct attribute_desc *attr;
423 IMFMediaType *media_type;
424 HRESULT hr;
425 ULONG ref;
427 hr = MFCreateMediaType(&media_type);
428 ok_(__FILE__, line)(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
429 init_media_type(media_type, attributes, -1);
431 for (attr = attributes; attr && attr->key; attr++)
433 winetest_push_context("%s", debugstr_a(attr->name));
434 hr = IMFMediaType_DeleteItem(media_type, attr->key);
435 ok_(__FILE__, line)(hr == S_OK, "DeleteItem returned %#lx\n", hr);
436 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
437 ok_(__FILE__, line)(FAILED(hr) == attr->required, "SetInputType returned %#lx.\n", hr);
438 hr = IMFMediaType_SetItem(media_type, attr->key, &attr->value);
439 ok_(__FILE__, line)(hr == S_OK, "SetItem returned %#lx\n", hr);
440 winetest_pop_context();
443 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
444 ok_(__FILE__, line)(hr == S_OK, "SetInputType returned %#lx.\n", hr);
445 ref = IMFMediaType_Release(media_type);
446 ok_(__FILE__, line)(!ref, "Release returned %lu\n", ref);
449 static void check_mft_set_input_type(IMFTransform *transform, const struct attribute_desc *attributes)
451 IMFMediaType *media_type;
452 HRESULT hr;
454 hr = MFCreateMediaType(&media_type);
455 ok(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
456 init_media_type(media_type, attributes, -1);
458 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
459 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
460 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
461 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
463 IMFMediaType_Release(media_type);
466 #define check_mft_get_input_current_type(a, b) check_mft_get_input_current_type_(a, b, FALSE, FALSE)
467 static void check_mft_get_input_current_type_(IMFTransform *transform, const struct attribute_desc *attributes,
468 BOOL todo_current, BOOL todo_compare)
470 HRESULT hr, expect_hr = attributes ? S_OK : MF_E_TRANSFORM_TYPE_NOT_SET;
471 IMFMediaType *media_type, *current_type;
472 BOOL result;
474 hr = IMFTransform_GetInputCurrentType(transform, 0, &current_type);
475 todo_wine_if(todo_current)
476 ok(hr == expect_hr, "GetInputCurrentType returned hr %#lx.\n", hr);
477 if (FAILED(hr))
478 return;
480 hr = MFCreateMediaType(&media_type);
481 ok(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
482 init_media_type(media_type, attributes, -1);
484 hr = IMFMediaType_Compare(current_type, (IMFAttributes *)media_type,
485 MF_ATTRIBUTES_MATCH_ALL_ITEMS, &result);
486 ok(hr == S_OK, "Compare returned hr %#lx.\n", hr);
487 todo_wine_if(todo_compare)
488 ok(result, "got result %u.\n", !!result);
490 IMFMediaType_Release(media_type);
491 IMFMediaType_Release(current_type);
494 #define check_mft_set_output_type_required(a, b) check_mft_set_output_type_required_(__LINE__, a, b)
495 static void check_mft_set_output_type_required_(int line, IMFTransform *transform, const struct attribute_desc *attributes)
497 const struct attribute_desc *attr;
498 IMFMediaType *media_type;
499 HRESULT hr;
500 ULONG ref;
502 hr = MFCreateMediaType(&media_type);
503 ok_(__FILE__, line)(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
504 init_media_type(media_type, attributes, -1);
506 for (attr = attributes; attr && attr->key; attr++)
508 winetest_push_context("%s", debugstr_a(attr->name));
509 hr = IMFMediaType_DeleteItem(media_type, attr->key);
510 ok_(__FILE__, line)(hr == S_OK, "DeleteItem returned %#lx\n", hr);
511 hr = IMFTransform_SetOutputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
512 ok_(__FILE__, line)(FAILED(hr) == attr->required, "SetOutputType returned %#lx.\n", hr);
513 hr = IMFMediaType_SetItem(media_type, attr->key, &attr->value);
514 ok_(__FILE__, line)(hr == S_OK, "SetItem returned %#lx\n", hr);
515 winetest_pop_context();
518 hr = IMFTransform_SetOutputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
519 ok_(__FILE__, line)(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
520 ref = IMFMediaType_Release(media_type);
521 ok_(__FILE__, line)(!ref, "Release returned %lu\n", ref);
524 static void check_mft_set_output_type(IMFTransform *transform, const struct attribute_desc *attributes,
525 HRESULT expect_hr)
527 IMFMediaType *media_type;
528 HRESULT hr;
530 hr = MFCreateMediaType(&media_type);
531 ok(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
532 init_media_type(media_type, attributes, -1);
534 hr = IMFTransform_SetOutputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
535 ok(hr == expect_hr, "SetOutputType returned %#lx.\n", hr);
536 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
537 ok(hr == expect_hr, "SetOutputType returned %#lx.\n", hr);
539 IMFMediaType_Release(media_type);
542 #define check_mft_get_output_current_type(a, b) check_mft_get_output_current_type_(a, b, FALSE, FALSE)
543 static void check_mft_get_output_current_type_(IMFTransform *transform, const struct attribute_desc *attributes,
544 BOOL todo_current, BOOL todo_compare)
546 HRESULT hr, expect_hr = attributes ? S_OK : MF_E_TRANSFORM_TYPE_NOT_SET;
547 IMFMediaType *media_type, *current_type;
548 BOOL result;
550 hr = IMFTransform_GetOutputCurrentType(transform, 0, &current_type);
551 todo_wine_if(todo_current)
552 ok(hr == expect_hr, "GetOutputCurrentType returned hr %#lx.\n", hr);
553 if (FAILED(hr))
554 return;
556 hr = MFCreateMediaType(&media_type);
557 ok(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
558 init_media_type(media_type, attributes, -1);
560 hr = IMFMediaType_Compare(current_type, (IMFAttributes *)media_type,
561 MF_ATTRIBUTES_MATCH_ALL_ITEMS, &result);
562 ok(hr == S_OK, "Compare returned hr %#lx.\n", hr);
563 todo_wine_if(todo_compare)
564 ok(result, "got result %u.\n", !!result);
566 IMFMediaType_Release(media_type);
567 IMFMediaType_Release(current_type);
570 #define check_mft_process_output(a, b, c) check_mft_process_output_(__LINE__, a, b, c)
571 static HRESULT check_mft_process_output_(int line, IMFTransform *transform, IMFSample *output_sample, DWORD *output_status)
573 static const DWORD expect_flags = MFT_OUTPUT_DATA_BUFFER_INCOMPLETE | MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE
574 | MFT_OUTPUT_DATA_BUFFER_STREAM_END | MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE;
575 MFT_OUTPUT_DATA_BUFFER output[2];
576 HRESULT hr, ret;
577 DWORD status;
579 status = 0;
580 memset(&output, 0, sizeof(output));
581 output[0].pSample = output_sample;
582 output[0].dwStreamID = 0;
583 ret = IMFTransform_ProcessOutput(transform, 0, 1, output, &status);
584 ok_(__FILE__, line)(output[0].dwStreamID == 0, "got dwStreamID %#lx\n", output[0].dwStreamID);
585 ok_(__FILE__, line)(output[0].pEvents == NULL, "got pEvents %p\n", output[0].pEvents);
586 ok_(__FILE__, line)(output[0].pSample == output_sample, "got pSample %p\n", output[0].pSample);
587 ok_(__FILE__, line)((output[0].dwStatus & ~expect_flags) == 0
588 || broken((output[0].dwStatus & ~expect_flags) == 6) /* Win7 */
589 || broken((output[0].dwStatus & ~expect_flags) == 7) /* Win7 */,
590 "got dwStatus %#lx\n", output[0].dwStatus);
591 *output_status = output[0].dwStatus & expect_flags;
593 if (!output_sample)
594 ok_(__FILE__, line)(status == 0, "got status %#lx\n", status);
595 else if (ret == MF_E_TRANSFORM_STREAM_CHANGE)
596 ok_(__FILE__, line)(status == MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS,
597 "got status %#lx\n", status);
598 else
600 if (*output_status & MFT_OUTPUT_DATA_BUFFER_INCOMPLETE)
602 hr = IMFSample_SetUINT32(output_sample, &mft_output_sample_incomplete, 1);
603 ok_(__FILE__, line)(hr == S_OK, "SetUINT32 returned %#lx\n", hr);
605 else
607 hr = IMFSample_DeleteItem(output_sample, &mft_output_sample_incomplete);
608 ok_(__FILE__, line)(hr == S_OK, "DeleteItem returned %#lx\n", hr);
610 ok_(__FILE__, line)(status == 0, "got status %#lx\n", status);
613 return ret;
616 typedef DWORD (*compare_cb)(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect);
618 static DWORD compare_nv12(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
620 DWORD x, y, size, diff = 0, width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
622 /* skip BMP header and RGB data from the dump */
623 size = *(DWORD *)(expect + 2);
624 *length = *length + size;
625 expect = expect + size;
627 for (y = 0; y < height; y++, data += width, expect += width)
629 if (y < rect->top || y >= rect->bottom) continue;
630 for (x = 0; x < width; x++)
632 if (x < rect->left || x >= rect->right) continue;
633 diff += abs((int)expect[x] - (int)data[x]);
637 for (y = 0; y < height; y += 2, data += width, expect += width)
639 if (y < rect->top || y >= rect->bottom) continue;
640 for (x = 0; x < width; x += 2)
642 if (x < rect->left || x >= rect->right) continue;
643 diff += abs((int)expect[x + 0] - (int)data[x + 0]);
644 diff += abs((int)expect[x + 1] - (int)data[x + 1]);
648 size = (rect->right - rect->left) * (rect->bottom - rect->top) * 3 / 2;
649 return diff * 100 / 256 / size;
652 static DWORD compare_i420(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
654 DWORD i, x, y, size, diff = 0, width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
656 /* skip BMP header and RGB data from the dump */
657 size = *(DWORD *)(expect + 2);
658 *length = *length + size;
659 expect = expect + size;
661 for (y = 0; y < height; y++, data += width, expect += width)
663 if (y < rect->top || y >= rect->bottom) continue;
664 for (x = 0; x < width; x++)
666 if (x < rect->left || x >= rect->right) continue;
667 diff += abs((int)expect[x] - (int)data[x]);
671 for (i = 0; i < 2; ++i) for (y = 0; y < height; y += 2, data += width / 2, expect += width / 2)
673 if (y < rect->top || y >= rect->bottom) continue;
674 for (x = 0; x < width; x += 2)
676 if (x < rect->left || x >= rect->right) continue;
677 diff += abs((int)expect[x / 2] - (int)data[x / 2]);
681 size = (rect->right - rect->left) * (rect->bottom - rect->top) * 3 / 2;
682 return diff * 100 / 256 / size;
685 static DWORD compare_rgb32(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
687 DWORD x, y, size, diff = 0, width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
689 /* skip BMP header from the dump */
690 size = *(DWORD *)(expect + 2 + 2 * sizeof(DWORD));
691 *length = *length + size;
692 expect = expect + size;
694 for (y = 0; y < height; y++, data += width * 4, expect += width * 4)
696 if (y < rect->top || y >= rect->bottom) continue;
697 for (x = 0; x < width; x++)
699 if (x < rect->left || x >= rect->right) continue;
700 diff += abs((int)expect[4 * x + 0] - (int)data[4 * x + 0]);
701 diff += abs((int)expect[4 * x + 1] - (int)data[4 * x + 1]);
702 diff += abs((int)expect[4 * x + 2] - (int)data[4 * x + 2]);
706 size = (rect->right - rect->left) * (rect->bottom - rect->top) * 3;
707 return diff * 100 / 256 / size;
710 static DWORD compare_pcm16(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
712 const INT16 *data_pcm = (INT16 *)data, *expect_pcm = (INT16 *)expect;
713 DWORD i, size = *length / 2, diff = 0;
715 for (i = 0; i < size; i++)
716 diff += abs((int)*expect_pcm++ - (int)*data_pcm++);
718 return diff * 100 / 65536 / size;
721 static DWORD compare_bytes(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
723 DWORD i, size = *length, diff = 0;
725 for (i = 0; i < size; i++)
726 diff += abs((int)*expect++ - (int)*data++);
728 return diff * 100 / 256 / size;
731 typedef void (*dump_cb)(const BYTE *data, DWORD length, const RECT *rect, HANDLE output);
733 static void dump_rgb32(const BYTE *data, DWORD length, const RECT *rect, HANDLE output)
735 DWORD width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
736 static const char magic[2] = "BM";
737 struct
739 DWORD length;
740 DWORD reserved;
741 DWORD offset;
742 BITMAPINFOHEADER biHeader;
743 } header =
745 .length = length + sizeof(header) + 2, .offset = sizeof(header) + 2,
746 .biHeader =
748 .biSize = sizeof(BITMAPINFOHEADER), .biWidth = width, .biHeight = height, .biPlanes = 1,
749 .biBitCount = 32, .biCompression = BI_RGB, .biSizeImage = width * height * 4,
752 DWORD written;
753 BOOL ret;
755 ret = WriteFile(output, magic, sizeof(magic), &written, NULL);
756 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
757 ok(written == sizeof(magic), "written %lu bytes\n", written);
758 ret = WriteFile(output, &header, sizeof(header), &written, NULL);
759 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
760 ok(written == sizeof(header), "written %lu bytes\n", written);
761 ret = WriteFile(output, data, length, &written, NULL);
762 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
763 ok(written == length, "written %lu bytes\n", written);
766 static void dump_nv12(const BYTE *data, DWORD length, const RECT *rect, HANDLE output)
768 DWORD written, x, y, width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
769 BYTE *rgb32_data = malloc(width * height * 4), *rgb32 = rgb32_data;
770 BOOL ret;
772 for (y = 0; y < height; y++) for (x = 0; x < width; x++)
774 *rgb32++ = data[width * y + x];
775 *rgb32++ = data[width * height + width * (y / 2) + (x & ~1) + 0];
776 *rgb32++ = data[width * height + width * (y / 2) + (x & ~1) + 1];
777 *rgb32++ = 0xff;
780 dump_rgb32(rgb32_data, width * height * 4, rect, output);
781 free(rgb32_data);
783 ret = WriteFile(output, data, length, &written, NULL);
784 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
785 ok(written == length, "written %lu bytes\n", written);
788 static void dump_i420(const BYTE *data, DWORD length, const RECT *rect, HANDLE output)
790 DWORD written, x, y, width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
791 BYTE *rgb32_data = malloc(width * height * 4), *rgb32 = rgb32_data;
792 BOOL ret;
794 for (y = 0; y < height; y++) for (x = 0; x < width; x++)
796 *rgb32++ = data[width * y + x];
797 *rgb32++ = data[width * height + (width / 2) * (y / 2) + x / 2];
798 *rgb32++ = data[width * height + (width / 2) * (y / 2) + (width / 2) * (height / 2) + x / 2];
799 *rgb32++ = 0xff;
802 dump_rgb32(rgb32_data, width * height * 4, rect, output);
803 free(rgb32_data);
805 ret = WriteFile(output, data, length, &written, NULL);
806 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
807 ok(written == length, "written %lu bytes\n", written);
810 struct buffer_desc
812 DWORD length;
813 BOOL todo_length;
814 compare_cb compare;
815 dump_cb dump;
816 RECT rect;
819 struct sample_desc
821 const struct attribute_desc *attributes;
822 LONGLONG sample_time;
823 LONGLONG sample_duration;
824 DWORD buffer_count;
825 const struct buffer_desc *buffers;
826 DWORD repeat_count;
827 BOOL todo_length;
828 LONGLONG todo_time;
831 typedef void (*enum_mf_media_buffers_cb)(IMFMediaBuffer *buffer, const struct buffer_desc *desc, void *context);
832 static void enum_mf_media_buffers(IMFSample *sample, const struct sample_desc *sample_desc,
833 enum_mf_media_buffers_cb callback, void *context)
835 IMFMediaBuffer *buffer;
836 HRESULT hr;
837 DWORD i;
839 for (i = 0; SUCCEEDED(hr = IMFSample_GetBufferByIndex(sample, i, &buffer)); i++)
841 winetest_push_context("buffer %lu", i);
842 ok(hr == S_OK, "GetBufferByIndex returned %#lx\n", hr);
843 ok(i < sample_desc->buffer_count, "got unexpected buffer\n");
845 callback(buffer, sample_desc->buffers + i, context);
847 IMFMediaBuffer_Release(buffer);
848 winetest_pop_context();
850 ok(hr == E_INVALIDARG, "GetBufferByIndex returned %#lx\n", hr);
853 struct enum_mf_sample_state
855 const struct sample_desc *next_sample;
856 struct sample_desc sample;
859 typedef void (*enum_mf_sample_cb)(IMFSample *sample, const struct sample_desc *sample_desc, void *context);
860 static void enum_mf_samples(IMFCollection *samples, const struct sample_desc *collection_desc,
861 enum_mf_sample_cb callback, void *context)
863 struct enum_mf_sample_state state = {.next_sample = collection_desc};
864 IMFSample *sample;
865 HRESULT hr;
866 DWORD i;
868 for (i = 0; SUCCEEDED(hr = IMFCollection_GetElement(samples, i, (IUnknown **)&sample)); i++)
870 winetest_push_context("sample %lu", i);
871 ok(hr == S_OK, "GetElement returned %#lx\n", hr);
873 state.sample.sample_time += state.sample.sample_duration;
874 if (!state.sample.repeat_count--)
875 state.sample = *state.next_sample++;
877 callback(sample, &state.sample, context);
879 IMFSample_Release(sample);
880 winetest_pop_context();
882 ok(hr == E_INVALIDARG, "GetElement returned %#lx\n", hr);
885 static void dump_mf_media_buffer(IMFMediaBuffer *buffer, const struct buffer_desc *buffer_desc, HANDLE output)
887 DWORD length, written;
888 HRESULT hr;
889 BYTE *data;
890 BOOL ret;
892 hr = IMFMediaBuffer_Lock(buffer, &data, NULL, &length);
893 ok(hr == S_OK, "Lock returned %#lx\n", hr);
895 if (buffer_desc->dump)
896 buffer_desc->dump(data, length, &buffer_desc->rect, output);
897 else
899 if (buffer_desc->length == -1)
901 ret = WriteFile(output, &length, sizeof(length), &written, NULL);
902 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
903 ok(written == sizeof(length), "written %lu bytes\n", written);
906 ret = WriteFile(output, data, length, &written, NULL);
907 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
908 ok(written == length, "written %lu bytes\n", written);
911 hr = IMFMediaBuffer_Unlock(buffer);
912 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
915 static void dump_mf_sample(IMFSample *sample, const struct sample_desc *sample_desc, HANDLE output)
917 enum_mf_media_buffers(sample, sample_desc, dump_mf_media_buffer, output);
920 static void dump_mf_sample_collection(IMFCollection *samples, const struct sample_desc *collection_desc,
921 const WCHAR *output_filename)
923 WCHAR path[MAX_PATH];
924 HANDLE output;
926 GetTempPathW(ARRAY_SIZE(path), path);
927 lstrcatW(path, output_filename);
929 output = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
930 ok(output != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
932 enum_mf_samples(samples, collection_desc, dump_mf_sample, output);
934 trace("created %s\n", debugstr_w(path));
935 CloseHandle(output);
938 #define check_mf_media_buffer(a, b, c) check_mf_media_buffer_(__LINE__, a, b, c)
939 static DWORD check_mf_media_buffer_(int line, IMFMediaBuffer *buffer, const struct buffer_desc *expect,
940 const BYTE **expect_data, DWORD *expect_data_len)
942 DWORD length, diff = 0, expect_length = expect->length;
943 HRESULT hr;
944 BYTE *data;
946 if (expect_length == -1)
948 expect_length = *(DWORD *)*expect_data;
949 *expect_data = *expect_data + sizeof(DWORD);
950 *expect_data_len = *expect_data_len - sizeof(DWORD);
953 hr = IMFMediaBuffer_Lock(buffer, &data, NULL, &length);
954 ok_(__FILE__, line)(hr == S_OK, "Lock returned %#lx\n", hr);
955 todo_wine_if(expect->todo_length)
956 ok_(__FILE__, line)(length == expect_length, "got length %#lx\n", length);
958 if (*expect_data_len < length)
959 todo_wine_if(expect->todo_length)
960 ok_(__FILE__, line)(0, "missing %#lx bytes\n", length - *expect_data_len);
961 else if (!expect->compare)
962 diff = compare_bytes(data, &length, NULL, *expect_data);
963 else
964 diff = expect->compare(data, &length, &expect->rect, *expect_data);
966 hr = IMFMediaBuffer_Unlock(buffer);
967 ok_(__FILE__, line)(hr == S_OK, "Unlock returned %#lx\n", hr);
969 *expect_data = *expect_data + min(length, *expect_data_len);
970 *expect_data_len = *expect_data_len - min(length, *expect_data_len);
972 return diff;
975 struct check_mf_sample_context
977 DWORD total_length;
978 const BYTE *data;
979 DWORD data_len;
980 DWORD diff;
981 int line;
984 static void check_mf_sample_buffer(IMFMediaBuffer *buffer, const struct buffer_desc *expect, void *context)
986 struct check_mf_sample_context *ctx = context;
987 DWORD expect_length = expect->length == -1 ? *(DWORD *)ctx->data : expect->length;
988 ctx->diff += check_mf_media_buffer_(ctx->line, buffer, expect, &ctx->data, &ctx->data_len);
989 ctx->total_length += expect_length;
992 #define check_mf_sample(a, b, c, d) check_mf_sample_(__LINE__, a, b, c, d)
993 static DWORD check_mf_sample_(int line, IMFSample *sample, const struct sample_desc *expect,
994 const BYTE **expect_data, DWORD *expect_data_len)
996 struct check_mf_sample_context ctx = {.data = *expect_data, .data_len = *expect_data_len, .line = line};
997 DWORD buffer_count, total_length, sample_flags;
998 LONGLONG timestamp;
999 HRESULT hr;
1001 if (expect->attributes)
1002 check_attributes_(line, (IMFAttributes *)sample, expect->attributes, -1);
1004 buffer_count = 0xdeadbeef;
1005 hr = IMFSample_GetBufferCount(sample, &buffer_count);
1006 ok_(__FILE__, line)(hr == S_OK, "GetBufferCount returned %#lx\n", hr);
1007 ok_(__FILE__, line)(buffer_count == expect->buffer_count,
1008 "got %lu buffers\n", buffer_count);
1010 sample_flags = 0xdeadbeef;
1011 hr = IMFSample_GetSampleFlags(sample, &sample_flags);
1012 ok_(__FILE__, line)(hr == S_OK, "GetSampleFlags returned %#lx\n", hr);
1013 ok_(__FILE__, line)(sample_flags == 0,
1014 "got sample flags %#lx\n", sample_flags);
1016 timestamp = 0xdeadbeef;
1017 hr = IMFSample_GetSampleTime(sample, &timestamp);
1018 ok_(__FILE__, line)(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
1019 todo_wine_if(expect->todo_time && timestamp == expect->todo_time)
1020 ok_(__FILE__, line)(llabs(timestamp - expect->sample_time) <= 50,
1021 "got sample time %I64d\n", timestamp);
1023 timestamp = 0xdeadbeef;
1024 hr = IMFSample_GetSampleDuration(sample, &timestamp);
1025 ok_(__FILE__, line)(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
1026 todo_wine_if(expect->todo_length)
1027 ok_(__FILE__, line)(llabs(timestamp - expect->sample_duration) <= 1,
1028 "got sample duration %I64d\n", timestamp);
1030 enum_mf_media_buffers(sample, expect, check_mf_sample_buffer, &ctx);
1032 total_length = 0xdeadbeef;
1033 hr = IMFSample_GetTotalLength(sample, &total_length);
1034 ok_(__FILE__, line)(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
1035 todo_wine_if(expect->todo_length)
1036 ok_(__FILE__, line)(total_length == ctx.total_length,
1037 "got total length %#lx\n", total_length);
1038 ok_(__FILE__, line)(*expect_data_len >= ctx.total_length,
1039 "missing %#lx data\n", ctx.total_length - *expect_data_len);
1041 *expect_data = ctx.data;
1042 *expect_data_len = ctx.data_len;
1044 return ctx.diff / buffer_count;
1047 static void check_mf_sample_collection_enum(IMFSample *sample, const struct sample_desc *expect, void *context)
1049 struct check_mf_sample_context *ctx = context;
1050 ctx->diff += check_mf_sample_(ctx->line, sample, expect, &ctx->data, &ctx->data_len);
1053 #define check_mf_sample_collection(a, b, c) check_mf_sample_collection_(__LINE__, a, b, c)
1054 static DWORD check_mf_sample_collection_(int line, IMFCollection *samples,
1055 const struct sample_desc *expect_samples, const WCHAR *expect_data_filename)
1057 struct check_mf_sample_context ctx = {.line = line};
1058 DWORD count;
1059 HRESULT hr;
1061 load_resource(expect_data_filename, &ctx.data, &ctx.data_len);
1062 enum_mf_samples(samples, expect_samples, check_mf_sample_collection_enum, &ctx);
1064 dump_mf_sample_collection(samples, expect_samples, expect_data_filename);
1066 hr = IMFCollection_GetElementCount(samples, &count);
1067 ok_(__FILE__, line)(hr == S_OK, "GetElementCount returned %#lx\n", hr);
1069 return ctx.diff / count;
1072 static HRESULT WINAPI test_unk_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
1074 if (IsEqualIID(riid, &IID_IUnknown))
1076 *obj = iface;
1077 IUnknown_AddRef(iface);
1078 return S_OK;
1081 *obj = NULL;
1082 return E_NOINTERFACE;
1085 static ULONG WINAPI test_unk_AddRef(IUnknown *iface)
1087 return 2;
1090 static ULONG WINAPI test_unk_Release(IUnknown *iface)
1092 return 1;
1095 static const IUnknownVtbl test_unk_vtbl =
1097 test_unk_QueryInterface,
1098 test_unk_AddRef,
1099 test_unk_Release,
1102 static BOOL is_supported_video_type(const GUID *guid)
1104 return IsEqualGUID(guid, &MFVideoFormat_L8)
1105 || IsEqualGUID(guid, &MFVideoFormat_L16)
1106 || IsEqualGUID(guid, &MFVideoFormat_D16)
1107 || IsEqualGUID(guid, &MFVideoFormat_IYUV)
1108 || IsEqualGUID(guid, &MFVideoFormat_YV12)
1109 || IsEqualGUID(guid, &MFVideoFormat_NV12)
1110 || IsEqualGUID(guid, &MFVideoFormat_NV21)
1111 || IsEqualGUID(guid, &MFVideoFormat_420O)
1112 || IsEqualGUID(guid, &MFVideoFormat_P010)
1113 || IsEqualGUID(guid, &MFVideoFormat_P016)
1114 || IsEqualGUID(guid, &MFVideoFormat_UYVY)
1115 || IsEqualGUID(guid, &MFVideoFormat_YUY2)
1116 || IsEqualGUID(guid, &MFVideoFormat_P208)
1117 || IsEqualGUID(guid, &MFVideoFormat_NV11)
1118 || IsEqualGUID(guid, &MFVideoFormat_AYUV)
1119 || IsEqualGUID(guid, &MFVideoFormat_ARGB32)
1120 || IsEqualGUID(guid, &MFVideoFormat_RGB32)
1121 || IsEqualGUID(guid, &MFVideoFormat_A2R10G10B10)
1122 || IsEqualGUID(guid, &MFVideoFormat_A16B16G16R16F)
1123 || IsEqualGUID(guid, &MFVideoFormat_RGB24)
1124 || IsEqualGUID(guid, &MFVideoFormat_I420)
1125 || IsEqualGUID(guid, &MFVideoFormat_YVYU)
1126 || IsEqualGUID(guid, &MFVideoFormat_RGB555)
1127 || IsEqualGUID(guid, &MFVideoFormat_RGB565)
1128 || IsEqualGUID(guid, &MFVideoFormat_RGB8)
1129 || IsEqualGUID(guid, &MFVideoFormat_Y216)
1130 || IsEqualGUID(guid, &MFVideoFormat_v410)
1131 || IsEqualGUID(guid, &MFVideoFormat_Y41P)
1132 || IsEqualGUID(guid, &MFVideoFormat_Y41T)
1133 || IsEqualGUID(guid, &MFVideoFormat_Y42T)
1134 || IsEqualGUID(guid, &MFVideoFormat_ABGR32);
1137 static BOOL is_sample_copier_available_type(IMFMediaType *type)
1139 GUID major = { 0 };
1140 UINT32 count;
1141 HRESULT hr;
1143 hr = IMFMediaType_GetMajorType(type, &major);
1144 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
1146 hr = IMFMediaType_GetCount(type, &count);
1147 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
1148 ok(count == 1, "Unexpected attribute count %u.\n", count);
1150 return IsEqualGUID(&major, &MFMediaType_Video) || IsEqualGUID(&major, &MFMediaType_Audio);
1153 static void test_sample_copier(void)
1155 static const struct attribute_desc expect_transform_attributes[] =
1157 ATTR_UINT32(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, 1),
1158 {0},
1160 const MFT_OUTPUT_STREAM_INFO initial_output_info = {0}, output_info = {.cbSize = 16 * 16};
1161 const MFT_INPUT_STREAM_INFO initial_input_info = {0}, input_info = {.cbSize = 16 * 16};
1162 IMFMediaType *mediatype, *mediatype2;
1163 IMFSample *sample, *client_sample;
1164 IMFMediaBuffer *media_buffer;
1165 MFT_INPUT_STREAM_INFO info;
1166 DWORD flags, output_status;
1167 IMFTransform *copier;
1168 HRESULT hr;
1169 LONG ref;
1171 if (!pMFCreateSampleCopierMFT)
1173 win_skip("MFCreateSampleCopierMFT() is not available.\n");
1174 return;
1177 winetest_push_context("copier");
1179 hr = pMFCreateSampleCopierMFT(&copier);
1180 ok(hr == S_OK, "Failed to create sample copier, hr %#lx.\n", hr);
1182 check_interface(copier, &IID_IMFTransform, TRUE);
1183 check_interface(copier, &IID_IMediaObject, FALSE);
1184 check_interface(copier, &IID_IPropertyStore, FALSE);
1185 check_interface(copier, &IID_IPropertyBag, FALSE);
1187 check_mft_optional_methods(copier);
1188 check_mft_get_attributes(copier, expect_transform_attributes, FALSE);
1190 /* Available types. */
1191 hr = IMFTransform_GetInputAvailableType(copier, 0, 0, &mediatype);
1192 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1193 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
1194 IMFMediaType_Release(mediatype);
1196 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype);
1197 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1198 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
1199 IMFMediaType_Release(mediatype);
1201 hr = IMFTransform_GetInputAvailableType(copier, 0, 2, &mediatype);
1202 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
1204 hr = IMFTransform_GetInputAvailableType(copier, 1, 0, &mediatype);
1205 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
1207 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype);
1208 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
1210 hr = IMFTransform_GetOutputAvailableType(copier, 1, 0, &mediatype);
1211 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
1213 check_mft_get_input_current_type(copier, NULL);
1214 check_mft_get_output_current_type(copier, NULL);
1216 hr = MFCreateSample(&sample);
1217 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
1219 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
1220 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
1222 hr = MFCreateMediaType(&mediatype);
1223 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
1225 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
1226 ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr);
1228 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
1229 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1231 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8);
1232 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1234 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
1235 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1237 check_mft_get_input_stream_info(copier, S_OK, &initial_input_info);
1238 check_mft_get_output_stream_info(copier, S_OK, &initial_output_info);
1240 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
1241 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
1243 memset(&info, 0xcd, sizeof(info));
1244 hr = IMFTransform_GetInputStreamInfo(copier, 0, &info);
1245 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
1246 check_member(info, initial_input_info, "%I64d", hnsMaxLatency);
1247 check_member(info, initial_input_info, "%#lx", dwFlags);
1248 todo_wine
1249 check_member(info, initial_input_info, "%#lx", cbSize);
1250 check_member(info, initial_input_info, "%#lx", cbMaxLookahead);
1251 check_member(info, initial_input_info, "%#lx", cbAlignment);
1252 check_mft_get_output_stream_info(copier, S_OK, &output_info);
1254 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
1255 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
1256 IMFMediaType_Release(mediatype2);
1258 check_mft_get_input_current_type(copier, NULL);
1260 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
1261 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
1263 /* Setting input type resets output type. */
1264 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
1265 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1266 IMFMediaType_Release(mediatype2);
1268 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
1269 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
1271 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
1272 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
1274 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype2);
1275 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1276 ok(is_sample_copier_available_type(mediatype2), "Unexpected type.\n");
1277 IMFMediaType_Release(mediatype2);
1279 check_mft_get_input_stream_info(copier, S_OK, &input_info);
1280 check_mft_get_output_stream_info(copier, S_OK, &output_info);
1282 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype2);
1283 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1284 hr = IMFMediaType_IsEqual(mediatype2, mediatype, &flags);
1285 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1286 IMFMediaType_Release(mediatype2);
1288 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
1289 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
1290 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected flags %#lx.\n", flags);
1292 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2);
1293 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
1294 IMFMediaType_Release(mediatype2);
1296 hr = IMFTransform_GetOutputStatus(copier, &flags);
1297 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
1299 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
1300 ok(hr == S_OK, "Failed to set output type, hr %#lx.\n", hr);
1302 hr = IMFTransform_GetOutputStatus(copier, &flags);
1303 ok(hr == S_OK, "Failed to get output status, hr %#lx.\n", hr);
1304 ok(!flags, "Unexpected flags %#lx.\n", flags);
1306 /* Pushing samples. */
1307 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
1308 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
1310 hr = IMFSample_AddBuffer(sample, media_buffer);
1311 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
1312 IMFMediaBuffer_Release(media_buffer);
1314 EXPECT_REF(sample, 1);
1315 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
1316 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
1317 EXPECT_REF(sample, 2);
1319 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
1320 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
1321 ok(!flags, "Unexpected flags %#lx.\n", flags);
1323 hr = IMFTransform_GetOutputStatus(copier, &flags);
1324 ok(hr == S_OK, "Failed to get output status, hr %#lx.\n", hr);
1325 ok(flags == MFT_OUTPUT_STATUS_SAMPLE_READY, "Unexpected flags %#lx.\n", flags);
1327 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
1328 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#lx.\n", hr);
1330 check_mft_get_input_stream_info(copier, S_OK, &input_info);
1331 check_mft_get_output_stream_info(copier, S_OK, &output_info);
1333 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
1334 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
1336 hr = MFCreateSample(&client_sample);
1337 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
1339 hr = IMFSample_AddBuffer(client_sample, media_buffer);
1340 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
1341 IMFMediaBuffer_Release(media_buffer);
1343 hr = check_mft_process_output(copier, client_sample, &output_status);
1344 ok(hr == S_OK, "Failed to get output, hr %#lx.\n", hr);
1345 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
1346 EXPECT_REF(sample, 1);
1348 hr = check_mft_process_output(copier, client_sample, &output_status);
1349 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Failed to get output, hr %#lx.\n", hr);
1350 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
1352 /* Flushing. */
1353 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
1354 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
1355 EXPECT_REF(sample, 2);
1357 hr = IMFTransform_ProcessMessage(copier, MFT_MESSAGE_COMMAND_FLUSH, 0);
1358 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
1360 ref = IMFSample_Release(sample);
1361 ok(ref == 0, "Release returned %ld\n", ref);
1362 ref = IMFSample_Release(client_sample);
1363 ok(ref == 0, "Release returned %ld\n", ref);
1365 ref = IMFTransform_Release(copier);
1366 ok(ref == 0, "Release returned %ld\n", ref);
1367 ref = IMFMediaType_Release(mediatype);
1368 ok(ref == 0, "Release returned %ld\n", ref);
1370 winetest_pop_context();
1373 struct sample_metadata
1375 unsigned int flags;
1376 LONGLONG duration;
1377 LONGLONG time;
1380 static void sample_copier_process(IMFTransform *copier, IMFMediaBuffer *input_buffer,
1381 IMFMediaBuffer *output_buffer, const struct sample_metadata *md)
1383 static const struct sample_metadata zero_md = { 0, ~0u, ~0u };
1384 IMFSample *input_sample, *output_sample;
1385 DWORD flags, output_status;
1386 LONGLONG time;
1387 HRESULT hr;
1388 LONG ref;
1390 hr = MFCreateSample(&input_sample);
1391 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
1393 if (md)
1395 hr = IMFSample_SetSampleFlags(input_sample, md->flags);
1396 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1398 hr = IMFSample_SetSampleTime(input_sample, md->time);
1399 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1401 hr = IMFSample_SetSampleDuration(input_sample, md->duration);
1402 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1405 hr = MFCreateSample(&output_sample);
1406 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
1408 hr = IMFSample_SetSampleFlags(output_sample, ~0u);
1409 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1411 hr = IMFSample_SetSampleTime(output_sample, ~0u);
1412 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1414 hr = IMFSample_SetSampleDuration(output_sample, ~0u);
1415 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1417 hr = IMFSample_AddBuffer(input_sample, input_buffer);
1418 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1420 hr = IMFSample_AddBuffer(output_sample, output_buffer);
1421 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1423 hr = IMFTransform_ProcessInput(copier, 0, input_sample, 0);
1424 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
1426 hr = check_mft_process_output(copier, output_sample, &output_status);
1427 ok(hr == S_OK, "Failed to get output, hr %#lx.\n", hr);
1428 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
1430 if (!md) md = &zero_md;
1432 hr = IMFSample_GetSampleFlags(output_sample, &flags);
1433 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1434 ok(md->flags == flags, "Unexpected flags.\n");
1435 hr = IMFSample_GetSampleTime(output_sample, &time);
1436 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1437 ok(md->time == time, "Unexpected time.\n");
1438 hr = IMFSample_GetSampleDuration(output_sample, &time);
1439 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1440 ok(md->duration == time, "Unexpected duration.\n");
1442 ref = IMFSample_Release(input_sample);
1443 ok(ref == 0, "Release returned %ld\n", ref);
1444 ref = IMFSample_Release(output_sample);
1445 ok(ref == 0, "Release returned %ld\n", ref);
1448 static void test_sample_copier_output_processing(void)
1450 IMFMediaBuffer *input_buffer, *output_buffer;
1451 MFT_OUTPUT_STREAM_INFO output_info;
1452 struct sample_metadata md;
1453 IMFMediaType *mediatype;
1454 IMFTransform *copier;
1455 DWORD max_length;
1456 HRESULT hr;
1457 BYTE *ptr;
1458 LONG ref;
1460 if (!pMFCreateSampleCopierMFT)
1461 return;
1463 hr = pMFCreateSampleCopierMFT(&copier);
1464 ok(hr == S_OK, "Failed to create sample copier, hr %#lx.\n", hr);
1466 /* Configure for 16 x 16 of D3DFMT_X8R8G8B8. */
1467 hr = MFCreateMediaType(&mediatype);
1468 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
1470 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
1471 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1473 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
1474 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1476 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
1477 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1479 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
1480 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
1482 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
1483 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
1485 /* Source and destination are linear buffers, destination is twice as large. */
1486 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
1487 ok(hr == S_OK, "Failed to get output info, hr %#lx.\n", hr);
1489 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &output_buffer);
1490 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
1492 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
1493 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1494 memset(ptr, 0xcc, max_length);
1495 hr = IMFMediaBuffer_Unlock(output_buffer);
1496 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1498 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &input_buffer);
1499 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
1501 hr = IMFMediaBuffer_Lock(input_buffer, &ptr, &max_length, NULL);
1502 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1503 memset(ptr, 0xaa, max_length);
1504 hr = IMFMediaBuffer_Unlock(input_buffer);
1505 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1506 hr = IMFMediaBuffer_SetCurrentLength(input_buffer, 4);
1507 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1509 sample_copier_process(copier, input_buffer, output_buffer, NULL);
1511 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
1512 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1513 ok(ptr[0] == 0xaa && ptr[4] == 0xcc, "Unexpected buffer contents.\n");
1515 hr = IMFMediaBuffer_Unlock(output_buffer);
1516 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1518 md.flags = 123;
1519 md.time = 10;
1520 md.duration = 2;
1521 sample_copier_process(copier, input_buffer, output_buffer, &md);
1523 ref = IMFMediaBuffer_Release(input_buffer);
1524 ok(ref == 0, "Release returned %ld\n", ref);
1525 ref = IMFMediaBuffer_Release(output_buffer);
1526 ok(ref == 0, "Release returned %ld\n", ref);
1528 ref = IMFTransform_Release(copier);
1529 ok(ref == 0, "Release returned %ld\n", ref);
1530 ref = IMFMediaType_Release(mediatype);
1531 ok(ref == 0, "Release returned %ld\n", ref);
1534 static IMFSample *create_sample(const BYTE *data, ULONG size)
1536 IMFMediaBuffer *media_buffer;
1537 IMFSample *sample;
1538 DWORD length;
1539 BYTE *buffer;
1540 HRESULT hr;
1541 ULONG ret;
1543 hr = MFCreateSample(&sample);
1544 ok(hr == S_OK, "MFCreateSample returned %#lx\n", hr);
1545 hr = MFCreateMemoryBuffer(size, &media_buffer);
1546 ok(hr == S_OK, "MFCreateMemoryBuffer returned %#lx\n", hr);
1547 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
1548 ok(hr == S_OK, "Lock returned %#lx\n", hr);
1549 ok(length == 0, "got length %lu\n", length);
1550 if (!data) memset(buffer, 0xcd, size);
1551 else memcpy(buffer, data, size);
1552 hr = IMFMediaBuffer_Unlock(media_buffer);
1553 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
1554 hr = IMFMediaBuffer_SetCurrentLength(media_buffer, data ? size : 0);
1555 ok(hr == S_OK, "SetCurrentLength returned %#lx\n", hr);
1556 hr = IMFSample_AddBuffer(sample, media_buffer);
1557 ok(hr == S_OK, "AddBuffer returned %#lx\n", hr);
1558 ret = IMFMediaBuffer_Release(media_buffer);
1559 ok(ret == 1, "Release returned %lu\n", ret);
1561 return sample;
1564 static const BYTE aac_codec_data[14] = {0x00,0x00,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x08};
1566 static void test_aac_encoder(void)
1568 const GUID *const class_id = &CLSID_AACMFTEncoder;
1569 const struct transform_info expect_mft_info =
1571 .name = L"Microsoft AAC Audio Encoder MFT",
1572 .major_type = &MFMediaType_Audio,
1573 .inputs =
1575 {.subtype = &MFAudioFormat_PCM},
1577 .outputs =
1579 {.subtype = &MFAudioFormat_AAC},
1583 static const struct attribute_desc input_type_desc[] =
1585 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
1586 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM, .required = TRUE),
1587 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1, .required = TRUE),
1588 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
1589 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .required = TRUE),
1590 {0},
1592 const struct attribute_desc output_type_desc[] =
1594 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
1595 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC, .required = TRUE),
1596 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1, .required = TRUE),
1597 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
1598 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .required = TRUE),
1599 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 12000, .required = TRUE),
1600 {0},
1603 static const struct attribute_desc expect_input_type_desc[] =
1605 ATTR_GUID(MF_MT_AM_FORMAT_TYPE, FORMAT_WaveFormatEx),
1606 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1607 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1608 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
1609 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1610 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2),
1611 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1612 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 * 2),
1613 ATTR_UINT32(MF_MT_AVG_BITRATE, 44100 * 2 * 8),
1614 ATTR_UINT32(MF_MT_COMPRESSED, 0),
1615 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
1616 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
1617 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
1618 {0},
1620 const struct attribute_desc expect_output_type_desc[] =
1622 ATTR_GUID(MF_MT_AM_FORMAT_TYPE, FORMAT_WaveFormatEx),
1623 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1624 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC),
1625 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
1626 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1627 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
1628 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1629 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 12000),
1630 ATTR_UINT32(MF_MT_AVG_BITRATE, 96000),
1631 ATTR_UINT32(MF_MT_COMPRESSED, 1),
1632 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 0),
1633 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
1634 ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 41),
1635 ATTR_UINT32(MF_MT_AAC_PAYLOAD_TYPE, 0),
1636 ATTR_BLOB(MF_MT_USER_DATA, aac_codec_data, sizeof(aac_codec_data)),
1637 {0},
1639 const MFT_OUTPUT_STREAM_INFO initial_output_info = {0}, output_info = {.cbSize = 0x600};
1640 const MFT_INPUT_STREAM_INFO input_info = {0};
1642 const struct buffer_desc output_buffer_desc[] =
1644 {.length = -1 /* variable */},
1646 const struct attribute_desc output_sample_attributes[] =
1648 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
1649 {0},
1651 const struct sample_desc output_sample_desc[] =
1654 .repeat_count = 88,
1655 .attributes = output_sample_attributes,
1656 .sample_time = 0, .sample_duration = 113823,
1657 .buffer_count = 1, .buffers = output_buffer_desc,
1661 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_AAC};
1662 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_PCM};
1663 IMFSample *input_sample, *output_sample;
1664 IMFCollection *output_samples;
1665 ULONG i, ret, audio_data_len;
1666 DWORD length, output_status;
1667 IMFTransform *transform;
1668 const BYTE *audio_data;
1669 HRESULT hr;
1670 LONG ref;
1672 hr = CoInitialize(NULL);
1673 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
1675 winetest_push_context("aacenc");
1677 if (!check_mft_enum(MFT_CATEGORY_AUDIO_ENCODER, &input_type, &output_type, class_id))
1678 goto failed;
1679 check_mft_get_info(class_id, &expect_mft_info);
1681 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
1682 &IID_IMFTransform, (void **)&transform)))
1683 goto failed;
1685 check_interface(transform, &IID_IMFTransform, TRUE);
1686 check_interface(transform, &IID_IMediaObject, FALSE);
1687 check_interface(transform, &IID_IPropertyStore, FALSE);
1688 check_interface(transform, &IID_IPropertyBag, FALSE);
1690 check_mft_optional_methods(transform);
1691 check_mft_get_attributes(transform, NULL, FALSE);
1692 check_mft_get_input_stream_info(transform, S_OK, &input_info);
1693 check_mft_get_output_stream_info(transform, S_OK, &initial_output_info);
1695 check_mft_set_output_type_required(transform, output_type_desc);
1696 check_mft_set_output_type(transform, output_type_desc, S_OK);
1697 check_mft_get_output_current_type(transform, expect_output_type_desc);
1699 check_mft_set_input_type_required(transform, input_type_desc);
1700 check_mft_set_input_type(transform, input_type_desc);
1701 check_mft_get_input_current_type(transform, expect_input_type_desc);
1703 check_mft_get_input_stream_info(transform, S_OK, &input_info);
1704 check_mft_get_output_stream_info(transform, S_OK, &output_info);
1706 if (!has_video_processor)
1708 win_skip("Skipping AAC encoder tests on Win7\n");
1709 goto done;
1712 load_resource(L"audiodata.bin", &audio_data, &audio_data_len);
1713 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
1715 input_sample = create_sample(audio_data, audio_data_len);
1716 hr = IMFSample_SetSampleTime(input_sample, 0);
1717 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
1718 hr = IMFSample_SetSampleDuration(input_sample, 10000000);
1719 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
1720 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
1721 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
1722 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
1723 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
1724 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
1725 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
1726 ref = IMFSample_Release(input_sample);
1727 ok(ref <= 1, "Release returned %ld\n", ref);
1729 hr = MFCreateCollection(&output_samples);
1730 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
1732 output_sample = create_sample(NULL, output_info.cbSize);
1733 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
1735 winetest_push_context("%lu", i);
1736 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
1737 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
1738 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
1739 ref = IMFSample_Release(output_sample);
1740 ok(ref == 1, "Release returned %ld\n", ref);
1741 output_sample = create_sample(NULL, output_info.cbSize);
1742 winetest_pop_context();
1744 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
1745 ret = IMFSample_Release(output_sample);
1746 ok(ret == 0, "Release returned %lu\n", ret);
1747 ok(i == 88, "got %lu output samples\n", i);
1749 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"aacencdata.bin");
1750 ok(ret == 0, "got %lu%% diff\n", ret);
1751 IMFCollection_Release(output_samples);
1753 output_sample = create_sample(NULL, output_info.cbSize);
1754 hr = check_mft_process_output(transform, output_sample, &output_status);
1755 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
1756 hr = IMFSample_GetTotalLength(output_sample, &length);
1757 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
1758 ok(length == 0, "got length %lu\n", length);
1759 ret = IMFSample_Release(output_sample);
1760 ok(ret == 0, "Release returned %lu\n", ret);
1762 done:
1763 ret = IMFTransform_Release(transform);
1764 ok(ret == 0, "Release returned %lu\n", ret);
1766 failed:
1767 winetest_pop_context();
1768 CoUninitialize();
1771 static void test_aac_decoder(void)
1773 const GUID *const class_id = &CLSID_MSAACDecMFT;
1774 const struct transform_info expect_mft_info =
1776 .name = L"Microsoft AAC Audio Decoder MFT",
1777 .major_type = &MFMediaType_Audio,
1778 .inputs =
1780 {.subtype = &MFAudioFormat_AAC},
1781 {.subtype = &MFAudioFormat_RAW_AAC1},
1782 {.subtype = &MFAudioFormat_ADTS, .broken = TRUE /* <= w8 */},
1784 .outputs =
1786 {.subtype = &MFAudioFormat_Float},
1787 {.subtype = &MFAudioFormat_PCM},
1791 static const struct attribute_desc expect_input_attributes[] =
1793 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1794 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
1795 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
1796 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 6),
1797 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 24),
1798 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
1799 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 1152000),
1800 {0},
1802 static const media_type_desc expect_available_inputs[] =
1805 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC),
1806 ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 0),
1807 ATTR_UINT32(MF_MT_AAC_PAYLOAD_TYPE, 0),
1808 /* MF_MT_USER_DATA with some AAC codec data */
1811 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_RAW_AAC1),
1814 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC),
1815 ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 0),
1816 ATTR_UINT32(MF_MT_AAC_PAYLOAD_TYPE, 1),
1817 /* MF_MT_USER_DATA with some AAC codec data */
1820 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC),
1821 ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 0),
1822 ATTR_UINT32(MF_MT_AAC_PAYLOAD_TYPE, 3),
1823 /* MF_MT_USER_DATA with some AAC codec data */
1826 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_ADTS),
1829 static const struct attribute_desc expect_output_attributes[] =
1831 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1832 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
1833 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1834 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
1835 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
1836 {0},
1838 static const media_type_desc expect_available_outputs[] =
1841 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1842 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
1843 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
1844 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
1845 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4 * 44100),
1848 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1849 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1850 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
1851 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2),
1852 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * 44100),
1855 const struct attribute_desc expect_transform_attributes[] =
1857 ATTR_UINT32(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, !has_video_processor /* 1 on W7 */, .todo = TRUE),
1858 /* more AAC decoder specific attributes from CODECAPI */
1859 {0},
1861 const struct attribute_desc input_type_desc[] =
1863 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
1864 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC, .required = TRUE),
1865 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .required = TRUE),
1866 ATTR_BLOB(MF_MT_USER_DATA, aac_codec_data, sizeof(aac_codec_data), .required = TRUE),
1867 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
1868 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
1869 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 12000),
1870 ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 41),
1871 ATTR_UINT32(MF_MT_AAC_PAYLOAD_TYPE, 0),
1872 {0},
1874 static const struct attribute_desc output_type_desc[] =
1876 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
1877 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM, .required = TRUE),
1878 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1, .required = TRUE),
1879 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
1880 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .required = TRUE),
1881 {0},
1883 const MFT_OUTPUT_STREAM_INFO output_info =
1885 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES,
1886 .cbSize = 0xc000,
1888 const MFT_INPUT_STREAM_INFO input_info =
1890 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
1891 MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE | MFT_INPUT_STREAM_HOLDS_BUFFERS,
1894 const struct buffer_desc output_buffer_desc[] =
1896 {.length = 0x800},
1898 const struct attribute_desc output_sample_attributes[] =
1900 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
1901 {0},
1903 const struct sample_desc output_sample_desc[] =
1906 .attributes = output_sample_attributes + (has_video_processor ? 0 : 1) /* MFSampleExtension_CleanPoint missing on Win7 */,
1907 .sample_time = 0, .sample_duration = 232200,
1908 .buffer_count = 1, .buffers = output_buffer_desc,
1912 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_Float};
1913 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_AAC};
1914 IMFSample *input_sample, *output_sample;
1915 ULONG i, ret, ref, aacenc_data_len;
1916 IMFCollection *output_samples;
1917 DWORD length, output_status;
1918 IMFMediaType *media_type;
1919 IMFTransform *transform;
1920 const BYTE *aacenc_data;
1921 HRESULT hr;
1923 hr = CoInitialize(NULL);
1924 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
1926 winetest_push_context("aacdec");
1928 if (!check_mft_enum(MFT_CATEGORY_AUDIO_DECODER, &input_type, &output_type, class_id))
1929 goto failed;
1930 check_mft_get_info(class_id, &expect_mft_info);
1932 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
1933 &IID_IMFTransform, (void **)&transform)))
1934 goto failed;
1936 check_interface(transform, &IID_IMFTransform, TRUE);
1937 check_interface(transform, &IID_IMediaObject, FALSE);
1938 check_interface(transform, &IID_IPropertyStore, FALSE);
1939 check_interface(transform, &IID_IPropertyBag, FALSE);
1941 check_mft_optional_methods(transform);
1942 check_mft_get_attributes(transform, expect_transform_attributes, FALSE);
1943 check_mft_get_input_stream_info(transform, S_OK, &input_info);
1944 check_mft_get_output_stream_info(transform, S_OK, &output_info);
1946 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
1947 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
1949 i = -1;
1950 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
1952 winetest_push_context("in %lu", i);
1953 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
1954 check_media_type(media_type, expect_input_attributes, -1);
1955 check_media_type(media_type, expect_available_inputs[i], -1);
1956 ret = IMFMediaType_Release(media_type);
1957 ok(ret <= 1, "Release returned %lu\n", ret);
1958 winetest_pop_context();
1960 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
1961 ok(i == ARRAY_SIZE(expect_available_inputs)
1962 || broken(i == 2) /* w7 */ || broken(i == 4) /* w8 */,
1963 "%lu input media types\n", i);
1965 /* setting output media type first doesn't work */
1966 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
1967 check_mft_get_output_current_type(transform, NULL);
1969 check_mft_set_input_type_required(transform, input_type_desc);
1970 check_mft_set_input_type(transform, input_type_desc);
1971 check_mft_get_input_current_type(transform, input_type_desc);
1973 /* check new output media types */
1975 i = -1;
1976 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
1978 winetest_push_context("out %lu", i);
1979 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
1980 check_media_type(media_type, expect_output_attributes, -1);
1981 check_media_type(media_type, expect_available_outputs[i], -1);
1982 ret = IMFMediaType_Release(media_type);
1983 ok(ret <= 1, "Release returned %lu\n", ret);
1984 winetest_pop_context();
1986 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
1987 ok(i == ARRAY_SIZE(expect_available_outputs), "%lu input media types\n", i);
1989 check_mft_set_output_type_required(transform, output_type_desc);
1990 check_mft_set_output_type(transform, output_type_desc, S_OK);
1991 check_mft_get_output_current_type(transform, output_type_desc);
1993 check_mft_get_input_stream_info(transform, S_OK, &input_info);
1994 check_mft_get_output_stream_info(transform, S_OK, &output_info);
1996 load_resource(L"aacencdata.bin", &aacenc_data, &aacenc_data_len);
1997 ok(aacenc_data_len == 24861, "got length %lu\n", aacenc_data_len);
1999 input_sample = create_sample(aacenc_data + sizeof(DWORD), *(DWORD *)aacenc_data);
2000 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2001 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2002 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2003 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2005 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
2006 * IMFTransform_ProcessOutput needs a sample or returns MF_E_TRANSFORM_NEED_MORE_INPUT */
2008 hr = check_mft_process_output(transform, NULL, &output_status);
2009 ok(hr == E_INVALIDARG, "ProcessOutput returned %#lx\n", hr);
2010 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
2011 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2012 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2014 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
2015 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
2016 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2017 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2019 hr = MFCreateCollection(&output_samples);
2020 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
2022 output_sample = create_sample(NULL, output_info.cbSize);
2023 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
2025 winetest_push_context("%lu", i);
2026 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
2027 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
2028 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
2029 ref = IMFSample_Release(output_sample);
2030 ok(ref == 1, "Release returned %ld\n", ref);
2031 output_sample = create_sample(NULL, output_info.cbSize);
2032 winetest_pop_context();
2034 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2035 ok(output_status == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE, "got output[0].dwStatus %#lx\n", output_status);
2036 ret = IMFSample_Release(output_sample);
2037 ok(ret == 0, "Release returned %lu\n", ret);
2038 ok(i == 1, "got %lu output samples\n", i);
2040 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"aacdecdata.bin");
2041 ok(ret == 0, "got %lu%% diff\n", ret);
2042 IMFCollection_Release(output_samples);
2044 output_sample = create_sample(NULL, output_info.cbSize);
2045 hr = check_mft_process_output(transform, output_sample, &output_status);
2046 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2047 ok(output_status == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE, "got output[0].dwStatus %#lx\n", output_status);
2048 hr = IMFSample_GetTotalLength(output_sample, &length);
2049 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
2050 ok(length == 0, "got length %lu\n", length);
2051 ret = IMFSample_Release(output_sample);
2052 ok(ret == 0, "Release returned %lu\n", ret);
2054 ret = IMFSample_Release(input_sample);
2055 ok(ret == 0, "Release returned %lu\n", ret);
2056 ret = IMFTransform_Release(transform);
2057 ok(ret == 0, "Release returned %lu\n", ret);
2059 failed:
2060 winetest_pop_context();
2061 CoUninitialize();
2064 static const BYTE wma_codec_data[10] = {0, 0x44, 0, 0, 0x17, 0, 0, 0, 0, 0};
2065 static const ULONG wmaenc_block_size = 1487;
2066 static const ULONG wmadec_block_size = 0x2000;
2068 static void test_wma_encoder(void)
2070 const GUID *const class_id = &CLSID_CWMAEncMediaObject;
2071 const struct transform_info expect_mft_info =
2073 .name = L"WMAudio Encoder MFT",
2074 .major_type = &MFMediaType_Audio,
2075 .inputs =
2077 {.subtype = &MFAudioFormat_PCM},
2078 {.subtype = &MFAudioFormat_Float},
2080 .outputs =
2082 {.subtype = &MFAudioFormat_WMAudioV8},
2083 {.subtype = &MFAudioFormat_WMAudioV9},
2084 {.subtype = &MFAudioFormat_WMAudio_Lossless},
2087 const struct transform_info expect_dmo_info =
2089 .name = L"WMAudio Encoder DMO",
2090 .major_type = &MEDIATYPE_Audio,
2091 .inputs =
2093 {.subtype = &MEDIASUBTYPE_PCM},
2095 .outputs =
2097 {.subtype = &MEDIASUBTYPE_WMAUDIO2},
2098 {.subtype = &MEDIASUBTYPE_WMAUDIO3},
2099 {.subtype = &MEDIASUBTYPE_WMAUDIO_LOSSLESS},
2103 static const struct attribute_desc input_type_desc[] =
2105 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2106 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float, .required = TRUE),
2107 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
2108 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32, .required = TRUE),
2109 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
2110 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2 * (32 / 8), .required = TRUE),
2111 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * (32 / 8) * 22050, .required = TRUE),
2112 {0},
2114 const struct attribute_desc output_type_desc[] =
2116 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2117 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8, .required = TRUE),
2118 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
2119 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
2120 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003, .required = TRUE),
2121 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size, .required = TRUE),
2122 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data), .required = TRUE),
2123 {0},
2125 static const struct attribute_desc expect_input_type_desc[] =
2127 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2128 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
2129 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
2130 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2131 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
2132 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
2133 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 22050 * 8),
2134 ATTR_UINT32(MF_MT_AUDIO_CHANNEL_MASK, 3),
2135 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2136 {0},
2138 const struct attribute_desc expect_output_type_desc[] =
2140 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2141 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
2142 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2143 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
2144 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003),
2145 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size),
2146 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)),
2147 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2148 {0},
2150 const MFT_OUTPUT_STREAM_INFO output_info =
2152 .cbSize = wmaenc_block_size,
2153 .cbAlignment = 1,
2155 const MFT_INPUT_STREAM_INFO input_info =
2157 .hnsMaxLatency = 19969161,
2158 .cbSize = 8,
2159 .cbAlignment = 1,
2162 const struct buffer_desc output_buffer_desc[] =
2164 {.length = wmaenc_block_size},
2166 const struct attribute_desc output_sample_attributes[] =
2168 ATTR_UINT32(mft_output_sample_incomplete, 1),
2169 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
2170 {0},
2172 const struct sample_desc output_sample_desc[] =
2175 .attributes = output_sample_attributes,
2176 .sample_time = 0, .sample_duration = 3250794,
2177 .buffer_count = 1, .buffers = output_buffer_desc,
2180 .attributes = output_sample_attributes,
2181 .sample_time = 3250794, .sample_duration = 3715193,
2182 .buffer_count = 1, .buffers = output_buffer_desc,
2185 .attributes = output_sample_attributes,
2186 .sample_time = 6965986, .sample_duration = 3366893,
2187 .buffer_count = 1, .buffers = output_buffer_desc,
2191 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8};
2192 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_Float};
2193 IMFSample *input_sample, *output_sample;
2194 IMFCollection *output_samples;
2195 DWORD length, output_status;
2196 IMFMediaType *media_type;
2197 IMFTransform *transform;
2198 const BYTE *audio_data;
2199 ULONG audio_data_len;
2200 ULONG i, ret;
2201 HRESULT hr;
2202 LONG ref;
2204 hr = CoInitialize(NULL);
2205 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
2207 winetest_push_context("wmaenc");
2209 if (!check_mft_enum(MFT_CATEGORY_AUDIO_ENCODER, &input_type, &output_type, class_id))
2210 goto failed;
2211 check_mft_get_info(class_id, &expect_mft_info);
2212 check_dmo_get_info(class_id, &expect_dmo_info);
2214 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
2215 &IID_IMFTransform, (void **)&transform)))
2216 goto failed;
2218 check_interface(transform, &IID_IMFTransform, TRUE);
2219 check_interface(transform, &IID_IMediaObject, TRUE);
2220 check_interface(transform, &IID_IPropertyStore, TRUE);
2221 check_interface(transform, &IID_IPropertyBag, TRUE);
2223 check_mft_optional_methods(transform);
2224 check_mft_get_attributes(transform, NULL, FALSE);
2225 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
2226 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
2228 check_mft_set_input_type_required(transform, input_type_desc);
2230 hr = MFCreateMediaType(&media_type);
2231 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
2232 init_media_type(media_type, input_type_desc, -1);
2233 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
2234 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
2235 ret = IMFMediaType_Release(media_type);
2236 ok(ret == 0, "Release returned %lu\n", ret);
2238 check_mft_set_output_type_required(transform, output_type_desc);
2239 check_mft_set_output_type(transform, output_type_desc, S_OK);
2240 check_mft_get_output_current_type(transform, expect_output_type_desc);
2242 check_mft_set_input_type_required(transform, input_type_desc);
2243 check_mft_set_input_type(transform, input_type_desc);
2244 check_mft_get_input_current_type(transform, expect_input_type_desc);
2246 check_mft_get_input_stream_info(transform, S_OK, &input_info);
2247 check_mft_get_output_stream_info(transform, S_OK, &output_info);
2249 load_resource(L"audiodata.bin", &audio_data, &audio_data_len);
2250 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
2252 input_sample = create_sample(audio_data, audio_data_len);
2253 hr = IMFSample_SetSampleTime(input_sample, 0);
2254 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
2255 hr = IMFSample_SetSampleDuration(input_sample, 10000000);
2256 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
2257 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2258 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2259 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
2260 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
2261 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2262 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2263 ref = IMFSample_Release(input_sample);
2264 ok(ref <= 1, "Release returned %ld\n", ref);
2266 hr = MFCreateCollection(&output_samples);
2267 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
2269 output_sample = create_sample(NULL, output_info.cbSize);
2270 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
2272 winetest_push_context("%lu", i);
2273 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
2274 ok(output_status == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE, "got output[0].dwStatus %#lx\n", output_status);
2275 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
2276 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
2277 ref = IMFSample_Release(output_sample);
2278 ok(ref == 1, "Release returned %ld\n", ref);
2279 output_sample = create_sample(NULL, output_info.cbSize);
2280 winetest_pop_context();
2282 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2283 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
2284 ret = IMFSample_Release(output_sample);
2285 ok(ret == 0, "Release returned %lu\n", ret);
2286 ok(i == 3, "got %lu output samples\n", i);
2288 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"wmaencdata.bin");
2289 ok(ret == 0, "got %lu%% diff\n", ret);
2290 IMFCollection_Release(output_samples);
2292 output_sample = create_sample(NULL, output_info.cbSize);
2293 hr = check_mft_process_output(transform, output_sample, &output_status);
2294 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2295 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
2296 hr = IMFSample_GetTotalLength(output_sample, &length);
2297 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
2298 ok(length == 0, "got length %lu\n", length);
2299 ret = IMFSample_Release(output_sample);
2300 ok(ret == 0, "Release returned %lu\n", ret);
2302 ret = IMFTransform_Release(transform);
2303 ok(ret == 0, "Release returned %lu\n", ret);
2305 failed:
2306 winetest_pop_context();
2307 CoUninitialize();
2310 static void test_wma_decoder(void)
2312 const GUID *const class_id = &CLSID_CWMADecMediaObject;
2313 const struct transform_info expect_mft_info =
2315 .name = L"WMAudio Decoder MFT",
2316 .major_type = &MFMediaType_Audio,
2317 .inputs =
2319 {.subtype = &MEDIASUBTYPE_MSAUDIO1},
2320 {.subtype = &MFAudioFormat_WMAudioV8},
2321 {.subtype = &MFAudioFormat_WMAudioV9},
2322 {.subtype = &MFAudioFormat_WMAudio_Lossless},
2324 .outputs =
2326 {.subtype = &MFAudioFormat_PCM},
2327 {.subtype = &MFAudioFormat_Float},
2330 const struct transform_info expect_dmo_info =
2332 .name = L"WMAudio Decoder DMO",
2333 .major_type = &MEDIATYPE_Audio,
2334 .inputs =
2336 {.subtype = &MEDIASUBTYPE_MSAUDIO1},
2337 {.subtype = &MEDIASUBTYPE_WMAUDIO2},
2338 {.subtype = &MEDIASUBTYPE_WMAUDIO3},
2339 {.subtype = &MEDIASUBTYPE_WMAUDIO_LOSSLESS},
2341 .outputs =
2343 {.subtype = &MEDIASUBTYPE_PCM},
2344 {.subtype = &MEDIASUBTYPE_IEEE_FLOAT},
2348 static const media_type_desc expect_available_inputs[] =
2351 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2352 ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_MSAUDIO1),
2353 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2356 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2357 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
2358 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2361 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2362 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV9),
2363 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2366 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2367 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudio_Lossless),
2368 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2371 static const media_type_desc expect_available_outputs[] =
2374 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2375 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
2376 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
2377 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2378 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
2379 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
2380 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
2381 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2382 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2383 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2386 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2387 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2388 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
2389 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2390 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
2391 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
2392 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
2393 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2394 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2395 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2399 const struct attribute_desc input_type_desc[] =
2401 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2402 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8, .required = TRUE),
2403 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data), .required = TRUE),
2404 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size, .required = TRUE),
2405 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
2406 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
2407 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003), /* not required by SetInputType, but needed for the transform to work */
2408 {0},
2410 static const struct attribute_desc output_type_desc[] =
2412 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2413 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM, .required = TRUE),
2414 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
2415 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
2416 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
2417 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2 * (16 / 8), .required = TRUE),
2418 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * (16 / 8) * 22050, .required = TRUE),
2419 {0},
2421 const struct attribute_desc expect_input_type_desc[] =
2423 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2424 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
2425 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)),
2426 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size),
2427 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
2428 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2429 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003),
2430 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2431 {0},
2433 static const struct attribute_desc expect_output_type_desc[] =
2435 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2436 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2437 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 22050 * 4),
2438 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
2439 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2440 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
2441 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
2442 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2443 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2444 {0},
2446 const MFT_INPUT_STREAM_INFO input_info =
2448 .cbSize = wmaenc_block_size,
2449 .cbAlignment = 1,
2451 const MFT_OUTPUT_STREAM_INFO output_info =
2453 .cbSize = wmadec_block_size,
2454 .cbAlignment = 1,
2457 const struct buffer_desc output_buffer_desc[] =
2459 {.length = wmadec_block_size, .compare = compare_pcm16},
2460 {.length = wmadec_block_size / 2, .compare = compare_pcm16, .todo_length = TRUE},
2462 const struct attribute_desc output_sample_attributes[] =
2464 ATTR_UINT32(mft_output_sample_incomplete, 1),
2465 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
2466 {0},
2468 const struct attribute_desc output_sample_attributes_todo[] =
2470 ATTR_UINT32(mft_output_sample_incomplete, 1, .todo = TRUE),
2471 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
2472 {0},
2474 struct sample_desc output_sample_desc[] =
2477 .attributes = output_sample_attributes + 0,
2478 .sample_time = 0, .sample_duration = 928798,
2479 .buffer_count = 1, .buffers = output_buffer_desc + 0, .repeat_count = 1,
2482 .attributes = output_sample_attributes + 0,
2483 .sample_time = 1857596, .sample_duration = 928798,
2484 .buffer_count = 1, .buffers = output_buffer_desc + 0,
2487 .attributes = output_sample_attributes + 1, /* not MFT_OUTPUT_DATA_BUFFER_INCOMPLETE */
2488 .sample_time = 2786394, .sample_duration = 464399,
2489 .buffer_count = 1, .buffers = output_buffer_desc + 1, .todo_length = TRUE,
2493 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8};
2494 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_Float};
2495 IUnknown *unknown, *tmp_unknown, outer = {&test_unk_vtbl};
2496 IMFSample *input_sample, *output_sample;
2497 IMFCollection *output_samples;
2498 DWORD length, output_status;
2499 IMediaObject *media_object;
2500 IPropertyBag *property_bag;
2501 IMFMediaType *media_type;
2502 IMFTransform *transform;
2503 const BYTE *wmaenc_data;
2504 ULONG wmaenc_data_len;
2505 ULONG i, ret, ref;
2506 HRESULT hr;
2508 hr = CoInitialize(NULL);
2509 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
2511 winetest_push_context("wmadec");
2513 if (!check_mft_enum(MFT_CATEGORY_AUDIO_DECODER, &input_type, &output_type, class_id))
2514 goto failed;
2515 check_mft_get_info(class_id, &expect_mft_info);
2516 check_dmo_get_info(class_id, &expect_dmo_info);
2518 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
2519 &IID_IMFTransform, (void **)&transform)))
2520 goto failed;
2522 check_interface(transform, &IID_IMFTransform, TRUE);
2523 check_interface(transform, &IID_IMediaObject, TRUE);
2524 todo_wine
2525 check_interface(transform, &IID_IPropertyStore, TRUE);
2526 check_interface(transform, &IID_IPropertyBag, TRUE);
2528 check_mft_optional_methods(transform);
2529 check_mft_get_attributes(transform, NULL, FALSE);
2530 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
2531 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
2533 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
2534 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
2536 i = -1;
2537 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
2539 winetest_push_context("in %lu", i);
2540 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
2541 check_media_type(media_type, expect_available_inputs[i], -1);
2542 ret = IMFMediaType_Release(media_type);
2543 ok(ret == 0, "Release returned %lu\n", ret);
2544 winetest_pop_context();
2546 todo_wine
2547 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
2548 todo_wine
2549 ok(i == 4, "%lu input media types\n", i);
2551 /* setting output media type first doesn't work */
2552 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
2553 check_mft_get_output_current_type_(transform, NULL, TRUE, FALSE);
2555 check_mft_set_input_type_required(transform, input_type_desc);
2556 check_mft_set_input_type(transform, input_type_desc);
2557 check_mft_get_input_current_type_(transform, expect_input_type_desc, TRUE, FALSE);
2559 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
2560 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
2562 /* check new output media types */
2564 i = -1;
2565 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
2567 winetest_push_context("out %lu", i);
2568 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
2569 check_media_type(media_type, expect_available_outputs[i], -1);
2570 ret = IMFMediaType_Release(media_type);
2571 ok(ret == 0, "Release returned %lu\n", ret);
2572 winetest_pop_context();
2574 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
2575 ok(i == 2, "%lu output media types\n", i);
2577 check_mft_set_output_type_required(transform, output_type_desc);
2578 check_mft_set_output_type(transform, output_type_desc, S_OK);
2579 check_mft_get_output_current_type_(transform, expect_output_type_desc, TRUE, FALSE);
2581 check_mft_get_input_stream_info(transform, S_OK, &input_info);
2582 check_mft_get_output_stream_info(transform, S_OK, &output_info);
2584 load_resource(L"wmaencdata.bin", &wmaenc_data, &wmaenc_data_len);
2585 ok(wmaenc_data_len % wmaenc_block_size == 0, "got length %lu\n", wmaenc_data_len);
2587 input_sample = create_sample(wmaenc_data, wmaenc_block_size / 2);
2588 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2589 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2590 ret = IMFSample_Release(input_sample);
2591 ok(ret == 0, "Release returned %lu\n", ret);
2592 input_sample = create_sample(wmaenc_data, wmaenc_block_size + 1);
2593 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2594 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2595 ret = IMFSample_Release(input_sample);
2596 ok(ret == 0, "Release returned %lu\n", ret);
2597 input_sample = create_sample(wmaenc_data, wmaenc_block_size);
2598 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2599 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2600 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2601 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2602 ret = IMFSample_Release(input_sample);
2603 ok(ret == 1, "Release returned %lu\n", ret);
2605 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
2606 * IMFTransform_ProcessOutput needs a sample or returns MF_E_TRANSFORM_NEED_MORE_INPUT */
2608 hr = check_mft_process_output(transform, NULL, &output_status);
2609 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2610 ok(output_status == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE
2611 || broken(output_status == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
2612 "got output[0].dwStatus %#lx\n", output_status);
2614 input_sample = create_sample(wmaenc_data, wmaenc_block_size);
2615 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2616 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2617 ret = IMFSample_Release(input_sample);
2618 ok(ret == 0, "Release returned %lu\n", ret);
2620 hr = check_mft_process_output(transform, NULL, &output_status);
2621 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2622 ok(output_status == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE
2623 || broken(output_status == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
2624 "got output[0].dwStatus %#lx\n", output_status);
2626 hr = MFCreateCollection(&output_samples);
2627 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
2629 output_sample = create_sample(NULL, output_info.cbSize);
2630 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
2632 winetest_push_context("%lu", i);
2633 ok(!(output_status & ~MFT_OUTPUT_DATA_BUFFER_INCOMPLETE), "got output[0].dwStatus %#lx\n", output_status);
2634 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
2635 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
2636 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
2637 ref = IMFSample_Release(output_sample);
2638 ok(ref == 1, "Release returned %ld\n", ref);
2639 output_sample = create_sample(NULL, output_info.cbSize);
2640 winetest_pop_context();
2642 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2643 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
2644 ret = IMFSample_Release(output_sample);
2645 ok(ret == 0, "Release returned %lu\n", ret);
2646 todo_wine_if(i == 3) /* wmadec output depends on ffmpeg version used */
2647 ok(i == 4, "got %lu output samples\n", i);
2649 if (!strcmp(winetest_platform, "wine") && i == 3)
2650 output_sample_desc[1].attributes = output_sample_attributes_todo;
2652 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"wmadecdata.bin");
2653 todo_wine_if(ret > 0 && ret <= 10) /* ffmpeg sometimes offsets the decoded data */
2654 ok(ret == 0, "got %lu%% diff\n", ret);
2655 IMFCollection_Release(output_samples);
2657 output_sample = create_sample(NULL, output_info.cbSize);
2658 hr = check_mft_process_output(transform, output_sample, &output_status);
2659 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2660 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
2661 hr = IMFSample_GetTotalLength(output_sample, &length);
2662 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
2663 ok(length == 0, "got length %lu\n", length);
2664 ret = IMFSample_Release(output_sample);
2665 ok(ret == 0, "Release returned %lu\n", ret);
2667 input_sample = create_sample(wmaenc_data, wmaenc_block_size);
2668 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2669 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2671 ret = IMFTransform_Release(transform);
2672 ok(ret == 0, "Release returned %lu\n", ret);
2673 ret = IMFSample_Release(input_sample);
2674 ok(ret == 0, "Release returned %lu\n", ret);
2676 hr = CoCreateInstance( &CLSID_CWMADecMediaObject, &outer, CLSCTX_INPROC_SERVER, &IID_IUnknown,
2677 (void **)&unknown );
2678 ok( hr == S_OK, "CoCreateInstance returned %#lx\n", hr );
2679 hr = IUnknown_QueryInterface( unknown, &IID_IMFTransform, (void **)&transform );
2680 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
2681 hr = IUnknown_QueryInterface( unknown, &IID_IMediaObject, (void **)&media_object );
2682 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
2683 hr = IUnknown_QueryInterface( unknown, &IID_IPropertyBag, (void **)&property_bag );
2684 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
2685 hr = IUnknown_QueryInterface( media_object, &IID_IUnknown, (void **)&tmp_unknown );
2686 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
2688 ok( unknown != &outer, "got outer IUnknown\n" );
2689 ok( transform != (void *)unknown, "got IUnknown == IMFTransform\n" );
2690 ok( media_object != (void *)unknown, "got IUnknown == IMediaObject\n" );
2691 ok( property_bag != (void *)unknown, "got IUnknown == IPropertyBag\n" );
2692 ok( tmp_unknown != unknown, "got inner IUnknown\n" );
2694 check_interface( unknown, &IID_IPersistPropertyBag, FALSE );
2695 check_interface( unknown, &IID_IAMFilterMiscFlags, FALSE );
2696 check_interface( unknown, &IID_IMediaSeeking, FALSE );
2697 check_interface( unknown, &IID_IMediaPosition, FALSE );
2698 check_interface( unknown, &IID_IReferenceClock, FALSE );
2699 check_interface( unknown, &IID_IBasicAudio, FALSE );
2701 ref = IUnknown_Release( tmp_unknown );
2702 ok( ref == 1, "Release returned %lu\n", ref );
2703 ref = IPropertyBag_Release( property_bag );
2704 ok( ref == 1, "Release returned %lu\n", ref );
2705 ref = IMediaObject_Release( media_object );
2706 ok( ref == 1, "Release returned %lu\n", ref );
2707 ref = IMFTransform_Release( transform );
2708 ok( ref == 1, "Release returned %lu\n", ref );
2709 ref = IUnknown_Release( unknown );
2710 ok( ref == 0, "Release returned %lu\n", ref );
2712 failed:
2713 winetest_pop_context();
2714 CoUninitialize();
2717 #define next_h264_sample(a, b) next_h264_sample_(__LINE__, a, b)
2718 static IMFSample *next_h264_sample_(int line, const BYTE **h264_buf, ULONG *h264_len)
2720 const BYTE *sample_data;
2722 ok_(__FILE__, line)(*h264_len > 4, "invalid h264 length\n");
2723 ok_(__FILE__, line)(*(UINT32 *)*h264_buf == 0x01000000, "invalid h264 buffer\n");
2724 sample_data = *h264_buf;
2726 (*h264_len) -= 4;
2727 (*h264_buf) += 4;
2729 while (*h264_len >= 4 && *(UINT32 *)*h264_buf != 0x01000000)
2731 (*h264_len)--;
2732 (*h264_buf)++;
2735 return create_sample(sample_data, *h264_buf - sample_data);
2738 static void test_h264_decoder(void)
2740 const GUID *const class_id = &CLSID_MSH264DecoderMFT;
2741 const struct transform_info expect_mft_info =
2743 .name = L"Microsoft H264 Video Decoder MFT",
2744 .major_type = &MFMediaType_Video,
2745 .inputs =
2747 {.subtype = &MFVideoFormat_H264},
2748 {.subtype = &MFVideoFormat_H264_ES},
2750 .outputs =
2752 {.subtype = &MFVideoFormat_NV12},
2753 {.subtype = &MFVideoFormat_YV12},
2754 {.subtype = &MFVideoFormat_IYUV},
2755 {.subtype = &MFVideoFormat_I420},
2756 {.subtype = &MFVideoFormat_YUY2},
2759 static const media_type_desc default_inputs[] =
2762 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2763 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
2766 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2767 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264_ES),
2770 static const struct attribute_desc expect_transform_attributes[] =
2772 ATTR_UINT32(MF_LOW_LATENCY, 0),
2773 ATTR_UINT32(MF_SA_D3D_AWARE, 1, .todo = TRUE),
2774 ATTR_UINT32(MF_SA_D3D11_AWARE, 1, .todo = TRUE),
2775 ATTR_UINT32(MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER, 0, .todo = TRUE),
2776 /* more H264 decoder specific attributes from CODECAPI */
2777 {0},
2779 static const DWORD input_width = 120, input_height = 248;
2780 const media_type_desc default_outputs[] =
2783 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2784 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
2785 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
2786 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
2787 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
2788 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
2789 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2790 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2791 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
2792 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
2793 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
2796 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2797 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
2798 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
2799 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
2800 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
2801 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
2802 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2803 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2804 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
2805 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
2806 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
2809 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2810 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
2811 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
2812 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
2813 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
2814 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
2815 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2816 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2817 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
2818 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
2819 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
2822 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2823 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
2824 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
2825 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
2826 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
2827 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
2828 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2829 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2830 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
2831 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
2832 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
2835 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2836 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
2837 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
2838 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
2839 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width * 2),
2840 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
2841 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2842 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2843 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
2844 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 2),
2845 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
2848 const struct attribute_desc input_type_desc[] =
2850 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
2851 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264, .required = TRUE),
2852 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
2853 {0},
2855 const struct attribute_desc output_type_desc[] =
2857 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
2858 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE),
2859 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height, .required = TRUE),
2860 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
2861 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 2, 1),
2862 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
2863 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * input_height * 3 / 2),
2864 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
2865 {0},
2867 const struct attribute_desc expect_input_type_desc[] =
2869 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2870 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
2871 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
2872 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 0),
2873 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 0),
2874 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 0),
2875 ATTR_UINT32(MF_MT_AVG_BIT_ERROR_RATE, 0),
2876 ATTR_UINT32(MF_MT_COMPRESSED, 1),
2877 {0},
2879 const struct attribute_desc expect_output_type_desc[] =
2881 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2882 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
2883 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
2884 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
2885 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 2, 1),
2886 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
2887 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * input_height * 3 / 2),
2888 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
2889 ATTR_UINT32(MF_MT_AVG_BIT_ERROR_RATE, 0),
2890 ATTR_UINT32(MF_MT_COMPRESSED, 0),
2891 {0},
2893 static const struct attribute_desc new_output_type_desc[] =
2895 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2896 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
2897 ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96),
2898 ATTR_RATIO(MF_MT_FRAME_RATE, 1, 1),
2899 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 2),
2900 {0},
2902 static const struct attribute_desc expect_new_output_type_desc[] =
2904 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2905 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
2906 ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96),
2907 ATTR_RATIO(MF_MT_FRAME_RATE, 1, 1),
2908 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 2),
2909 ATTR_UINT32(MF_MT_COMPRESSED, 0),
2910 ATTR_UINT32(MF_MT_AVG_BIT_ERROR_RATE, 0),
2911 {0},
2913 static const MFVideoArea actual_aperture = {.Area={82,84}};
2914 static const DWORD actual_width = 96, actual_height = 96;
2915 const media_type_desc actual_outputs[] =
2918 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2919 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
2920 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
2921 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
2922 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
2923 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
2924 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
2925 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
2926 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
2927 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2928 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2929 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
2932 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2933 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
2934 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
2935 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
2936 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
2937 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
2938 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
2939 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
2940 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
2941 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2942 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2943 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
2946 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2947 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
2948 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
2949 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
2950 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
2951 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
2952 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
2953 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
2954 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
2955 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2956 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2957 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
2960 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2961 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
2962 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
2963 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
2964 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
2965 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
2966 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
2967 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
2968 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
2969 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2970 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2971 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
2974 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2975 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
2976 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
2977 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
2978 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
2979 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
2980 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
2981 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
2982 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
2983 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2984 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2985 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
2988 const MFT_OUTPUT_STREAM_INFO initial_output_info =
2990 .dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
2991 MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE,
2992 .cbSize = 1920 * 1088 * 2,
2994 const MFT_OUTPUT_STREAM_INFO output_info =
2996 .dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
2997 MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE,
2998 .cbSize = input_width * input_height * 2,
3000 const MFT_OUTPUT_STREAM_INFO actual_output_info =
3002 .dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
3003 MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE,
3004 .cbSize = actual_width * actual_height * 2,
3006 const MFT_INPUT_STREAM_INFO input_info =
3008 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
3009 MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE,
3010 .cbSize = 0x1000,
3013 const struct attribute_desc output_sample_attributes[] =
3015 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
3016 {0},
3018 const struct buffer_desc output_buffer_desc_nv12 =
3020 .length = actual_width * actual_height * 3 / 2,
3021 .compare = compare_nv12, .dump = dump_nv12, .rect = {.right = 82, .bottom = 84},
3023 const struct sample_desc output_sample_desc_nv12 =
3025 .attributes = output_sample_attributes,
3026 .sample_time = 0, .sample_duration = 333667,
3027 .buffer_count = 1, .buffers = &output_buffer_desc_nv12,
3029 const struct buffer_desc output_buffer_desc_i420 =
3031 .length = actual_width * actual_height * 3 / 2,
3032 .compare = compare_i420, .dump = dump_i420, .rect = {.right = 82, .bottom = 84},
3034 const struct sample_desc expect_output_sample_i420 =
3036 .attributes = output_sample_attributes,
3037 .sample_time = 333667, .sample_duration = 333667, .todo_time = 1334666 /* with VA-API */,
3038 .buffer_count = 1, .buffers = &output_buffer_desc_i420,
3041 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_H264};
3042 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
3043 IMFSample *input_sample, *output_sample;
3044 const BYTE *h264_encoded_data;
3045 IMFCollection *output_samples;
3046 ULONG h264_encoded_data_len;
3047 DWORD length, output_status;
3048 IMFAttributes *attributes;
3049 IMFMediaType *media_type;
3050 IMFTransform *transform;
3051 ULONG i, ret, ref;
3052 HRESULT hr;
3054 hr = CoInitialize(NULL);
3055 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
3057 winetest_push_context("h264dec");
3059 if (!check_mft_enum(MFT_CATEGORY_VIDEO_DECODER, &input_type, &output_type, class_id))
3060 goto failed;
3061 check_mft_get_info(class_id, &expect_mft_info);
3063 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
3064 &IID_IMFTransform, (void **)&transform)))
3065 goto failed;
3067 check_interface(transform, &IID_IMFTransform, TRUE);
3068 check_interface(transform, &IID_IMediaObject, FALSE);
3069 check_interface(transform, &IID_IPropertyStore, FALSE);
3070 check_interface(transform, &IID_IPropertyBag, FALSE);
3072 check_mft_optional_methods(transform);
3073 check_mft_get_attributes(transform, expect_transform_attributes, TRUE);
3074 check_mft_get_input_stream_info(transform, S_OK, &input_info);
3075 check_mft_get_output_stream_info(transform, S_OK, &initial_output_info);
3077 hr = IMFTransform_GetAttributes(transform, &attributes);
3078 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
3079 hr = IMFAttributes_SetUINT32(attributes, &MF_LOW_LATENCY, 1);
3080 ok(hr == S_OK, "SetUINT32 returned %#lx\n", hr);
3081 IMFAttributes_Release(attributes);
3083 /* no output type is available before an input type is set */
3085 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
3086 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
3088 /* setting output media type first doesn't work */
3089 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
3090 check_mft_get_output_current_type(transform, NULL);
3092 /* check available input types */
3094 i = -1;
3095 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
3097 winetest_push_context("in %lu", i);
3098 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
3099 check_media_type(media_type, default_inputs[i], -1);
3100 ret = IMFMediaType_Release(media_type);
3101 ok(ret == 0, "Release returned %lu\n", ret);
3102 winetest_pop_context();
3104 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
3105 ok(i == 2 || broken(i == 1) /* Win7 */, "%lu input media types\n", i);
3107 check_mft_set_input_type_required(transform, input_type_desc);
3108 check_mft_set_input_type(transform, input_type_desc);
3109 check_mft_get_input_current_type_(transform, expect_input_type_desc, TRUE, FALSE);
3111 check_mft_get_input_stream_info(transform, S_OK, &input_info);
3112 check_mft_get_output_stream_info(transform, S_OK, &output_info);
3114 /* output types can now be enumerated (though they are actually the same for all input types) */
3116 i = -1;
3117 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
3119 winetest_push_context("out %lu", i);
3120 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3121 check_media_type(media_type, default_outputs[i], -1);
3122 ret = IMFMediaType_Release(media_type);
3123 ok(ret == 0, "Release returned %lu\n", ret);
3124 winetest_pop_context();
3126 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3127 ok(i == 5, "%lu output media types\n", i);
3129 check_mft_set_output_type_required(transform, output_type_desc);
3130 check_mft_set_output_type(transform, output_type_desc, S_OK);
3131 check_mft_get_output_current_type_(transform, expect_output_type_desc, FALSE, TRUE);
3133 /* check that the output media type we've selected don't change the enumeration */
3135 i = -1;
3136 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
3138 winetest_push_context("out %lu", i);
3139 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3140 check_media_type(media_type, default_outputs[i], -1);
3141 ret = IMFMediaType_Release(media_type);
3142 ok(ret == 0, "Release returned %lu\n", ret);
3143 winetest_pop_context();
3145 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3146 ok(i == 5, "%lu output media types\n", i);
3148 check_mft_get_input_stream_info(transform, S_OK, &input_info);
3149 check_mft_get_output_stream_info(transform, S_OK, &output_info);
3151 load_resource(L"h264data.bin", &h264_encoded_data, &h264_encoded_data_len);
3153 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
3154 * IMFTransform_ProcessOutput needs a sample or returns an error */
3156 hr = check_mft_process_output(transform, NULL, &output_status);
3157 ok(hr == E_INVALIDARG || hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3158 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3160 i = 0;
3161 input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
3162 while (1)
3164 output_sample = create_sample(NULL, output_info.cbSize);
3165 hr = check_mft_process_output(transform, output_sample, &output_status);
3166 if (hr != MF_E_TRANSFORM_NEED_MORE_INPUT) break;
3168 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3169 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3170 hr = IMFSample_GetTotalLength(output_sample, &length);
3171 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
3172 ok(length == 0, "got length %lu\n", length);
3173 ret = IMFSample_Release(output_sample);
3174 ok(ret == 0, "Release returned %lu\n", ret);
3176 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3177 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3178 ret = IMFSample_Release(input_sample);
3179 ok(ret <= 1, "Release returned %lu\n", ret);
3180 input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
3182 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3183 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3184 ret = IMFSample_Release(input_sample);
3185 ok(ret <= 1, "Release returned %lu\n", ret);
3186 input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
3187 i++;
3189 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
3190 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
3192 todo_wine
3193 ok(i == 2, "got %lu iterations\n", i);
3194 todo_wine
3195 ok(h264_encoded_data_len == 1180, "got h264_encoded_data_len %lu\n", h264_encoded_data_len);
3196 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
3197 ok(output_status == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got output[0].dwStatus %#lx\n", output_status);
3198 hr = IMFSample_GetTotalLength(output_sample, &length);
3199 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
3200 ok(length == 0, "got length %lu\n", length);
3201 ret = IMFSample_Release(output_sample);
3202 ok(ret == 0, "Release returned %lu\n", ret);
3204 check_mft_get_input_stream_info(transform, S_OK, &input_info);
3205 check_mft_get_output_stream_info(transform, S_OK, &actual_output_info);
3207 i = -1;
3208 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
3210 winetest_push_context("out %lu", i);
3211 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3212 check_media_type(media_type, actual_outputs[i], -1);
3213 ret = IMFMediaType_Release(media_type);
3214 ok(ret == 0, "Release returned %lu\n", ret);
3215 winetest_pop_context();
3217 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3218 ok(i == 5, "%lu output media types\n", i);
3220 /* current output type is still the one we selected */
3221 check_mft_get_output_current_type_(transform, expect_output_type_desc, FALSE, TRUE);
3223 hr = MFCreateCollection(&output_samples);
3224 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
3226 output_sample = create_sample(NULL, output_info.cbSize);
3227 hr = check_mft_process_output(transform, output_sample, &output_status);
3228 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
3229 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3230 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
3231 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
3232 ref = IMFSample_Release(output_sample);
3233 ok(ref == 1, "Release returned %ld\n", ref);
3235 ret = check_mf_sample_collection(output_samples, &output_sample_desc_nv12, L"nv12frame.bmp");
3236 ok(ret == 0, "got %lu%% diff\n", ret);
3237 IMFCollection_Release(output_samples);
3239 /* we can change it, but only with the correct frame size */
3240 hr = MFCreateMediaType(&media_type);
3241 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
3242 init_media_type(media_type, output_type_desc, -1);
3243 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3244 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
3245 init_media_type(media_type, new_output_type_desc, -1);
3246 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3247 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
3248 ret = IMFMediaType_Release(media_type);
3249 ok(ret == 1, "Release returned %lu\n", ret);
3251 check_mft_get_output_current_type_(transform, expect_new_output_type_desc, FALSE, TRUE);
3253 output_sample = create_sample(NULL, actual_width * actual_height * 2);
3254 hr = check_mft_process_output(transform, output_sample, &output_status);
3255 todo_wine
3256 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
3257 todo_wine
3258 ok(output_status == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got output[0].dwStatus %#lx\n", output_status);
3260 while (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
3262 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3263 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3264 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3265 ret = IMFSample_Release(input_sample);
3266 ok(ret <= 1, "Release returned %lu\n", ret);
3267 input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
3268 hr = check_mft_process_output(transform, output_sample, &output_status);
3271 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
3272 ok(output_status == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got output[0].dwStatus %#lx\n", output_status);
3274 hr = IMFSample_GetTotalLength(output_sample, &length);
3275 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
3276 ok(length == 0, "got length %lu\n", length);
3277 ret = IMFSample_Release(output_sample);
3278 ok(ret == 0, "Release returned %lu\n", ret);
3280 hr = MFCreateCollection(&output_samples);
3281 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
3283 output_sample = create_sample(NULL, actual_width * actual_height * 2);
3284 hr = check_mft_process_output(transform, output_sample, &output_status);
3285 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
3286 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3287 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
3288 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
3289 ref = IMFSample_Release(output_sample);
3290 ok(ref == 1, "Release returned %ld\n", ref);
3292 ret = check_mf_sample_collection(output_samples, &expect_output_sample_i420, L"i420frame.bmp");
3293 ok(ret == 0, "got %lu%% diff\n", ret);
3294 IMFCollection_Release(output_samples);
3296 output_sample = create_sample(NULL, actual_width * actual_height * 2);
3297 hr = check_mft_process_output(transform, output_sample, &output_status);
3298 todo_wine_if(hr == S_OK) /* when VA-API plugin is used */
3299 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3300 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3301 ret = IMFSample_Release(output_sample);
3302 ok(ret == 0, "Release returned %lu\n", ret);
3304 ret = IMFTransform_Release(transform);
3305 ok(ret == 0, "Release returned %lu\n", ret);
3306 ret = IMFSample_Release(input_sample);
3307 ok(ret == 0, "Release returned %lu\n", ret);
3309 failed:
3310 winetest_pop_context();
3311 CoUninitialize();
3314 static void test_audio_convert(void)
3316 const GUID *const class_id = &CLSID_CResamplerMediaObject;
3317 const struct transform_info expect_mft_info =
3319 .name = L"Resampler MFT",
3320 .major_type = &MFMediaType_Audio,
3321 .inputs =
3323 {.subtype = &MFAudioFormat_PCM},
3324 {.subtype = &MFAudioFormat_Float},
3326 .outputs =
3328 {.subtype = &MFAudioFormat_PCM},
3329 {.subtype = &MFAudioFormat_Float},
3332 const struct transform_info expect_dmo_info =
3334 .name = L"Resampler DMO",
3335 .major_type = &MEDIATYPE_Audio,
3336 .inputs =
3338 {.subtype = &MEDIASUBTYPE_PCM},
3339 {.subtype = &MEDIASUBTYPE_IEEE_FLOAT},
3341 .outputs =
3343 {.subtype = &MEDIASUBTYPE_PCM},
3344 {.subtype = &MEDIASUBTYPE_IEEE_FLOAT},
3348 static const media_type_desc expect_available_inputs[] =
3351 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3352 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
3353 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3356 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3357 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
3358 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3361 static const media_type_desc expect_available_outputs[] =
3364 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3365 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
3366 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3369 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3370 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
3371 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3374 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3375 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
3376 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
3377 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
3378 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
3379 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 384000),
3380 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
3381 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3382 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
3385 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3386 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
3387 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
3388 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
3389 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
3390 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 192000),
3391 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
3392 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3393 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
3397 static const struct attribute_desc input_type_desc[] =
3399 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
3400 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float, .required = TRUE),
3401 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
3402 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32, .required = TRUE),
3403 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
3404 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2 * (32 / 8), .required = TRUE),
3405 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * (32 / 8) * 22050, .required = TRUE),
3406 {0},
3408 const struct attribute_desc output_type_desc[] =
3410 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
3411 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM, .required = TRUE),
3412 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
3413 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
3414 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .required = TRUE),
3415 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2 * (16 / 8), .required = TRUE),
3416 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * (16 / 8) * 44100, .required = TRUE),
3417 {0},
3419 static const struct attribute_desc expect_input_type_desc[] =
3421 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3422 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
3423 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
3424 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
3425 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
3426 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
3427 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 22050 * 8),
3428 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3429 ATTR_UINT32(MF_MT_AUDIO_CHANNEL_MASK, 3),
3430 {0},
3432 const struct attribute_desc expect_output_type_desc[] =
3434 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3435 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
3436 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
3437 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
3438 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
3439 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
3440 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 * 4),
3441 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3442 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
3443 {0},
3445 const MFT_OUTPUT_STREAM_INFO output_info =
3447 .cbSize = 4,
3448 .cbAlignment = 1,
3450 const MFT_INPUT_STREAM_INFO input_info =
3452 .cbSize = 8,
3453 .cbAlignment = 1,
3456 static const ULONG audioconv_block_size = 0x4000;
3457 const struct buffer_desc output_buffer_desc[] =
3459 {.length = audioconv_block_size, .compare = compare_pcm16},
3460 {.length = 0x3dd8, .compare = compare_pcm16, .todo_length = TRUE},
3461 {.length = 0xfc, .compare = compare_pcm16},
3463 const struct attribute_desc output_sample_attributes[] =
3465 ATTR_UINT32(mft_output_sample_incomplete, 1),
3466 ATTR_UINT32(MFSampleExtension_CleanPoint, has_video_processor /* 0 on Win7 */, .todo = TRUE),
3467 {0},
3469 const struct sample_desc output_sample_desc[] =
3472 .attributes = output_sample_attributes + 0,
3473 .sample_time = 0, .sample_duration = 928798,
3474 .buffer_count = 1, .buffers = output_buffer_desc + 0, .repeat_count = 9,
3477 .attributes = output_sample_attributes + 1, /* not MFT_OUTPUT_DATA_BUFFER_INCOMPLETE */
3478 .sample_time = 9287980, .sample_duration = 897506,
3479 .buffer_count = 1, .buffers = output_buffer_desc + 1, .todo_length = TRUE,
3482 .attributes = output_sample_attributes + 0,
3483 .sample_time = 10185486, .sample_duration = 14286,
3484 .buffer_count = 1, .buffers = output_buffer_desc + 2,
3488 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_PCM};
3489 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_Float};
3490 IMFSample *input_sample, *output_sample;
3491 IMFCollection *output_samples;
3492 DWORD length, output_status;
3493 IMFMediaType *media_type;
3494 IMFTransform *transform;
3495 const BYTE *audio_data;
3496 ULONG audio_data_len;
3497 ULONG i, ret, ref;
3498 HRESULT hr;
3500 hr = CoInitialize(NULL);
3501 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
3503 winetest_push_context("resampler");
3505 if (!check_mft_enum(MFT_CATEGORY_AUDIO_EFFECT, &input_type, &output_type, class_id))
3506 goto failed;
3507 check_mft_get_info(class_id, &expect_mft_info);
3508 check_dmo_get_info(class_id, &expect_dmo_info);
3510 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
3511 &IID_IMFTransform, (void **)&transform)))
3512 goto failed;
3514 check_interface(transform, &IID_IMFTransform, TRUE);
3515 check_interface(transform, &IID_IMediaObject, TRUE);
3516 check_interface(transform, &IID_IPropertyStore, TRUE);
3517 check_interface(transform, &IID_IPropertyBag, TRUE);
3518 /* check_interface(transform, &IID_IWMResamplerProps, TRUE); */
3520 check_mft_optional_methods(transform);
3521 check_mft_get_attributes(transform, NULL, FALSE);
3522 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
3523 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
3525 i = -1;
3526 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
3528 winetest_push_context("out %lu", i);
3529 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3530 check_media_type(media_type, expect_available_outputs[i], -1);
3531 ret = IMFMediaType_Release(media_type);
3532 ok(ret == 0, "Release returned %lu\n", ret);
3533 winetest_pop_context();
3535 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3536 ok(i == 4, "%lu output media types\n", i);
3538 i = -1;
3539 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
3541 winetest_push_context("in %lu", i);
3542 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
3543 check_media_type(media_type, expect_available_inputs[i], -1);
3544 ret = IMFMediaType_Release(media_type);
3545 ok(ret == 0, "Release returned %lu\n", ret);
3546 winetest_pop_context();
3548 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
3549 ok(i == 2, "%lu input media types\n", i);
3551 /* setting output media type first doesn't work */
3552 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
3553 check_mft_get_output_current_type(transform, NULL);
3555 check_mft_set_input_type_required(transform, input_type_desc);
3556 check_mft_set_input_type(transform, input_type_desc);
3557 check_mft_get_input_current_type_(transform, expect_input_type_desc, FALSE, TRUE);
3559 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
3560 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
3562 /* check new output media types */
3564 i = -1;
3565 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
3567 winetest_push_context("out %lu", i);
3568 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3569 check_media_type(media_type, expect_available_outputs[i], -1);
3570 ret = IMFMediaType_Release(media_type);
3571 ok(ret == 0, "Release returned %lu\n", ret);
3572 winetest_pop_context();
3574 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3575 ok(i == 4, "%lu output media types\n", i);
3577 check_mft_set_output_type_required(transform, output_type_desc);
3578 check_mft_set_output_type(transform, output_type_desc, S_OK);
3579 check_mft_get_output_current_type_(transform, expect_output_type_desc, FALSE, TRUE);
3581 check_mft_get_input_stream_info(transform, S_OK, &input_info);
3582 check_mft_get_output_stream_info(transform, S_OK, &output_info);
3584 load_resource(L"audiodata.bin", &audio_data, &audio_data_len);
3585 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
3587 input_sample = create_sample(audio_data, audio_data_len);
3588 hr = IMFSample_SetSampleTime(input_sample, 0);
3589 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
3590 hr = IMFSample_SetSampleDuration(input_sample, 10000000);
3591 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
3592 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3593 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3594 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
3595 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
3596 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3597 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
3598 ret = IMFSample_Release(input_sample);
3599 ok(ret <= 1, "Release returned %ld\n", ret);
3601 hr = MFCreateCollection(&output_samples);
3602 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
3604 output_sample = create_sample(NULL, audioconv_block_size);
3605 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
3607 winetest_push_context("%lu", i);
3608 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
3609 ok(!(output_status & ~MFT_OUTPUT_DATA_BUFFER_INCOMPLETE), "got output[0].dwStatus %#lx\n", output_status);
3610 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
3611 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
3612 ref = IMFSample_Release(output_sample);
3613 ok(ref == 1, "Release returned %ld\n", ref);
3614 output_sample = create_sample(NULL, audioconv_block_size);
3615 winetest_pop_context();
3617 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3618 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3619 ret = IMFSample_Release(output_sample);
3620 ok(ret == 0, "Release returned %lu\n", ret);
3621 todo_wine
3622 ok(i == 12 || broken(i == 11) /* Win7 */, "got %lu output samples\n", i);
3624 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"audioconvdata.bin");
3625 ok(ret == 0, "got %lu%% diff\n", ret);
3626 IMFCollection_Release(output_samples);
3628 output_sample = create_sample(NULL, audioconv_block_size);
3629 hr = check_mft_process_output(transform, output_sample, &output_status);
3630 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3631 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3632 hr = IMFSample_GetTotalLength(output_sample, &length);
3633 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
3634 ok(length == 0, "got length %lu\n", length);
3635 ret = IMFSample_Release(output_sample);
3636 ok(ret == 0, "Release returned %lu\n", ret);
3638 ret = IMFTransform_Release(transform);
3639 ok(ret == 0, "Release returned %lu\n", ret);
3641 failed:
3642 winetest_pop_context();
3643 CoUninitialize();
3646 static void test_wmv_decoder(void)
3648 const GUID *const class_id = &CLSID_CWMVDecMediaObject;
3649 const struct transform_info expect_mft_info =
3651 .name = L"WMVideo Decoder MFT",
3652 .major_type = &MFMediaType_Video,
3653 .inputs =
3655 {.subtype = &MFVideoFormat_WMV1},
3656 {.subtype = &MFVideoFormat_WMV2},
3657 {.subtype = &MFVideoFormat_WMV3},
3658 {.subtype = &MEDIASUBTYPE_WMVP},
3659 {.subtype = &MEDIASUBTYPE_WVP2},
3660 {.subtype = &MEDIASUBTYPE_WMVR},
3661 {.subtype = &MEDIASUBTYPE_WMVA},
3662 {.subtype = &MFVideoFormat_WVC1},
3663 {.subtype = &MFVideoFormat_VC1S},
3665 .outputs =
3667 {.subtype = &MFVideoFormat_YV12},
3668 {.subtype = &MFVideoFormat_YUY2},
3669 {.subtype = &MFVideoFormat_UYVY},
3670 {.subtype = &MFVideoFormat_YVYU},
3671 {.subtype = &MFVideoFormat_NV11},
3672 {.subtype = &MFVideoFormat_NV12},
3673 {.subtype = &DMOVideoFormat_RGB32},
3674 {.subtype = &DMOVideoFormat_RGB24},
3675 {.subtype = &DMOVideoFormat_RGB565},
3676 {.subtype = &DMOVideoFormat_RGB555},
3677 {.subtype = &DMOVideoFormat_RGB8},
3680 const struct transform_info expect_dmo_info =
3682 .name = L"WMVideo Decoder DMO",
3683 .major_type = &MEDIATYPE_Video,
3684 .inputs =
3686 {.subtype = &MEDIASUBTYPE_WMV1},
3687 {.subtype = &MEDIASUBTYPE_WMV2},
3688 {.subtype = &MEDIASUBTYPE_WMV3},
3689 {.subtype = &MEDIASUBTYPE_WMVA},
3690 {.subtype = &MEDIASUBTYPE_WVC1},
3691 {.subtype = &MEDIASUBTYPE_WMVP},
3692 {.subtype = &MEDIASUBTYPE_WVP2},
3693 {.subtype = &MFVideoFormat_VC1S},
3695 .outputs =
3697 {.subtype = &MEDIASUBTYPE_YV12},
3698 {.subtype = &MEDIASUBTYPE_YUY2},
3699 {.subtype = &MEDIASUBTYPE_UYVY},
3700 {.subtype = &MEDIASUBTYPE_YVYU},
3701 {.subtype = &MEDIASUBTYPE_NV11},
3702 {.subtype = &MEDIASUBTYPE_NV12},
3703 {.subtype = &MEDIASUBTYPE_RGB32},
3704 {.subtype = &MEDIASUBTYPE_RGB24},
3705 {.subtype = &MEDIASUBTYPE_RGB565},
3706 {.subtype = &MEDIASUBTYPE_RGB555},
3707 {.subtype = &MEDIASUBTYPE_RGB8},
3711 static const struct attribute_desc expect_common_attributes[] =
3713 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3714 {0},
3716 static const media_type_desc expect_available_inputs[] =
3718 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1)},
3719 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV2)},
3720 {ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_WMVA)},
3721 {ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_WMVP)},
3722 {ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_WVP2)},
3723 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV_Unknown)},
3724 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WVC1)},
3725 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV3)},
3726 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_VC1S)},
3728 static const MFVideoArea actual_aperture = {.Area={96,96}};
3729 static const DWORD actual_width = 96, actual_height = 96;
3730 const struct attribute_desc expect_output_attributes[] =
3732 ATTR_BLOB(MF_MT_GEOMETRIC_APERTURE, &actual_aperture, sizeof(actual_aperture)),
3733 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, sizeof(actual_aperture)),
3734 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3735 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3736 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3737 ATTR_UINT32(MF_MT_INTERLACE_MODE, 2),
3738 {0},
3740 const media_type_desc expect_available_outputs[] =
3743 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3744 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
3745 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3746 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
3747 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
3750 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3751 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
3752 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3753 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
3754 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
3757 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3758 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
3759 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3760 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
3761 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
3764 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3765 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
3766 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3767 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
3768 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
3771 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3772 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
3773 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3774 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
3775 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
3778 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3779 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY),
3780 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3781 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
3782 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
3785 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3786 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU),
3787 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3788 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
3789 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
3792 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3793 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11),
3794 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3795 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
3796 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
3799 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3800 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
3801 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3802 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 4),
3803 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 4),
3806 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3807 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24),
3808 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3809 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 3),
3810 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3),
3813 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3814 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565),
3815 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3816 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
3817 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
3818 /* ATTR_BLOB(MF_MT_PALETTE, ... with 12 elements), */
3821 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3822 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555),
3823 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3824 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
3825 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
3828 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3829 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB8),
3830 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3831 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
3832 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height),
3833 /* ATTR_BLOB(MF_MT_PALETTE, ... with 904 elements), */
3836 const struct attribute_desc expect_attributes[] =
3838 ATTR_UINT32(MF_LOW_LATENCY, 0),
3839 ATTR_UINT32(MF_SA_D3D11_AWARE, 1),
3840 ATTR_UINT32(MF_SA_D3D_AWARE, 1),
3841 ATTR_UINT32(MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER, 0),
3842 /* more attributes from CODECAPI */
3843 {0},
3845 const struct attribute_desc input_type_desc[] =
3847 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
3848 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1, .required = TRUE),
3849 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
3850 {0},
3852 const struct attribute_desc output_type_desc[] =
3854 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
3855 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE),
3856 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
3857 {0},
3859 const struct attribute_desc expect_input_type_desc[] =
3861 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3862 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1),
3863 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3864 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3865 {0},
3867 const struct attribute_desc expect_output_type_desc[] =
3869 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3870 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
3871 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3872 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
3873 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
3874 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3875 ATTR_UINT32(MF_MT_VIDEO_NOMINAL_RANGE, 2),
3876 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3877 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3878 {0},
3880 const MFT_OUTPUT_STREAM_INFO expect_output_info =
3882 .dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_DISCARDABLE,
3883 .cbSize = 0x3600,
3884 .cbAlignment = 1,
3886 const MFT_OUTPUT_STREAM_INFO empty_output_info =
3888 .dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_DISCARDABLE,
3890 const MFT_INPUT_STREAM_INFO expect_input_info =
3892 .cbSize = 0x3600,
3893 .cbAlignment = 1,
3896 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
3897 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_WMV1};
3898 IMFMediaType *media_type;
3899 IMFTransform *transform;
3900 ULONG i, ret;
3901 HRESULT hr;
3903 hr = CoInitialize(NULL);
3904 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
3906 winetest_push_context("wmvdec");
3908 if (!has_video_processor)
3910 win_skip("Skipping inconsistent WMV decoder tests on Win7\n");
3911 goto failed;
3914 if (!check_mft_enum(MFT_CATEGORY_VIDEO_DECODER, &input_type, &output_type, class_id))
3915 goto failed;
3916 check_mft_get_info(class_id, &expect_mft_info);
3917 check_dmo_get_info(class_id, &expect_dmo_info);
3919 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
3920 &IID_IMFTransform, (void **)&transform)))
3921 goto failed;
3923 check_interface(transform, &IID_IMFTransform, TRUE);
3924 check_interface(transform, &IID_IMediaObject, TRUE);
3925 check_interface(transform, &IID_IPropertyStore, TRUE);
3926 check_interface(transform, &IID_IPropertyBag, TRUE);
3928 check_mft_optional_methods(transform);
3929 check_mft_get_attributes(transform, expect_attributes, TRUE);
3930 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
3931 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, &empty_output_info);
3933 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
3934 todo_wine
3935 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
3937 i = -1;
3938 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
3940 winetest_push_context("in %lu", i);
3941 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
3942 check_media_type(media_type, expect_common_attributes, -1);
3943 check_media_type(media_type, expect_available_inputs[i], -1);
3944 ret = IMFMediaType_Release(media_type);
3945 ok(!ret, "Release returned %lu\n", ret);
3946 winetest_pop_context();
3948 todo_wine
3949 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
3950 todo_wine
3951 ok(i == ARRAY_SIZE(expect_available_inputs), "%lu input media types\n", i);
3953 if (hr == E_NOTIMPL)
3954 goto skip_tests;
3956 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
3957 check_mft_get_output_current_type(transform, NULL);
3959 check_mft_set_input_type_required(transform, input_type_desc);
3960 check_mft_set_input_type(transform, input_type_desc);
3961 check_mft_get_input_current_type_(transform, expect_input_type_desc, FALSE, TRUE);
3963 i = -1;
3964 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
3966 winetest_push_context("out %lu", i);
3967 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3968 check_media_type(media_type, expect_common_attributes, -1);
3969 check_media_type(media_type, expect_output_attributes, -1);
3970 check_media_type(media_type, expect_available_outputs[i], -1);
3971 ret = IMFMediaType_Release(media_type);
3972 ok(!ret, "Release returned %lu\n", ret);
3973 winetest_pop_context();
3975 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3976 ok(i == ARRAY_SIZE(expect_available_outputs), "%lu input media types\n", i);
3978 check_mft_set_output_type_required(transform, output_type_desc);
3979 check_mft_set_output_type(transform, output_type_desc, S_OK);
3980 check_mft_get_output_current_type_(transform, expect_output_type_desc, FALSE, TRUE);
3982 check_mft_get_input_stream_info(transform, S_OK, &expect_input_info);
3983 check_mft_get_output_stream_info(transform, S_OK, &expect_output_info);
3985 skip_tests:
3986 ret = IMFTransform_Release(transform);
3987 ok(ret == 0, "Release returned %lu\n", ret);
3989 failed:
3990 winetest_pop_context();
3991 CoUninitialize();
3994 static void test_color_convert(void)
3996 const GUID *const class_id = &CLSID_CColorConvertDMO;
3997 const struct transform_info expect_mft_info =
3999 .name = L"Color Converter MFT",
4000 .major_type = &MFMediaType_Video,
4001 .inputs =
4003 {.subtype = &MFVideoFormat_YV12},
4004 {.subtype = &MFVideoFormat_YUY2},
4005 {.subtype = &MFVideoFormat_UYVY},
4006 {.subtype = &MFVideoFormat_AYUV},
4007 {.subtype = &MFVideoFormat_NV12},
4008 {.subtype = &DMOVideoFormat_RGB32},
4009 {.subtype = &DMOVideoFormat_RGB565},
4010 {.subtype = &MFVideoFormat_I420},
4011 {.subtype = &MFVideoFormat_IYUV},
4012 {.subtype = &MFVideoFormat_YVYU},
4013 {.subtype = &DMOVideoFormat_RGB24},
4014 {.subtype = &DMOVideoFormat_RGB555},
4015 {.subtype = &DMOVideoFormat_RGB8},
4016 {.subtype = &MEDIASUBTYPE_V216},
4017 {.subtype = &MEDIASUBTYPE_V410},
4018 {.subtype = &MFVideoFormat_NV11},
4019 {.subtype = &MFVideoFormat_Y41P},
4020 {.subtype = &MFVideoFormat_Y41T},
4021 {.subtype = &MFVideoFormat_Y42T},
4022 {.subtype = &MFVideoFormat_YVU9},
4024 .outputs =
4026 {.subtype = &MFVideoFormat_YV12},
4027 {.subtype = &MFVideoFormat_YUY2},
4028 {.subtype = &MFVideoFormat_UYVY},
4029 {.subtype = &MFVideoFormat_AYUV},
4030 {.subtype = &MFVideoFormat_NV12},
4031 {.subtype = &DMOVideoFormat_RGB32},
4032 {.subtype = &DMOVideoFormat_RGB565},
4033 {.subtype = &MFVideoFormat_I420},
4034 {.subtype = &MFVideoFormat_IYUV},
4035 {.subtype = &MFVideoFormat_YVYU},
4036 {.subtype = &DMOVideoFormat_RGB24},
4037 {.subtype = &DMOVideoFormat_RGB555},
4038 {.subtype = &DMOVideoFormat_RGB8},
4039 {.subtype = &MEDIASUBTYPE_V216},
4040 {.subtype = &MEDIASUBTYPE_V410},
4041 {.subtype = &MFVideoFormat_NV11},
4044 const struct transform_info expect_dmo_info =
4046 .name = L"Color Converter DMO",
4047 .major_type = &MEDIATYPE_Video,
4048 .inputs =
4050 {.subtype = &MEDIASUBTYPE_YV12},
4051 {.subtype = &MEDIASUBTYPE_YUY2},
4052 {.subtype = &MEDIASUBTYPE_UYVY},
4053 {.subtype = &MEDIASUBTYPE_AYUV},
4054 {.subtype = &MEDIASUBTYPE_NV12},
4055 {.subtype = &MEDIASUBTYPE_RGB32},
4056 {.subtype = &MEDIASUBTYPE_RGB565},
4057 {.subtype = &MEDIASUBTYPE_I420},
4058 {.subtype = &MEDIASUBTYPE_IYUV},
4059 {.subtype = &MEDIASUBTYPE_YVYU},
4060 {.subtype = &MEDIASUBTYPE_RGB24},
4061 {.subtype = &MEDIASUBTYPE_RGB555},
4062 {.subtype = &MEDIASUBTYPE_RGB8},
4063 {.subtype = &MEDIASUBTYPE_V216},
4064 {.subtype = &MEDIASUBTYPE_V410},
4065 {.subtype = &MEDIASUBTYPE_NV11},
4066 {.subtype = &MEDIASUBTYPE_Y41P},
4067 {.subtype = &MEDIASUBTYPE_Y41T},
4068 {.subtype = &MEDIASUBTYPE_Y42T},
4069 {.subtype = &MEDIASUBTYPE_YVU9},
4071 .outputs =
4073 {.subtype = &MEDIASUBTYPE_YV12},
4074 {.subtype = &MEDIASUBTYPE_YUY2},
4075 {.subtype = &MEDIASUBTYPE_UYVY},
4076 {.subtype = &MEDIASUBTYPE_AYUV},
4077 {.subtype = &MEDIASUBTYPE_NV12},
4078 {.subtype = &MEDIASUBTYPE_RGB32},
4079 {.subtype = &MEDIASUBTYPE_RGB565},
4080 {.subtype = &MEDIASUBTYPE_I420},
4081 {.subtype = &MEDIASUBTYPE_IYUV},
4082 {.subtype = &MEDIASUBTYPE_YVYU},
4083 {.subtype = &MEDIASUBTYPE_RGB24},
4084 {.subtype = &MEDIASUBTYPE_RGB555},
4085 {.subtype = &MEDIASUBTYPE_RGB8},
4086 {.subtype = &MEDIASUBTYPE_V216},
4087 {.subtype = &MEDIASUBTYPE_V410},
4088 {.subtype = &MEDIASUBTYPE_NV11},
4092 static const media_type_desc expect_available_inputs[20] =
4094 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12), },
4095 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), },
4096 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY), },
4097 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_AYUV), },
4098 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), },
4099 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), },
4100 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565), },
4101 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420), },
4102 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV), },
4103 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU), },
4104 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24), },
4105 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555), },
4106 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_RGB8), },
4107 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V216), },
4108 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V410), },
4109 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11), },
4110 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y41P), },
4111 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y41T), },
4112 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y42T), },
4113 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVU9), },
4115 static const media_type_desc expect_available_outputs[16] =
4117 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12), },
4118 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), },
4119 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY), },
4120 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_AYUV), },
4121 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), },
4122 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), },
4123 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565), },
4124 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420), },
4125 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV), },
4126 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU), },
4127 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24), },
4128 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555), },
4129 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_RGB8), },
4130 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V216), },
4131 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V410), },
4132 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11), },
4134 static const media_type_desc expect_available_common =
4136 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4137 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4138 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4141 static const MFVideoArea actual_aperture = {.Area={82,84}};
4142 static const DWORD actual_width = 96, actual_height = 96;
4143 const struct attribute_desc input_type_desc[] =
4145 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
4146 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE),
4147 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
4148 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
4149 {0},
4151 const struct attribute_desc output_type_desc[] =
4153 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
4154 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32, .required = TRUE),
4155 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
4156 {0},
4158 const struct attribute_desc expect_input_type_desc[] =
4160 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4161 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
4162 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
4163 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4164 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
4165 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
4166 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4167 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4168 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4169 {0},
4171 const struct attribute_desc expect_output_type_desc[] =
4173 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4174 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
4175 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4176 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 4),
4177 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 4),
4178 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4179 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4180 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4181 {0},
4183 const MFT_OUTPUT_STREAM_INFO output_info =
4185 .cbSize = actual_width * actual_height * 4,
4186 .cbAlignment = 1,
4188 const MFT_INPUT_STREAM_INFO input_info =
4190 .cbSize = actual_width * actual_height * 3 / 2,
4191 .cbAlignment = 1,
4194 const struct buffer_desc output_buffer_desc =
4196 .length = actual_width * actual_height * 4,
4197 .compare = compare_rgb32, .dump = dump_rgb32, .rect = {.right = 82, .bottom = 84},
4199 const struct attribute_desc output_sample_attributes[] =
4201 ATTR_UINT32(MFSampleExtension_CleanPoint, 0, .todo = TRUE),
4202 {0},
4204 const struct sample_desc output_sample_desc =
4206 .attributes = output_sample_attributes,
4207 .sample_time = 0, .sample_duration = 10000000,
4208 .buffer_count = 1, .buffers = &output_buffer_desc,
4211 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
4212 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_I420};
4213 IMFSample *input_sample, *output_sample;
4214 IMFCollection *output_samples;
4215 DWORD length, output_status;
4216 const BYTE *nv12frame_data;
4217 ULONG nv12frame_data_len;
4218 IMFMediaType *media_type;
4219 IMFTransform *transform;
4220 ULONG i, ret, ref;
4221 HRESULT hr;
4223 hr = CoInitialize(NULL);
4224 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
4226 winetest_push_context("colorconv");
4228 if (!check_mft_enum(MFT_CATEGORY_VIDEO_EFFECT, &input_type, &output_type, class_id))
4229 goto failed;
4230 check_mft_get_info(class_id, &expect_mft_info);
4231 check_dmo_get_info(class_id, &expect_dmo_info);
4233 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
4234 &IID_IMFTransform, (void **)&transform)))
4235 goto failed;
4237 check_interface(transform, &IID_IMFTransform, TRUE);
4238 check_interface(transform, &IID_IMediaObject, TRUE);
4239 check_interface(transform, &IID_IPropertyStore, TRUE);
4240 todo_wine
4241 check_interface(transform, &IID_IPropertyBag, FALSE);
4242 todo_wine
4243 check_interface(transform, &IID_IMFRealTimeClient, TRUE);
4244 /* check_interface(transform, &IID_IWMColorConvProps, TRUE); */
4246 check_mft_optional_methods(transform);
4247 check_mft_get_attributes(transform, NULL, FALSE);
4248 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
4249 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
4251 i = -1;
4252 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
4254 winetest_push_context("out %lu", i);
4255 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
4256 check_media_type(media_type, expect_available_common, -1);
4257 check_media_type(media_type, expect_available_outputs[i], -1);
4258 ret = IMFMediaType_Release(media_type);
4259 ok(ret == 0, "Release returned %lu\n", ret);
4260 winetest_pop_context();
4262 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
4263 ok(i == 16, "%lu output media types\n", i);
4265 i = -1;
4266 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
4268 winetest_push_context("in %lu", i);
4269 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
4270 check_media_type(media_type, expect_available_common, -1);
4271 check_media_type(media_type, expect_available_inputs[i], -1);
4272 ret = IMFMediaType_Release(media_type);
4273 ok(ret == 0, "Release returned %lu\n", ret);
4274 winetest_pop_context();
4276 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
4277 ok(i == 20, "%lu input media types\n", i);
4279 check_mft_set_output_type_required(transform, output_type_desc);
4280 check_mft_set_output_type(transform, output_type_desc, S_OK);
4281 check_mft_get_output_current_type_(transform, expect_output_type_desc, FALSE, TRUE);
4283 check_mft_set_input_type_required(transform, input_type_desc);
4284 check_mft_set_input_type(transform, input_type_desc);
4285 check_mft_get_input_current_type_(transform, expect_input_type_desc, FALSE, TRUE);
4287 check_mft_get_input_stream_info(transform, S_OK, &input_info);
4288 check_mft_get_output_stream_info(transform, S_OK, &output_info);
4290 load_resource(L"nv12frame.bmp", &nv12frame_data, &nv12frame_data_len);
4291 /* skip BMP header and RGB data from the dump */
4292 length = *(DWORD *)(nv12frame_data + 2);
4293 nv12frame_data_len = nv12frame_data_len - length;
4294 nv12frame_data = nv12frame_data + length;
4295 ok(nv12frame_data_len == 13824, "got length %lu\n", nv12frame_data_len);
4297 input_sample = create_sample(nv12frame_data, nv12frame_data_len);
4298 hr = IMFSample_SetSampleTime(input_sample, 0);
4299 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
4300 hr = IMFSample_SetSampleDuration(input_sample, 10000000);
4301 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
4302 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
4303 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
4304 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
4305 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
4306 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
4307 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
4308 ret = IMFSample_Release(input_sample);
4309 ok(ret <= 1, "Release returned %ld\n", ret);
4311 hr = MFCreateCollection(&output_samples);
4312 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
4314 output_sample = create_sample(NULL, output_info.cbSize);
4315 hr = check_mft_process_output(transform, output_sample, &output_status);
4316 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
4317 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
4318 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
4319 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
4320 ref = IMFSample_Release(output_sample);
4321 ok(ref == 1, "Release returned %ld\n", ref);
4323 ret = check_mf_sample_collection(output_samples, &output_sample_desc, L"rgb32frame.bmp");
4324 ok(ret <= 4 /* small and harmless diff in Wine vs Windows */, "got %lu%% diff\n", ret);
4325 IMFCollection_Release(output_samples);
4327 output_sample = create_sample(NULL, output_info.cbSize);
4328 hr = check_mft_process_output(transform, output_sample, &output_status);
4329 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
4330 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
4331 hr = IMFSample_GetTotalLength(output_sample, &length);
4332 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
4333 ok(length == 0, "got length %lu\n", length);
4334 ret = IMFSample_Release(output_sample);
4335 ok(ret == 0, "Release returned %lu\n", ret);
4337 ret = IMFTransform_Release(transform);
4338 ok(ret == 0, "Release returned %ld\n", ret);
4340 failed:
4341 winetest_pop_context();
4342 CoUninitialize();
4345 static void test_video_processor(void)
4347 const GUID *const class_id = &CLSID_VideoProcessorMFT;
4348 const struct transform_info expect_mft_info =
4350 .name = L"Microsoft Video Processor MFT",
4351 .major_type = &MFMediaType_Video,
4352 .inputs =
4354 {.subtype = &MFVideoFormat_IYUV},
4355 {.subtype = &MFVideoFormat_YV12},
4356 {.subtype = &MFVideoFormat_NV12},
4357 {.subtype = &MFVideoFormat_YUY2},
4358 {.subtype = &MFVideoFormat_ARGB32},
4359 {.subtype = &MFVideoFormat_RGB32},
4360 {.subtype = &MFVideoFormat_NV11},
4361 {.subtype = &MFVideoFormat_AYUV},
4362 {.subtype = &MFVideoFormat_UYVY},
4363 {.subtype = &MEDIASUBTYPE_P208},
4364 {.subtype = &MFVideoFormat_RGB24},
4365 {.subtype = &MFVideoFormat_RGB555},
4366 {.subtype = &MFVideoFormat_RGB565},
4367 {.subtype = &MFVideoFormat_RGB8},
4368 {.subtype = &MFVideoFormat_I420},
4369 {.subtype = &MFVideoFormat_Y216},
4370 {.subtype = &MFVideoFormat_v410},
4371 {.subtype = &MFVideoFormat_Y41P},
4372 {.subtype = &MFVideoFormat_Y41T},
4373 {.subtype = &MFVideoFormat_Y42T},
4374 {.subtype = &MFVideoFormat_YVYU},
4375 {.subtype = &MFVideoFormat_420O},
4377 .outputs =
4379 {.subtype = &MFVideoFormat_IYUV},
4380 {.subtype = &MFVideoFormat_YV12},
4381 {.subtype = &MFVideoFormat_NV12},
4382 {.subtype = &MFVideoFormat_YUY2},
4383 {.subtype = &MFVideoFormat_ARGB32},
4384 {.subtype = &MFVideoFormat_RGB32},
4385 {.subtype = &MFVideoFormat_NV11},
4386 {.subtype = &MFVideoFormat_AYUV},
4387 {.subtype = &MFVideoFormat_UYVY},
4388 {.subtype = &MEDIASUBTYPE_P208},
4389 {.subtype = &MFVideoFormat_RGB24},
4390 {.subtype = &MFVideoFormat_RGB555},
4391 {.subtype = &MFVideoFormat_RGB565},
4392 {.subtype = &MFVideoFormat_RGB8},
4393 {.subtype = &MFVideoFormat_I420},
4394 {.subtype = &MFVideoFormat_Y216},
4395 {.subtype = &MFVideoFormat_v410},
4396 {.subtype = &MFVideoFormat_Y41P},
4397 {.subtype = &MFVideoFormat_Y41T},
4398 {.subtype = &MFVideoFormat_Y42T},
4399 {.subtype = &MFVideoFormat_YVYU},
4402 const GUID expect_available_inputs_w8[] =
4404 MFVideoFormat_IYUV,
4405 MFVideoFormat_YV12,
4406 MFVideoFormat_NV12,
4407 MFVideoFormat_420O,
4408 MFVideoFormat_UYVY,
4409 MFVideoFormat_YUY2,
4410 MFVideoFormat_P208,
4411 MFVideoFormat_NV11,
4412 MFVideoFormat_AYUV,
4413 MFVideoFormat_ARGB32,
4414 MFVideoFormat_RGB32,
4415 MFVideoFormat_RGB24,
4416 MFVideoFormat_I420,
4417 MFVideoFormat_YVYU,
4418 MFVideoFormat_RGB555,
4419 MFVideoFormat_RGB565,
4420 MFVideoFormat_RGB8,
4421 MFVideoFormat_Y216,
4422 MFVideoFormat_v410,
4423 MFVideoFormat_Y41P,
4424 MFVideoFormat_Y41T,
4425 MFVideoFormat_Y42T,
4427 const GUID expect_available_inputs_w10[] =
4429 MFVideoFormat_L8,
4430 MFVideoFormat_L16,
4431 MFAudioFormat_MPEG,
4432 MFVideoFormat_IYUV,
4433 MFVideoFormat_YV12,
4434 MFVideoFormat_NV12,
4435 MFVideoFormat_420O,
4436 MFVideoFormat_P010,
4437 MFVideoFormat_P016,
4438 MFVideoFormat_UYVY,
4439 MFVideoFormat_YUY2,
4440 MFVideoFormat_P208,
4441 MFVideoFormat_NV11,
4442 MFVideoFormat_AYUV,
4443 MFVideoFormat_ARGB32,
4444 MFVideoFormat_ABGR32,
4445 MFVideoFormat_RGB32,
4446 MFVideoFormat_A2R10G10B10,
4447 MFVideoFormat_A16B16G16R16F,
4448 MFVideoFormat_RGB24,
4449 MFVideoFormat_I420,
4450 MFVideoFormat_YVYU,
4451 MFVideoFormat_RGB555,
4452 MFVideoFormat_RGB565,
4453 MFVideoFormat_RGB8,
4454 MFVideoFormat_Y216,
4455 MFVideoFormat_v410,
4456 MFVideoFormat_Y41P,
4457 MFVideoFormat_Y41T,
4458 MFVideoFormat_Y42T,
4460 const GUID expect_available_outputs[] =
4462 MFVideoFormat_A2R10G10B10, /* enumerated with MFVideoFormat_P010 input */
4463 MFVideoFormat_P010, /* enumerated with MFVideoFormat_A2R10G10B10 input */
4464 MFVideoFormat_YUY2,
4465 MFVideoFormat_IYUV,
4466 MFVideoFormat_I420,
4467 MFVideoFormat_NV12,
4468 MFVideoFormat_RGB24,
4469 MFVideoFormat_ARGB32,
4470 MFVideoFormat_RGB32,
4471 MFVideoFormat_YV12,
4472 MFVideoFormat_Y216, /* enumerated with some input formats */
4473 MFVideoFormat_UYVY, /* enumerated with some input formats */
4474 MFVideoFormat_YVYU, /* enumerated with some input formats */
4475 MFVideoFormat_AYUV,
4476 MFVideoFormat_RGB555,
4477 MFVideoFormat_RGB565,
4478 MFVideoFormat_AYUV, /* some inputs enumerate MFVideoFormat_AYUV after RGB565 */
4479 MFVideoFormat_NV12, /* P010 enumerates NV12 after (A)RGB32 formats */
4480 MFVideoFormat_A16B16G16R16F, /* enumerated with MFVideoFormat_P010 input */
4482 static const media_type_desc expect_available_common =
4484 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4486 static const struct attribute_desc expect_transform_attributes[] =
4488 ATTR_UINT32(MFT_SUPPORT_3DVIDEO, 1, .todo = TRUE),
4489 /* ATTR_UINT32(MF_SA_D3D_AWARE, 1), only on W7 */
4490 {0},
4493 static const MFVideoArea actual_aperture = {.Area={82,84}};
4494 static const DWORD actual_width = 96, actual_height = 96;
4495 const struct attribute_desc input_type_desc[] =
4497 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
4498 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE),
4499 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
4500 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
4501 {0},
4503 const struct attribute_desc output_type_desc[] =
4505 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
4506 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32, .required = TRUE),
4507 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
4508 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
4509 {0},
4511 const MFT_OUTPUT_STREAM_INFO initial_output_info = {0};
4512 const MFT_INPUT_STREAM_INFO initial_input_info = {0};
4513 MFT_OUTPUT_STREAM_INFO output_info = {0};
4514 MFT_INPUT_STREAM_INFO input_info = {0};
4516 const struct buffer_desc output_buffer_desc =
4518 .length = actual_width * actual_height * 4,
4519 .compare = compare_rgb32, .dump = dump_rgb32, .rect = {.top = 12, .right = 82, .bottom = 96},
4521 const struct attribute_desc output_sample_attributes[] =
4523 ATTR_UINT32(MFSampleExtension_CleanPoint, 1, .todo = TRUE),
4524 {0},
4526 const struct sample_desc output_sample_desc =
4528 .attributes = output_sample_attributes,
4529 .sample_time = 0, .sample_duration = 10000000,
4530 .buffer_count = 1, .buffers = &output_buffer_desc,
4533 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
4534 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_I420};
4535 DWORD i, j, k, flags, length, output_status;
4536 IMFSample *input_sample, *output_sample;
4537 IMFMediaType *media_type, *media_type2;
4538 const GUID *expect_available_inputs;
4539 IMFCollection *output_samples;
4540 const BYTE *nv12frame_data;
4541 ULONG nv12frame_data_len;
4542 IMFTransform *transform;
4543 IMFMediaBuffer *buffer;
4544 UINT32 count;
4545 HRESULT hr;
4546 ULONG ret;
4547 GUID guid;
4548 LONG ref;
4550 hr = CoInitialize(NULL);
4551 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
4553 winetest_push_context("videoproc");
4555 if (!check_mft_enum(MFT_CATEGORY_VIDEO_PROCESSOR, &input_type, &output_type, class_id))
4556 goto failed;
4557 check_mft_get_info(class_id, &expect_mft_info);
4559 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
4560 &IID_IMFTransform, (void **)&transform)))
4561 goto failed;
4563 todo_wine
4564 check_interface(transform, &IID_IMFVideoProcessorControl, TRUE);
4565 todo_wine
4566 check_interface(transform, &IID_IMFRealTimeClientEx, TRUE);
4567 check_interface(transform, &IID_IMFMediaEventGenerator, FALSE);
4568 check_interface(transform, &IID_IMFShutdown, FALSE);
4570 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
4571 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
4573 hr = IMFTransform_GetOutputStatus(transform, &flags);
4574 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
4576 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
4577 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
4579 check_mft_get_input_current_type(transform, NULL);
4580 check_mft_get_output_current_type(transform, NULL);
4582 check_mft_get_input_stream_info(transform, S_OK, &initial_input_info);
4583 check_mft_get_output_stream_info(transform, S_OK, &initial_output_info);
4585 /* Configure stream types. */
4586 for (i = 0;;++i)
4588 if (FAILED(hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type)))
4590 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
4591 break;
4594 hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type2);
4595 ok(hr == S_OK, "Failed to get available type, hr %#lx.\n", hr);
4596 ok(media_type != media_type2, "Unexpected instance.\n");
4597 ref = IMFMediaType_Release(media_type2);
4598 ok(ref == 0, "Release returned %ld\n", ref);
4600 hr = IMFMediaType_GetMajorType(media_type, &guid);
4601 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
4602 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type.\n");
4604 hr = IMFMediaType_GetCount(media_type, &count);
4605 ok(hr == S_OK, "Failed to get attributes count, hr %#lx.\n", hr);
4606 ok(count == 2, "Unexpected count %u.\n", count);
4608 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
4609 ok(hr == S_OK, "Failed to get subtype, hr %#lx.\n", hr);
4610 ok(is_supported_video_type(&guid), "Unexpected media type %s.\n", wine_dbgstr_guid(&guid));
4612 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
4613 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
4615 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
4616 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
4618 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type2);
4619 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
4621 /* FIXME: figure out if those require additional attributes or simply advertised but not supported */
4622 if (IsEqualGUID(&guid, &MFVideoFormat_L8) || IsEqualGUID(&guid, &MFVideoFormat_L16)
4623 || IsEqualGUID(&guid, &MFVideoFormat_D16) || IsEqualGUID(&guid, &MFVideoFormat_420O)
4624 || IsEqualGUID(&guid, &MFVideoFormat_A16B16G16R16F))
4626 ref = IMFMediaType_Release(media_type);
4627 ok(ref == 0, "Release returned %ld\n", ref);
4628 continue;
4631 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
4632 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4634 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
4635 ok(hr == S_OK, "Failed to test input type %s, hr %#lx.\n", wine_dbgstr_guid(&guid), hr);
4637 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
4638 ok(hr == S_OK, "Failed to test input type, hr %#lx.\n", hr);
4640 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type2);
4641 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
4642 ok(media_type != media_type2, "Unexpected instance.\n");
4643 IMFMediaType_Release(media_type2);
4645 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
4646 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
4647 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected input status %#lx.\n", flags);
4649 input_info.cbSize = 0;
4650 if (!IsEqualGUID(&guid, &MFVideoFormat_P208) && !IsEqualGUID(&guid, &MEDIASUBTYPE_Y41T)
4651 && !IsEqualGUID(&guid, &MEDIASUBTYPE_Y42T))
4653 hr = MFCalculateImageSize(&guid, 16, 16, (UINT32 *)&input_info.cbSize);
4654 todo_wine_if(IsEqualGUID(&guid, &MFVideoFormat_NV11) || IsEqualGUID(&guid, &MFVideoFormat_YVYU)
4655 || IsEqualGUID(&guid, &MFVideoFormat_Y216) || IsEqualGUID(&guid, &MFVideoFormat_v410)
4656 || IsEqualGUID(&guid, &MFVideoFormat_Y41P))
4657 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4659 check_mft_get_input_stream_info(transform, S_OK, &input_info);
4660 check_mft_get_output_stream_info(transform, S_OK, &initial_output_info);
4662 IMFMediaType_Release(media_type);
4665 /* IYUV -> RGB32 */
4666 hr = MFCreateMediaType(&media_type);
4667 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
4669 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
4670 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4672 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_IYUV);
4673 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4675 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
4676 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4678 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
4679 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
4681 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
4682 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
4684 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
4685 ok(hr == S_OK, "Failed to set output type, hr %#lx.\n", hr);
4687 hr = MFCalculateImageSize(&MFVideoFormat_IYUV, 16, 16, (UINT32 *)&input_info.cbSize);
4688 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4689 hr = MFCalculateImageSize(&MFVideoFormat_RGB32, 16, 16, (UINT32 *)&output_info.cbSize);
4690 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4691 check_mft_get_input_stream_info(transform, S_OK, &input_info);
4692 check_mft_get_output_stream_info(transform, S_OK, &output_info);
4694 hr = MFCreateSample(&input_sample);
4695 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
4697 hr = MFCreateSample(&output_sample);
4698 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
4700 hr = check_mft_process_output(transform, output_sample, &output_status);
4701 todo_wine
4702 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#lx.\n", hr);
4704 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
4705 todo_wine
4706 ok(hr == S_OK, "Failed to push a sample, hr %#lx.\n", hr);
4708 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
4709 todo_wine
4710 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#lx.\n", hr);
4712 hr = check_mft_process_output(transform, output_sample, &output_status);
4713 todo_wine
4714 ok(hr == MF_E_NO_SAMPLE_TIMESTAMP, "Unexpected hr %#lx.\n", hr);
4716 hr = IMFSample_SetSampleTime(input_sample, 0);
4717 ok(hr == S_OK, "Failed to set sample time, hr %#lx.\n", hr);
4718 hr = check_mft_process_output(transform, output_sample, &output_status);
4719 todo_wine
4720 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4722 hr = MFCreateMemoryBuffer(1024 * 1024, &buffer);
4723 ok(hr == S_OK, "Failed to create a buffer, hr %#lx.\n", hr);
4725 hr = IMFSample_AddBuffer(input_sample, buffer);
4726 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
4728 hr = IMFSample_AddBuffer(output_sample, buffer);
4729 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
4731 hr = check_mft_process_output(transform, output_sample, &output_status);
4732 todo_wine
4733 ok(hr == S_OK || broken(FAILED(hr)) /* Win8 */, "Failed to get output buffer, hr %#lx.\n", hr);
4735 if (SUCCEEDED(hr))
4737 hr = check_mft_process_output(transform, output_sample, &output_status);
4738 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#lx.\n", hr);
4741 ref = IMFTransform_Release(transform);
4742 ok(ref == 0, "Release returned %ld\n", ref);
4744 ref = IMFMediaType_Release(media_type);
4745 ok(ref == 0, "Release returned %ld\n", ref);
4746 ref = IMFSample_Release(input_sample);
4747 ok(ref == 0, "Release returned %ld\n", ref);
4748 ref = IMFSample_Release(output_sample);
4749 ok(ref == 0, "Release returned %ld\n", ref);
4750 ref = IMFMediaBuffer_Release(buffer);
4751 ok(ref == 0, "Release returned %ld\n", ref);
4754 hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)&transform);
4755 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4757 check_interface(transform, &IID_IMFTransform, TRUE);
4758 check_interface(transform, &IID_IMediaObject, FALSE);
4759 check_interface(transform, &IID_IPropertyStore, FALSE);
4760 check_interface(transform, &IID_IPropertyBag, FALSE);
4762 check_mft_optional_methods(transform);
4763 check_mft_get_attributes(transform, expect_transform_attributes, TRUE);
4764 check_mft_get_input_stream_info(transform, S_OK, &initial_input_info);
4765 check_mft_get_output_stream_info(transform, S_OK, &initial_output_info);
4767 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
4768 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
4770 hr = IMFTransform_GetInputAvailableType(transform, 0, 23, &media_type);
4771 ok(hr == S_OK || hr == MF_E_NO_MORE_TYPES /* w8 */, "GetOutputAvailableType returned %#lx\n", hr);
4772 if (hr == MF_E_NO_MORE_TYPES)
4773 expect_available_inputs = expect_available_inputs_w8;
4774 else
4776 hr = IMFTransform_GetInputAvailableType(transform, 0, 27, &media_type);
4777 ok(hr == S_OK || broken(hr == MF_E_NO_MORE_TYPES) /* w1064v1507 */, "GetOutputAvailableType returned %#lx\n", hr);
4778 if (hr == MF_E_NO_MORE_TYPES)
4779 expect_available_inputs = expect_available_inputs_w10 + 3;
4780 else
4781 expect_available_inputs = expect_available_inputs_w10;
4784 i = -1;
4785 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
4787 /* FIXME: Skip exotic input types which aren't directly accepted */
4788 if (IsEqualGUID(&expect_available_inputs[i], &MFVideoFormat_L8)
4789 || IsEqualGUID(&expect_available_inputs[i], &MFVideoFormat_L16)
4790 || IsEqualGUID(&expect_available_inputs[i], &MFAudioFormat_MPEG)
4791 || IsEqualGUID(&expect_available_inputs[i], &MFVideoFormat_420O)
4792 || IsEqualGUID(&expect_available_inputs[i], &MFVideoFormat_A16B16G16R16F) /* w1064v1507 */)
4793 continue;
4795 winetest_push_context("in %lu", i);
4796 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
4797 check_media_type(media_type, expect_available_common, -1);
4799 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
4800 ok(hr == S_OK, "GetGUID returned %#lx\n", hr);
4802 /* w1064v1507 doesn't expose MFVideoFormat_ABGR32 input */
4803 if (broken(IsEqualGUID(&expect_available_inputs[i], &MFVideoFormat_ABGR32)
4804 && IsEqualGUID(&guid, &MFVideoFormat_RGB32)))
4805 expect_available_inputs++;
4807 ok(IsEqualGUID(&expect_available_inputs[i], &guid), "got subtype %s\n", debugstr_guid(&guid));
4809 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
4810 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
4812 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)actual_width << 32 | actual_height);
4813 ok(hr == S_OK, "SetUINT64 returned %#lx.\n", hr);
4814 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
4815 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
4817 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type2);
4818 ok(hr == S_OK, "GetOutputAvailableType returned %#lx.\n", hr);
4819 hr = IMFMediaType_IsEqual(media_type, media_type2, &flags);
4820 ok(hr == S_OK, "IsEqual returned %#lx.\n", hr);
4821 IMFMediaType_Release(media_type2);
4823 ret = IMFMediaType_Release(media_type);
4824 ok(ret == 1, "Release returned %lu\n", ret);
4826 j = k = 0;
4827 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++j, &media_type)))
4829 winetest_push_context("out %lu", j);
4830 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
4831 check_media_type(media_type, expect_available_common, -1);
4833 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
4834 ok(hr == S_OK, "GetGUID returned %#lx\n", hr);
4836 for (; k < ARRAY_SIZE(expect_available_outputs); k++)
4837 if (IsEqualGUID(&expect_available_outputs[k], &guid))
4838 break;
4839 ok(k < ARRAY_SIZE(expect_available_outputs), "got subtype %s\n", debugstr_guid(&guid));
4841 ret = IMFMediaType_Release(media_type);
4842 ok(ret == 0, "Release returned %lu\n", ret);
4843 winetest_pop_context();
4845 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
4847 winetest_pop_context();
4849 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
4850 ok(i == 22 || i == 30 || broken(i == 26) /* w1064v1507 */, "%lu input media types\n", i);
4852 check_mft_set_input_type_required(transform, input_type_desc);
4853 check_mft_set_input_type(transform, input_type_desc);
4854 check_mft_get_input_current_type(transform, input_type_desc);
4856 check_mft_set_output_type_required(transform, output_type_desc);
4857 check_mft_set_output_type(transform, output_type_desc, S_OK);
4858 check_mft_get_output_current_type(transform, output_type_desc);
4860 input_info.cbSize = actual_width * actual_height * 3 / 2;
4861 output_info.cbSize = actual_width * actual_height * 4;
4862 check_mft_get_input_stream_info(transform, S_OK, &input_info);
4863 check_mft_get_output_stream_info(transform, S_OK, &output_info);
4865 load_resource(L"nv12frame.bmp", &nv12frame_data, &nv12frame_data_len);
4866 /* skip BMP header and RGB data from the dump */
4867 length = *(DWORD *)(nv12frame_data + 2);
4868 nv12frame_data_len = nv12frame_data_len - length;
4869 nv12frame_data = nv12frame_data + length;
4870 ok(nv12frame_data_len == 13824, "got length %lu\n", nv12frame_data_len);
4872 input_sample = create_sample(nv12frame_data, nv12frame_data_len);
4873 hr = IMFSample_SetSampleTime(input_sample, 0);
4874 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
4875 hr = IMFSample_SetSampleDuration(input_sample, 10000000);
4876 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
4877 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
4878 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
4879 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
4880 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
4881 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
4882 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
4883 ret = IMFSample_Release(input_sample);
4884 ok(ret <= 1, "Release returned %ld\n", ret);
4886 hr = MFCreateCollection(&output_samples);
4887 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
4889 output_sample = create_sample(NULL, output_info.cbSize);
4890 hr = check_mft_process_output(transform, output_sample, &output_status);
4891 ok(hr == S_OK || broken(hr == MF_E_SHUTDOWN) /* w8 */, "ProcessOutput returned %#lx\n", hr);
4892 if (hr != S_OK)
4894 win_skip("ProcessOutput returned MF_E_SHUTDOWN, skipping tests.\n");
4895 goto skip_output;
4897 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
4899 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
4900 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
4901 ref = IMFSample_Release(output_sample);
4902 ok(ref == 1, "Release returned %ld\n", ref);
4904 ret = check_mf_sample_collection(output_samples, &output_sample_desc, L"rgb32frame-vp.bmp");
4905 todo_wine
4906 ok(ret == 0 || broken(ret == 25) /* w1064v1507 / w1064v1809 incorrectly rescale */, "got %lu%% diff\n", ret);
4907 IMFCollection_Release(output_samples);
4909 output_sample = create_sample(NULL, output_info.cbSize);
4910 hr = check_mft_process_output(transform, output_sample, &output_status);
4911 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
4912 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
4913 hr = IMFSample_GetTotalLength(output_sample, &length);
4914 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
4915 ok(length == 0, "got length %lu\n", length);
4917 skip_output:
4918 ret = IMFSample_Release(output_sample);
4919 ok(ret == 0, "Release returned %lu\n", ret);
4921 ret = IMFTransform_Release(transform);
4922 ok(ret == 0, "Release returned %ld\n", ret);
4924 failed:
4925 winetest_pop_context();
4926 CoUninitialize();
4929 static void test_mp3_decoder(void)
4931 const GUID *const class_id = &CLSID_CMP3DecMediaObject;
4932 const struct transform_info expect_mft_info =
4934 .name = L"MP3 Decoder MFT",
4935 .major_type = &MFMediaType_Audio,
4936 .inputs =
4938 {.subtype = &MFAudioFormat_MP3},
4940 .outputs =
4942 {.subtype = &MFAudioFormat_PCM},
4945 const struct transform_info expect_dmo_info =
4947 .name = L"MP3 Decoder DMO",
4948 .major_type = &MEDIATYPE_Audio,
4949 .inputs =
4951 {.subtype = &MFAudioFormat_MP3},
4953 .outputs =
4955 {.subtype = &MEDIASUBTYPE_PCM},
4959 static const ULONG mp3dec_block_size = 0x1200;
4960 static const media_type_desc expect_available_inputs[] =
4963 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
4964 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3),
4965 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4968 static const media_type_desc expect_available_outputs[] =
4971 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
4972 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
4973 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
4974 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
4975 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
4976 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
4977 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
4978 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4981 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
4982 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
4983 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
4984 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
4985 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
4986 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
4987 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
4988 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4991 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
4992 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
4993 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
4994 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
4995 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
4996 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
4997 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2),
4998 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
5001 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5002 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
5003 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
5004 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
5005 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
5006 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
5007 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
5008 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
5011 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5012 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
5013 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
5014 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
5015 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
5016 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
5017 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2),
5018 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
5021 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5022 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
5023 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
5024 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
5025 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
5026 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 22050),
5027 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
5028 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
5032 const struct attribute_desc input_type_desc[] =
5034 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
5035 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3, .required = TRUE),
5036 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
5037 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
5038 {0},
5040 static const struct attribute_desc output_type_desc[] =
5042 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
5043 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM, .required = TRUE),
5044 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
5045 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
5046 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
5047 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2 * (16 / 8), .required = TRUE),
5048 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * (16 / 8) * 22050, .required = TRUE),
5049 {0},
5051 const struct attribute_desc expect_input_type_desc[] =
5053 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5054 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3),
5055 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
5056 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
5057 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
5058 {0},
5060 static const struct attribute_desc expect_output_type_desc[] =
5062 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
5063 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
5064 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
5065 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
5066 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
5067 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
5068 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 22050 * 4),
5069 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
5070 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
5071 {0},
5073 const MFT_OUTPUT_STREAM_INFO output_info =
5075 .cbSize = mp3dec_block_size,
5076 .cbAlignment = 1,
5078 const MFT_INPUT_STREAM_INFO input_info =
5080 .cbAlignment = 1,
5083 const struct buffer_desc output_buffer_desc[] =
5085 {.length = 0x9c0, .compare = compare_pcm16},
5086 {.length = mp3dec_block_size, .compare = compare_pcm16},
5088 const struct attribute_desc output_sample_attributes[] =
5090 ATTR_UINT32(mft_output_sample_incomplete, 1),
5091 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
5092 {0},
5094 const struct sample_desc output_sample_desc[] =
5097 .attributes = output_sample_attributes + 0,
5098 .sample_time = 0, .sample_duration = 282993,
5099 .buffer_count = 1, .buffers = output_buffer_desc + 0,
5102 .attributes = output_sample_attributes + 0,
5103 .sample_time = 282993, .sample_duration = 522449,
5104 .buffer_count = 1, .buffers = output_buffer_desc + 1, .repeat_count = 18,
5107 .attributes = output_sample_attributes + 1, /* not MFT_OUTPUT_DATA_BUFFER_INCOMPLETE */
5108 .sample_time = 10209524, .sample_duration = 522449,
5109 .buffer_count = 1, .buffers = output_buffer_desc + 1,
5113 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_PCM};
5114 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_MP3};
5115 IMFSample *input_sample, *output_sample;
5116 IMFCollection *output_samples;
5117 DWORD length, output_status;
5118 IMFMediaType *media_type;
5119 IMFTransform *transform;
5120 const BYTE *mp3enc_data;
5121 ULONG mp3enc_data_len;
5122 ULONG i, ret, ref;
5123 HRESULT hr;
5125 hr = CoInitialize(NULL);
5126 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
5128 winetest_push_context("mp3dec");
5130 if (!check_mft_enum(MFT_CATEGORY_AUDIO_DECODER, &input_type, &output_type, class_id))
5131 goto failed;
5132 check_mft_get_info(class_id, &expect_mft_info);
5133 check_dmo_get_info(class_id, &expect_dmo_info);
5135 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
5136 &IID_IMFTransform, (void **)&transform)))
5137 goto failed;
5139 check_interface(transform, &IID_IMFTransform, TRUE);
5140 check_interface(transform, &IID_IMediaObject, TRUE);
5141 todo_wine
5142 check_interface(transform, &IID_IPropertyStore, TRUE);
5143 check_interface(transform, &IID_IPropertyBag, FALSE);
5145 check_mft_optional_methods(transform);
5146 check_mft_get_attributes(transform, NULL, FALSE);
5147 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
5148 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
5150 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
5151 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
5153 i = -1;
5154 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
5156 winetest_push_context("in %lu", i);
5157 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
5158 check_media_type(media_type, expect_available_inputs[i], -1);
5159 ret = IMFMediaType_Release(media_type);
5160 ok(ret == 0, "Release returned %lu\n", ret);
5161 winetest_pop_context();
5163 todo_wine
5164 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
5165 todo_wine
5166 ok(i == ARRAY_SIZE(expect_available_inputs), "%lu input media types\n", i);
5168 /* setting output media type first doesn't work */
5169 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
5170 check_mft_get_output_current_type(transform, NULL);
5172 check_mft_set_input_type_required(transform, input_type_desc);
5173 check_mft_set_input_type(transform, input_type_desc);
5174 check_mft_get_input_current_type(transform, expect_input_type_desc);
5176 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
5177 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
5179 /* check new output media types */
5181 i = -1;
5182 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
5184 winetest_push_context("out %lu", i);
5185 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
5186 check_media_type(media_type, expect_available_outputs[i], -1);
5187 ret = IMFMediaType_Release(media_type);
5188 ok(ret == 0, "Release returned %lu\n", ret);
5189 winetest_pop_context();
5191 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
5192 ok(i == ARRAY_SIZE(expect_available_outputs), "%lu output media types\n", i);
5194 check_mft_set_output_type_required(transform, output_type_desc);
5195 check_mft_set_output_type(transform, output_type_desc, S_OK);
5196 check_mft_get_output_current_type(transform, expect_output_type_desc);
5198 check_mft_get_input_stream_info(transform, S_OK, &input_info);
5199 check_mft_get_output_stream_info(transform, S_OK, &output_info);
5201 load_resource(L"mp3encdata.bin", &mp3enc_data, &mp3enc_data_len);
5202 ok(mp3enc_data_len == 6295, "got length %lu\n", mp3enc_data_len);
5204 input_sample = create_sample(mp3enc_data, mp3enc_data_len);
5205 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
5206 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
5207 ret = IMFSample_Release(input_sample);
5208 ok(ret == 1, "Release returned %lu\n", ret);
5210 input_sample = create_sample(mp3enc_data, mp3enc_data_len);
5211 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
5212 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
5213 ret = IMFSample_Release(input_sample);
5214 ok(ret == 0, "Release returned %lu\n", ret);
5216 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
5217 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
5219 hr = MFCreateCollection(&output_samples);
5220 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
5222 /* first sample is broken */
5223 output_sample = create_sample(NULL, output_info.cbSize);
5224 hr = check_mft_process_output(transform, output_sample, &output_status);
5225 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
5226 ok(output_status == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE, "got output[0].dwStatus %#lx\n", output_status);
5227 hr = IMFSample_GetTotalLength(output_sample, &length);
5228 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
5229 ok(length == mp3dec_block_size /* Win8 */ || length == 0x9c0 /* Win10 */ || length == 0x900 /* Win7 */,
5230 "got length %lu\n", length);
5231 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
5232 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
5233 ref = IMFSample_Release(output_sample);
5234 ok(ref == 1, "Release returned %ld\n", ref);
5236 output_sample = create_sample(NULL, output_info.cbSize);
5237 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
5239 winetest_push_context("%lu", i);
5240 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
5241 ok(!(output_status & ~MFT_OUTPUT_DATA_BUFFER_INCOMPLETE), "got output[0].dwStatus %#lx\n", output_status);
5242 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
5243 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
5244 ref = IMFSample_Release(output_sample);
5245 ok(ref == 1, "Release returned %ld\n", ref);
5246 output_sample = create_sample(NULL, output_info.cbSize);
5247 winetest_pop_context();
5249 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
5250 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
5251 ret = IMFSample_Release(output_sample);
5252 ok(ret == 0, "Release returned %lu\n", ret);
5253 ok(i == 20 || broken(i == 41) /* Win7 */, "got %lu output samples\n", i);
5255 if (broken(length != 0x9c0))
5256 win_skip("Skipping MP3 decoder output sample checks on Win7 / Win8\n");
5257 else
5259 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"mp3decdata.bin");
5260 ok(ret == 0, "got %lu%% diff\n", ret);
5262 IMFCollection_Release(output_samples);
5264 output_sample = create_sample(NULL, mp3dec_block_size);
5265 hr = check_mft_process_output(transform, output_sample, &output_status);
5266 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
5267 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
5268 hr = IMFSample_GetTotalLength(output_sample, &length);
5269 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
5270 ok(length == 0, "got length %lu\n", length);
5271 ret = IMFSample_Release(output_sample);
5272 ok(ret == 0, "Release returned %lu\n", ret);
5274 ret = IMFTransform_Release(transform);
5275 ok(ret == 0, "Release returned %lu\n", ret);
5277 failed:
5278 winetest_pop_context();
5279 CoUninitialize();
5282 START_TEST(transform)
5284 init_functions();
5286 test_sample_copier();
5287 test_sample_copier_output_processing();
5288 test_aac_encoder();
5289 test_aac_decoder();
5290 test_wma_encoder();
5291 test_wma_decoder();
5292 test_h264_decoder();
5293 test_wmv_decoder();
5294 test_audio_convert();
5295 test_color_convert();
5296 test_video_processor();
5297 test_mp3_decoder();