mf/tests: Split create_transform into check_(mft|dmo)_(enum|get_info).
[wine.git] / dlls / mf / tests / transform.c
blob2bcb3805a14265b6b2a312d13bd20541e8a0e251
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(MFVideoFormat_ABGR32,0x00000020,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
49 DEFINE_GUID(MFVideoFormat_P208,0x38303250,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
51 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
52 static void _expect_ref(IUnknown* obj, ULONG expected_refcount, int line)
54 ULONG refcount;
55 IUnknown_AddRef(obj);
56 refcount = IUnknown_Release(obj);
57 ok_(__FILE__, line)(refcount == expected_refcount, "Unexpected refcount %ld, expected %ld.\n", refcount,
58 expected_refcount);
61 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
62 static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported)
64 IUnknown *iface = iface_ptr;
65 HRESULT hr, expected_hr;
66 IUnknown *unk;
68 expected_hr = supported ? S_OK : E_NOINTERFACE;
70 hr = IUnknown_QueryInterface(iface, iid, (void **)&unk);
71 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#lx, expected %#lx.\n", hr, expected_hr);
72 if (SUCCEEDED(hr))
73 IUnknown_Release(unk);
76 void check_attributes_(int line, IMFAttributes *attributes, const struct attribute_desc *desc, ULONG limit)
78 char buffer[256], *buf = buffer;
79 PROPVARIANT value;
80 int i, j, ret;
81 HRESULT hr;
83 for (i = 0; i < limit && desc[i].key; ++i)
85 hr = IMFAttributes_GetItem(attributes, desc[i].key, &value);
86 todo_wine_if(desc[i].todo)
87 ok_(__FILE__, line)(hr == S_OK, "%s missing, hr %#lx\n", debugstr_a(desc[i].name), hr);
88 if (hr != S_OK) continue;
90 switch (value.vt)
92 default: sprintf(buffer, "??"); break;
93 case VT_CLSID: sprintf(buffer, "%s", debugstr_guid(value.puuid)); break;
94 case VT_UI4: sprintf(buffer, "%lu", value.ulVal); break;
95 case VT_UI8:
96 if (desc[i].ratio)
97 sprintf(buffer, "%lu:%lu", value.uhVal.HighPart, value.uhVal.LowPart);
98 else
99 sprintf(buffer, "%I64u", value.uhVal.QuadPart);
100 break;
101 case VT_VECTOR | VT_UI1:
102 buf += sprintf(buf, "size %lu, data {", value.caub.cElems);
103 for (j = 0; j < 16 && j < value.caub.cElems; ++j)
104 buf += sprintf(buf, "0x%02x,", value.caub.pElems[j]);
105 if (value.caub.cElems > 16)
106 buf += sprintf(buf, "...}");
107 else
108 buf += sprintf(buf - (j ? 1 : 0), "}");
109 break;
112 ret = PropVariantCompareEx(&value, &desc[i].value, 0, 0);
113 todo_wine_if(desc[i].todo_value)
114 ok_(__FILE__, line)(ret == 0, "%s mismatch, type %u, value %s\n",
115 debugstr_a(desc[i].name), value.vt, buffer);
119 struct transform_info
121 const WCHAR *name;
122 const GUID *major_type;
123 struct
125 const GUID *subtype;
126 } inputs[32], input_end, outputs[32], output_end;
129 static BOOL check_mft_enum(GUID category, MFT_REGISTER_TYPE_INFO *input_type,
130 MFT_REGISTER_TYPE_INFO *output_type, const GUID *expect_class_id)
132 GUID *class_ids = NULL;
133 UINT32 count = 0, i;
134 HRESULT hr;
136 hr = MFTEnum(category, 0, input_type, output_type, NULL, &class_ids, &count);
137 if (FAILED(hr) || count == 0)
139 todo_wine
140 win_skip("MFTEnum returned %#lx, count %u, skipping tests.\n", hr, count);
141 return FALSE;
144 ok(hr == S_OK, "MFTEnum returned %#lx\n", hr);
145 for (i = 0; i < count; ++i)
146 if (IsEqualGUID(expect_class_id, class_ids + i))
147 break;
148 ok(i < count, "Failed to find transform.\n");
149 CoTaskMemFree(class_ids);
151 return i < count;
154 static void check_mft_get_info(const GUID *class_id, const struct transform_info *expect)
156 MFT_REGISTER_TYPE_INFO *input_types = NULL, *output_types = NULL;
157 UINT32 input_count = 0, output_count = 0, i;
158 WCHAR *name;
159 HRESULT hr;
161 hr = MFTGetInfo(*class_id, &name, &input_types, &input_count, &output_types, &output_count, NULL);
162 ok(hr == S_OK, "MFTEnum returned %#lx\n", hr);
163 ok(!wcscmp(name, expect->name), "got name %s\n", debugstr_w(name));
165 for (i = 0; i < input_count && expect->inputs[i].subtype; ++i)
167 ok(IsEqualGUID(&input_types[i].guidMajorType, expect->major_type),
168 "got input[%u] major %s\n", i, debugstr_guid(&input_types[i].guidMajorType));
169 ok(IsEqualGUID(&input_types[i].guidSubtype, expect->inputs[i].subtype),
170 "got input[%u] subtype %s\n", i, debugstr_guid(&input_types[i].guidSubtype));
172 for (; expect->inputs[i].subtype; ++i)
173 ok(0, "missing input[%u] subtype %s\n", i, debugstr_guid(expect->inputs[i].subtype));
174 for (; i < input_count; ++i)
175 ok(0, "extra input[%u] subtype %s\n", i, debugstr_guid(&input_types[i].guidSubtype));
177 for (i = 0; expect->outputs[i].subtype; ++i)
179 ok(IsEqualGUID(&output_types[i].guidMajorType, expect->major_type),
180 "got output[%u] major %s\n", i, debugstr_guid(&output_types[i].guidMajorType));
181 ok(IsEqualGUID(&output_types[i].guidSubtype, expect->outputs[i].subtype),
182 "got output[%u] subtype %s\n", i, debugstr_guid(&output_types[i].guidSubtype));
184 for (; expect->outputs[i].subtype; ++i)
185 ok(0, "missing output[%u] subtype %s\n", i, debugstr_guid(expect->outputs[i].subtype));
186 for (; i < output_count; ++i)
187 ok(0, "extra output[%u] subtype %s\n", i, debugstr_guid(&output_types[i].guidSubtype));
189 CoTaskMemFree(output_types);
190 CoTaskMemFree(input_types);
191 CoTaskMemFree(name);
194 static void check_dmo_get_info(const GUID *class_id, const struct transform_info *expect)
196 DWORD input_count = 0, output_count = 0;
197 DMO_PARTIAL_MEDIATYPE output[32] = {{{0}}};
198 DMO_PARTIAL_MEDIATYPE input[32] = {{{0}}};
199 WCHAR name[80];
200 HRESULT hr;
201 int i;
203 hr = DMOGetName(class_id, name);
204 ok(hr == S_OK, "DMOGetName returned %#lx\n", hr);
205 ok(!wcscmp(name, expect->name), "got name %s\n", debugstr_w(name));
207 hr = DMOGetTypes(class_id, ARRAY_SIZE(input), &input_count, input,
208 ARRAY_SIZE(output), &output_count, output);
209 ok(hr == S_OK, "DMOGetTypes returned %#lx\n", hr);
211 for (i = 0; i < input_count && expect->inputs[i].subtype; ++i)
213 ok(IsEqualGUID(&input[i].type, expect->major_type),
214 "got input[%u] major %s\n", i, debugstr_guid(&input[i].type));
215 ok(IsEqualGUID(&input[i].subtype, expect->inputs[i].subtype),
216 "got input[%u] subtype %s\n", i, debugstr_guid(&input[i].subtype));
218 for (; expect->inputs[i].subtype; ++i)
219 ok(0, "missing input[%u] subtype %s\n", i, debugstr_guid(expect->inputs[i].subtype));
220 for (; i < input_count; ++i)
221 ok(0, "extra input[%u] subtype %s\n", i, debugstr_guid(&input[i].subtype));
223 for (i = 0; expect->outputs[i].subtype; ++i)
225 ok(IsEqualGUID(&output[i].type, expect->major_type),
226 "got output[%u] major %s\n", i, debugstr_guid(&output[i].type));
227 ok(IsEqualGUID(&output[i].subtype, expect->outputs[i].subtype),
228 "got output[%u] subtype %s\n", i, debugstr_guid(&output[i].subtype));
230 for (; expect->outputs[i].subtype; ++i)
231 ok(0, "missing output[%u] subtype %s\n", i, debugstr_guid(expect->outputs[i].subtype));
232 for (; i < output_count; ++i)
233 ok(0, "extra output[%u] subtype %s\n", i, debugstr_guid(&output[i].subtype));
236 void init_media_type(IMFMediaType *mediatype, const struct attribute_desc *desc, ULONG limit)
238 HRESULT hr;
239 ULONG i;
241 hr = IMFMediaType_DeleteAllItems(mediatype);
242 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
244 for (i = 0; i < limit && desc[i].key; ++i)
246 hr = IMFMediaType_SetItem(mediatype, desc[i].key, &desc[i].value);
247 ok(hr == S_OK, "SetItem %s returned %#lx\n", debugstr_a(desc[i].name), hr);
251 static HRESULT WINAPI test_unk_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
253 if (IsEqualIID(riid, &IID_IUnknown))
255 *obj = iface;
256 IUnknown_AddRef(iface);
257 return S_OK;
260 *obj = NULL;
261 return E_NOINTERFACE;
264 static ULONG WINAPI test_unk_AddRef(IUnknown *iface)
266 return 2;
269 static ULONG WINAPI test_unk_Release(IUnknown *iface)
271 return 1;
274 static const IUnknownVtbl test_unk_vtbl =
276 test_unk_QueryInterface,
277 test_unk_AddRef,
278 test_unk_Release,
281 static BOOL is_supported_video_type(const GUID *guid)
283 return IsEqualGUID(guid, &MFVideoFormat_L8)
284 || IsEqualGUID(guid, &MFVideoFormat_L16)
285 || IsEqualGUID(guid, &MFVideoFormat_D16)
286 || IsEqualGUID(guid, &MFVideoFormat_IYUV)
287 || IsEqualGUID(guid, &MFVideoFormat_YV12)
288 || IsEqualGUID(guid, &MFVideoFormat_NV12)
289 || IsEqualGUID(guid, &MFVideoFormat_NV21)
290 || IsEqualGUID(guid, &MFVideoFormat_420O)
291 || IsEqualGUID(guid, &MFVideoFormat_P010)
292 || IsEqualGUID(guid, &MFVideoFormat_P016)
293 || IsEqualGUID(guid, &MFVideoFormat_UYVY)
294 || IsEqualGUID(guid, &MFVideoFormat_YUY2)
295 || IsEqualGUID(guid, &MFVideoFormat_P208)
296 || IsEqualGUID(guid, &MFVideoFormat_NV11)
297 || IsEqualGUID(guid, &MFVideoFormat_AYUV)
298 || IsEqualGUID(guid, &MFVideoFormat_ARGB32)
299 || IsEqualGUID(guid, &MFVideoFormat_RGB32)
300 || IsEqualGUID(guid, &MFVideoFormat_A2R10G10B10)
301 || IsEqualGUID(guid, &MFVideoFormat_A16B16G16R16F)
302 || IsEqualGUID(guid, &MFVideoFormat_RGB24)
303 || IsEqualGUID(guid, &MFVideoFormat_I420)
304 || IsEqualGUID(guid, &MFVideoFormat_YVYU)
305 || IsEqualGUID(guid, &MFVideoFormat_RGB555)
306 || IsEqualGUID(guid, &MFVideoFormat_RGB565)
307 || IsEqualGUID(guid, &MFVideoFormat_RGB8)
308 || IsEqualGUID(guid, &MFVideoFormat_Y216)
309 || IsEqualGUID(guid, &MFVideoFormat_v410)
310 || IsEqualGUID(guid, &MFVideoFormat_Y41P)
311 || IsEqualGUID(guid, &MFVideoFormat_Y41T)
312 || IsEqualGUID(guid, &MFVideoFormat_Y42T)
313 || IsEqualGUID(guid, &MFVideoFormat_ABGR32);
316 static BOOL is_sample_copier_available_type(IMFMediaType *type)
318 GUID major = { 0 };
319 UINT32 count;
320 HRESULT hr;
322 hr = IMFMediaType_GetMajorType(type, &major);
323 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
325 hr = IMFMediaType_GetCount(type, &count);
326 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
327 ok(count == 1, "Unexpected attribute count %u.\n", count);
329 return IsEqualGUID(&major, &MFMediaType_Video) || IsEqualGUID(&major, &MFMediaType_Audio);
332 static void test_sample_copier(void)
334 IMFAttributes *attributes, *attributes2;
335 DWORD in_min, in_max, out_min, out_max;
336 IMFMediaType *mediatype, *mediatype2;
337 MFT_OUTPUT_STREAM_INFO output_info;
338 IMFSample *sample, *client_sample;
339 MFT_INPUT_STREAM_INFO input_info;
340 DWORD input_count, output_count;
341 MFT_OUTPUT_DATA_BUFFER buffer;
342 IMFMediaBuffer *media_buffer;
343 IMFTransform *copier;
344 DWORD flags, status;
345 UINT32 value, count;
346 HRESULT hr;
347 LONG ref;
349 if (!pMFCreateSampleCopierMFT)
351 win_skip("MFCreateSampleCopierMFT() is not available.\n");
352 return;
355 winetest_push_context("copier");
357 hr = pMFCreateSampleCopierMFT(&copier);
358 ok(hr == S_OK, "Failed to create sample copier, hr %#lx.\n", hr);
360 hr = IMFTransform_GetAttributes(copier, &attributes);
361 ok(hr == S_OK, "Failed to get transform attributes, hr %#lx.\n", hr);
362 hr = IMFTransform_GetAttributes(copier, &attributes2);
363 ok(hr == S_OK, "Failed to get transform attributes, hr %#lx.\n", hr);
364 ok(attributes == attributes2, "Unexpected instance.\n");
365 IMFAttributes_Release(attributes2);
366 hr = IMFAttributes_GetCount(attributes, &count);
367 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
368 ok(count == 1, "Unexpected attribute count %u.\n", count);
369 hr = IMFAttributes_GetUINT32(attributes, &MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, &value);
370 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
371 ok(!!value, "Unexpected value %u.\n", value);
372 ref = IMFAttributes_Release(attributes);
373 ok(ref == 1, "Release returned %ld\n", ref);
375 hr = IMFTransform_GetInputStreamAttributes(copier, 0, &attributes);
376 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
378 hr = IMFTransform_GetInputStreamAttributes(copier, 1, &attributes);
379 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
381 hr = IMFTransform_GetOutputStreamAttributes(copier, 0, &attributes);
382 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
384 hr = IMFTransform_GetOutputStreamAttributes(copier, 1, &attributes);
385 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
387 hr = IMFTransform_SetOutputBounds(copier, 0, 0);
388 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
390 /* No dynamic streams. */
391 input_count = output_count = 0;
392 hr = IMFTransform_GetStreamCount(copier, &input_count, &output_count);
393 ok(hr == S_OK, "Failed to get stream count, hr %#lx.\n", hr);
394 ok(input_count == 1 && output_count == 1, "Unexpected streams count.\n");
396 hr = IMFTransform_GetStreamLimits(copier, &in_min, &in_max, &out_min, &out_max);
397 ok(hr == S_OK, "Failed to get stream limits, hr %#lx.\n", hr);
398 ok(in_min == in_max && in_min == 1 && out_min == out_max && out_min == 1, "Unexpected stream limits.\n");
400 hr = IMFTransform_GetStreamIDs(copier, 1, &input_count, 1, &output_count);
401 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
403 hr = IMFTransform_DeleteInputStream(copier, 0);
404 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
406 /* Available types. */
407 hr = IMFTransform_GetInputAvailableType(copier, 0, 0, &mediatype);
408 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
409 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
410 IMFMediaType_Release(mediatype);
412 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype);
413 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
414 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
415 IMFMediaType_Release(mediatype);
417 hr = IMFTransform_GetInputAvailableType(copier, 0, 2, &mediatype);
418 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
420 hr = IMFTransform_GetInputAvailableType(copier, 1, 0, &mediatype);
421 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
423 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype);
424 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
426 hr = IMFTransform_GetOutputAvailableType(copier, 1, 0, &mediatype);
427 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
429 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype);
430 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
432 hr = IMFTransform_GetInputCurrentType(copier, 1, &mediatype);
433 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
435 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype);
436 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
438 hr = IMFTransform_GetOutputCurrentType(copier, 1, &mediatype);
439 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
441 hr = MFCreateSample(&sample);
442 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
444 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
445 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
447 hr = MFCreateMediaType(&mediatype);
448 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
450 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
451 ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr);
453 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
454 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
456 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8);
457 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
459 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
460 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
462 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
463 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
464 ok(!output_info.dwFlags, "Unexpected flags %#lx.\n", output_info.dwFlags);
465 ok(!output_info.cbSize, "Unexpected size %lu.\n", output_info.cbSize);
466 ok(!output_info.cbAlignment, "Unexpected alignment %lu.\n", output_info.cbAlignment);
468 hr = IMFTransform_GetInputStreamInfo(copier, 0, &input_info);
469 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
471 ok(!input_info.hnsMaxLatency, "Unexpected latency %s.\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
472 ok(!input_info.dwFlags, "Unexpected flags %#lx.\n", input_info.dwFlags);
473 ok(!input_info.cbSize, "Unexpected size %lu.\n", input_info.cbSize);
474 ok(!input_info.cbMaxLookahead, "Unexpected lookahead size %lu.\n", input_info.cbMaxLookahead);
475 ok(!input_info.cbAlignment, "Unexpected alignment %lu.\n", input_info.cbAlignment);
477 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
478 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
480 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
481 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
482 ok(!output_info.dwFlags, "Unexpected flags %#lx.\n", output_info.dwFlags);
483 ok(output_info.cbSize == 16 * 16, "Unexpected size %lu.\n", output_info.cbSize);
484 ok(!output_info.cbAlignment, "Unexpected alignment %lu.\n", output_info.cbAlignment);
486 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
487 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
488 IMFMediaType_Release(mediatype2);
490 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2);
491 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
493 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
494 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
496 /* Setting input type resets output type. */
497 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
498 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
499 IMFMediaType_Release(mediatype2);
501 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
502 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
504 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
505 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
507 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype2);
508 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
509 ok(is_sample_copier_available_type(mediatype2), "Unexpected type.\n");
510 IMFMediaType_Release(mediatype2);
512 hr = IMFTransform_GetInputStreamInfo(copier, 0, &input_info);
513 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
514 ok(!input_info.hnsMaxLatency, "Unexpected latency %s.\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
515 ok(!input_info.dwFlags, "Unexpected flags %#lx.\n", input_info.dwFlags);
516 ok(input_info.cbSize == 16 * 16, "Unexpected size %lu.\n", input_info.cbSize);
517 ok(!input_info.cbMaxLookahead, "Unexpected lookahead size %lu.\n", input_info.cbMaxLookahead);
518 ok(!input_info.cbAlignment, "Unexpected alignment %lu.\n", input_info.cbAlignment);
520 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype2);
521 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
522 hr = IMFMediaType_IsEqual(mediatype2, mediatype, &flags);
523 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
524 IMFMediaType_Release(mediatype2);
526 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
527 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
528 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected flags %#lx.\n", flags);
530 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2);
531 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
532 IMFMediaType_Release(mediatype2);
534 hr = IMFTransform_GetOutputStatus(copier, &flags);
535 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
537 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
538 ok(hr == S_OK, "Failed to set output type, hr %#lx.\n", hr);
540 hr = IMFTransform_GetOutputStatus(copier, &flags);
541 ok(hr == S_OK, "Failed to get output status, hr %#lx.\n", hr);
542 ok(!flags, "Unexpected flags %#lx.\n", flags);
544 /* Pushing samples. */
545 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
546 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
548 hr = IMFSample_AddBuffer(sample, media_buffer);
549 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
550 IMFMediaBuffer_Release(media_buffer);
552 EXPECT_REF(sample, 1);
553 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
554 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
555 EXPECT_REF(sample, 2);
557 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
558 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
559 ok(!flags, "Unexpected flags %#lx.\n", flags);
561 hr = IMFTransform_GetOutputStatus(copier, &flags);
562 ok(hr == S_OK, "Failed to get output status, hr %#lx.\n", hr);
563 ok(flags == MFT_OUTPUT_STATUS_SAMPLE_READY, "Unexpected flags %#lx.\n", flags);
565 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
566 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#lx.\n", hr);
568 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
569 ok(hr == S_OK, "Failed to get output info, hr %#lx.\n", hr);
571 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
572 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
574 hr = MFCreateSample(&client_sample);
575 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
577 hr = IMFSample_AddBuffer(client_sample, media_buffer);
578 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
579 IMFMediaBuffer_Release(media_buffer);
581 status = 0;
582 memset(&buffer, 0, sizeof(buffer));
583 buffer.pSample = client_sample;
584 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
585 ok(hr == S_OK, "Failed to get output, hr %#lx.\n", hr);
586 EXPECT_REF(sample, 1);
588 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
589 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Failed to get output, hr %#lx.\n", hr);
591 /* Flushing. */
592 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
593 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
594 EXPECT_REF(sample, 2);
596 hr = IMFTransform_ProcessMessage(copier, MFT_MESSAGE_COMMAND_FLUSH, 0);
597 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
599 ref = IMFSample_Release(sample);
600 ok(ref == 0, "Release returned %ld\n", ref);
601 ref = IMFSample_Release(client_sample);
602 ok(ref == 0, "Release returned %ld\n", ref);
604 ref = IMFTransform_Release(copier);
605 ok(ref == 0, "Release returned %ld\n", ref);
606 ref = IMFMediaType_Release(mediatype);
607 ok(ref == 0, "Release returned %ld\n", ref);
609 winetest_pop_context();
612 struct sample_metadata
614 unsigned int flags;
615 LONGLONG duration;
616 LONGLONG time;
619 static void sample_copier_process(IMFTransform *copier, IMFMediaBuffer *input_buffer,
620 IMFMediaBuffer *output_buffer, const struct sample_metadata *md)
622 static const struct sample_metadata zero_md = { 0, ~0u, ~0u };
623 IMFSample *input_sample, *output_sample;
624 MFT_OUTPUT_DATA_BUFFER buffer;
625 DWORD flags, status;
626 LONGLONG time;
627 HRESULT hr;
628 LONG ref;
630 hr = MFCreateSample(&input_sample);
631 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
633 if (md)
635 hr = IMFSample_SetSampleFlags(input_sample, md->flags);
636 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
638 hr = IMFSample_SetSampleTime(input_sample, md->time);
639 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
641 hr = IMFSample_SetSampleDuration(input_sample, md->duration);
642 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
645 hr = MFCreateSample(&output_sample);
646 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
648 hr = IMFSample_SetSampleFlags(output_sample, ~0u);
649 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
651 hr = IMFSample_SetSampleTime(output_sample, ~0u);
652 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
654 hr = IMFSample_SetSampleDuration(output_sample, ~0u);
655 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
657 hr = IMFSample_AddBuffer(input_sample, input_buffer);
658 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
660 hr = IMFSample_AddBuffer(output_sample, output_buffer);
661 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
663 hr = IMFTransform_ProcessInput(copier, 0, input_sample, 0);
664 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
666 status = 0;
667 memset(&buffer, 0, sizeof(buffer));
668 buffer.pSample = output_sample;
669 hr = IMFTransform_ProcessOutput(copier, 0, 1, &buffer, &status);
670 ok(hr == S_OK, "Failed to get output, hr %#lx.\n", hr);
672 if (!md) md = &zero_md;
674 hr = IMFSample_GetSampleFlags(output_sample, &flags);
675 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
676 ok(md->flags == flags, "Unexpected flags.\n");
677 hr = IMFSample_GetSampleTime(output_sample, &time);
678 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
679 ok(md->time == time, "Unexpected time.\n");
680 hr = IMFSample_GetSampleDuration(output_sample, &time);
681 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
682 ok(md->duration == time, "Unexpected duration.\n");
684 ref = IMFSample_Release(input_sample);
685 ok(ref == 0, "Release returned %ld\n", ref);
686 ref = IMFSample_Release(output_sample);
687 ok(ref == 0, "Release returned %ld\n", ref);
690 static void test_sample_copier_output_processing(void)
692 IMFMediaBuffer *input_buffer, *output_buffer;
693 MFT_OUTPUT_STREAM_INFO output_info;
694 struct sample_metadata md;
695 IMFMediaType *mediatype;
696 IMFTransform *copier;
697 DWORD max_length;
698 HRESULT hr;
699 BYTE *ptr;
700 LONG ref;
702 if (!pMFCreateSampleCopierMFT)
703 return;
705 hr = pMFCreateSampleCopierMFT(&copier);
706 ok(hr == S_OK, "Failed to create sample copier, hr %#lx.\n", hr);
708 /* Configure for 16 x 16 of D3DFMT_X8R8G8B8. */
709 hr = MFCreateMediaType(&mediatype);
710 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
712 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
713 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
715 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
716 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
718 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
719 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
721 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
722 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
724 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
725 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
727 /* Source and destination are linear buffers, destination is twice as large. */
728 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
729 ok(hr == S_OK, "Failed to get output info, hr %#lx.\n", hr);
731 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &output_buffer);
732 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
734 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
735 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
736 memset(ptr, 0xcc, max_length);
737 hr = IMFMediaBuffer_Unlock(output_buffer);
738 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
740 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &input_buffer);
741 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
743 hr = IMFMediaBuffer_Lock(input_buffer, &ptr, &max_length, NULL);
744 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
745 memset(ptr, 0xaa, max_length);
746 hr = IMFMediaBuffer_Unlock(input_buffer);
747 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
748 hr = IMFMediaBuffer_SetCurrentLength(input_buffer, 4);
749 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
751 sample_copier_process(copier, input_buffer, output_buffer, NULL);
753 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
754 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
755 ok(ptr[0] == 0xaa && ptr[4] == 0xcc, "Unexpected buffer contents.\n");
757 hr = IMFMediaBuffer_Unlock(output_buffer);
758 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
760 md.flags = 123;
761 md.time = 10;
762 md.duration = 2;
763 sample_copier_process(copier, input_buffer, output_buffer, &md);
765 ref = IMFMediaBuffer_Release(input_buffer);
766 ok(ref == 0, "Release returned %ld\n", ref);
767 ref = IMFMediaBuffer_Release(output_buffer);
768 ok(ref == 0, "Release returned %ld\n", ref);
770 ref = IMFTransform_Release(copier);
771 ok(ref == 0, "Release returned %ld\n", ref);
772 ref = IMFMediaType_Release(mediatype);
773 ok(ref == 0, "Release returned %ld\n", ref);
776 static IMFSample *create_sample(const BYTE *data, ULONG size)
778 IMFMediaBuffer *media_buffer;
779 IMFSample *sample;
780 DWORD length;
781 BYTE *buffer;
782 HRESULT hr;
783 ULONG ret;
785 hr = MFCreateSample(&sample);
786 ok(hr == S_OK, "MFCreateSample returned %#lx\n", hr);
787 hr = MFCreateMemoryBuffer(size, &media_buffer);
788 ok(hr == S_OK, "MFCreateMemoryBuffer returned %#lx\n", hr);
789 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
790 ok(hr == S_OK, "Lock returned %#lx\n", hr);
791 ok(length == 0, "got length %lu\n", length);
792 if (!data) memset(buffer, 0xcd, size);
793 else memcpy(buffer, data, size);
794 hr = IMFMediaBuffer_Unlock(media_buffer);
795 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
796 hr = IMFMediaBuffer_SetCurrentLength(media_buffer, data ? size : 0);
797 ok(hr == S_OK, "SetCurrentLength returned %#lx\n", hr);
798 hr = IMFSample_AddBuffer(sample, media_buffer);
799 ok(hr == S_OK, "AddBuffer returned %#lx\n", hr);
800 ret = IMFMediaBuffer_Release(media_buffer);
801 ok(ret == 1, "Release returned %lu\n", ret);
803 return sample;
806 #define check_sample(a, b, c) check_sample_(__LINE__, a, b, c)
807 static void check_sample_(int line, IMFSample *sample, const BYTE *expect_buf, HANDLE output_file)
809 IMFMediaBuffer *media_buffer;
810 DWORD length;
811 BYTE *buffer;
812 HRESULT hr;
813 ULONG ret;
815 hr = IMFSample_ConvertToContiguousBuffer(sample, &media_buffer);
816 ok_(__FILE__, line)(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
817 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
818 ok_(__FILE__, line)(hr == S_OK, "Lock returned %#lx\n", hr);
819 ok_(__FILE__, line)(!memcmp(expect_buf, buffer, length), "unexpected buffer data\n");
820 if (output_file) WriteFile(output_file, buffer, length, &length, NULL);
821 hr = IMFMediaBuffer_Unlock(media_buffer);
822 ok_(__FILE__, line)(hr == S_OK, "Unlock returned %#lx\n", hr);
823 ret = IMFMediaBuffer_Release(media_buffer);
824 ok_(__FILE__, line)(ret == 1, "Release returned %lu\n", ret);
827 #define check_sample_rgb32(a, b, c) check_sample_rgb32_(__LINE__, a, b, c)
828 static void check_sample_rgb32_(int line, IMFSample *sample, const BYTE *expect_buf, HANDLE output_file)
830 DWORD i, length, diff = 0, max_diff;
831 IMFMediaBuffer *media_buffer;
832 BYTE *buffer;
833 HRESULT hr;
834 ULONG ret;
836 hr = IMFSample_ConvertToContiguousBuffer(sample, &media_buffer);
837 ok_(__FILE__, line)(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
838 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
839 ok_(__FILE__, line)(hr == S_OK, "Lock returned %#lx\n", hr);
841 /* check that buffer values are "close" enough, there's some pretty big
842 * differences with the color converter between ffmpeg and native.
844 for (i = 0; i < length; i++)
846 if (i % 4 == 3) continue; /* ignore alpha diff */
847 if (!expect_buf[(i & ~3) + 3]) continue; /* ignore transparent pixels */
848 diff += abs((int)expect_buf[i] - (int)buffer[i]);
850 max_diff = length * 3 * 256;
851 ok_(__FILE__, line)(diff * 100 / max_diff == 0, "unexpected buffer data\n");
853 if (output_file) WriteFile(output_file, buffer, length, &length, NULL);
854 hr = IMFMediaBuffer_Unlock(media_buffer);
855 ok_(__FILE__, line)(hr == S_OK, "Unlock returned %#lx\n", hr);
856 ret = IMFMediaBuffer_Release(media_buffer);
857 ok_(__FILE__, line)(ret == 1, "Release returned %lu\n", ret);
860 #define check_sample_pcm16(a, b, c, d) check_sample_pcm16_(__LINE__, a, b, c, d)
861 static void check_sample_pcm16_(int line, IMFSample *sample, const BYTE *expect_buf, HANDLE output_file, BOOL todo)
863 IMFMediaBuffer *media_buffer;
864 DWORD i, length;
865 BYTE *buffer;
866 HRESULT hr;
867 ULONG ret;
869 hr = IMFSample_ConvertToContiguousBuffer(sample, &media_buffer);
870 ok_(__FILE__, line)(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
871 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
872 ok_(__FILE__, line)(hr == S_OK, "Lock returned %#lx\n", hr);
874 /* check that buffer values are close enough, there's some differences in
875 * the output of audio DSP between 32bit and 64bit implementation
877 for (i = 0; i < length; i += 2)
879 DWORD expect = *(INT16 *)(expect_buf + i), value = *(INT16 *)(buffer + i);
880 if (expect - value + 512 > 1024) break;
883 todo_wine_if(todo && i < length / 2)
884 ok_(__FILE__, line)(i == length, "unexpected buffer data\n");
886 if (output_file) WriteFile(output_file, buffer, length, &length, NULL);
887 hr = IMFMediaBuffer_Unlock(media_buffer);
888 ok_(__FILE__, line)(hr == S_OK, "Unlock returned %#lx\n", hr);
889 ret = IMFMediaBuffer_Release(media_buffer);
890 ok_(__FILE__, line)(ret == 1, "Release returned %lu\n", ret);
893 static const BYTE wma_codec_data[10] = {0, 0x44, 0, 0, 0x17, 0, 0, 0, 0, 0};
894 static const ULONG wmaenc_block_size = 1487;
895 static const ULONG wmadec_block_size = 0x2000;
897 static void test_wma_encoder(void)
899 const GUID *const class_id = &CLSID_CWMAEncMediaObject;
900 const struct transform_info expect_mft_info =
902 .name = L"WMAudio Encoder MFT",
903 .major_type = &MFMediaType_Audio,
904 .inputs =
906 {.subtype = &MFAudioFormat_PCM},
907 {.subtype = &MFAudioFormat_Float},
909 .outputs =
911 {.subtype = &MFAudioFormat_WMAudioV8},
912 {.subtype = &MFAudioFormat_WMAudioV9},
913 {.subtype = &MFAudioFormat_WMAudio_Lossless},
916 const struct transform_info expect_dmo_info =
918 .name = L"WMAudio Encoder DMO",
919 .major_type = &MEDIATYPE_Audio,
920 .inputs =
922 {.subtype = &MEDIASUBTYPE_PCM},
924 .outputs =
926 {.subtype = &MEDIASUBTYPE_WMAUDIO2},
927 {.subtype = &MEDIASUBTYPE_WMAUDIO3},
928 {.subtype = &MEDIASUBTYPE_WMAUDIO_LOSSLESS},
932 static const struct attribute_desc input_type_desc[] =
934 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
935 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
936 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
937 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
938 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
939 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
940 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
941 {0},
943 const struct attribute_desc output_type_desc[] =
945 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
946 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
947 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
948 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
949 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003),
950 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size),
951 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)),
952 {0},
955 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8};
956 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_Float};
957 ULONG audio_data_len, wmaenc_data_len;
958 const BYTE *audio_data, *wmaenc_data;
959 MFT_OUTPUT_STREAM_INFO output_info;
960 MFT_INPUT_STREAM_INFO input_info;
961 MFT_OUTPUT_DATA_BUFFER output;
962 WCHAR output_path[MAX_PATH];
963 IMFMediaType *media_type;
964 IMFTransform *transform;
965 DWORD status, length;
966 HANDLE output_file;
967 IMFSample *sample;
968 HRSRC resource;
969 ULONG i, ret;
970 HRESULT hr;
971 LONG ref;
973 hr = CoInitialize(NULL);
974 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
976 winetest_push_context("wmaenc");
978 if (!check_mft_enum(MFT_CATEGORY_AUDIO_ENCODER, &input_type, &output_type, class_id))
979 goto failed;
980 check_mft_get_info(class_id, &expect_mft_info);
981 check_dmo_get_info(class_id, &expect_dmo_info);
983 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
984 &IID_IMFTransform, (void **)&transform)))
985 goto failed;
987 check_interface(transform, &IID_IMFTransform, TRUE);
988 check_interface(transform, &IID_IMediaObject, TRUE);
989 check_interface(transform, &IID_IPropertyStore, TRUE);
990 check_interface(transform, &IID_IPropertyBag, TRUE);
992 hr = MFCreateMediaType(&media_type);
993 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
994 init_media_type(media_type, input_type_desc, -1);
995 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
996 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
997 init_media_type(media_type, output_type_desc, -1);
998 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
999 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
1000 ret = IMFMediaType_Release(media_type);
1001 ok(ret == 0, "Release returned %lu\n", ret);
1003 memset(&input_info, 0xcd, sizeof(input_info));
1004 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
1005 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
1006 ok(input_info.hnsMaxLatency == 19969161, "got hnsMaxLatency %s\n",
1007 wine_dbgstr_longlong(input_info.hnsMaxLatency));
1008 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
1009 ok(input_info.cbSize == 8, "got cbSize %lu\n", input_info.cbSize);
1010 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
1011 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
1013 memset(&output_info, 0xcd, sizeof(output_info));
1014 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
1015 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
1016 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
1017 ok(output_info.cbSize == wmaenc_block_size, "got cbSize %#lx\n", output_info.cbSize);
1018 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
1020 resource = FindResourceW(NULL, L"audiodata.bin", (const WCHAR *)RT_RCDATA);
1021 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
1022 audio_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
1023 audio_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
1024 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
1026 sample = create_sample(audio_data, audio_data_len);
1027 hr = IMFSample_SetSampleTime(sample, 0);
1028 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
1029 hr = IMFSample_SetSampleDuration(sample, 10000000);
1030 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
1031 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
1032 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
1033 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
1034 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
1035 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
1036 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
1037 ref = IMFSample_Release(sample);
1038 ok(ref <= 1, "Release returned %ld\n", ref);
1040 status = 0xdeadbeef;
1041 sample = create_sample(NULL, output_info.cbSize);
1042 memset(&output, 0, sizeof(output));
1043 output.pSample = sample;
1045 resource = FindResourceW(NULL, L"wmaencdata.bin", (const WCHAR *)RT_RCDATA);
1046 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
1047 wmaenc_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
1048 wmaenc_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
1049 ok(wmaenc_data_len % wmaenc_block_size == 0, "got length %lu\n", wmaenc_data_len);
1051 /* and generate a new one as well in a temporary directory */
1052 GetTempPathW(ARRAY_SIZE(output_path), output_path);
1053 lstrcatW(output_path, L"wmaencdata.bin");
1054 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
1055 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
1057 i = 0;
1058 while (SUCCEEDED(hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status)))
1060 winetest_push_context("%lu", i);
1061 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
1062 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
1063 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE ||
1064 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)) /* win7 */,
1065 "got dwStatus %#lx\n", output.dwStatus);
1066 ok(status == 0, "got status %#lx\n", status);
1067 hr = IMFSample_GetTotalLength(sample, &length);
1068 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
1069 ok(length == wmaenc_block_size, "got length %lu\n", length);
1070 ok(wmaenc_data_len > i * wmaenc_block_size, "got %lu blocks\n", i);
1071 check_sample(sample, wmaenc_data + i * wmaenc_block_size, output_file);
1072 winetest_pop_context();
1073 i++;
1076 trace("created %s\n", debugstr_w(output_path));
1077 CloseHandle(output_file);
1079 ret = IMFSample_Release(sample);
1080 ok(ret == 0, "Release returned %lu\n", ret);
1082 status = 0xdeadbeef;
1083 sample = create_sample(NULL, output_info.cbSize);
1084 memset(&output, 0, sizeof(output));
1085 output.pSample = sample;
1086 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
1087 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
1088 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
1089 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
1090 ok(status == 0, "got status %#lx\n", status);
1091 hr = IMFSample_GetTotalLength(sample, &length);
1092 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
1093 ok(length == 0, "got length %lu\n", length);
1094 ret = IMFSample_Release(sample);
1095 ok(ret == 0, "Release returned %lu\n", ret);
1097 ret = IMFTransform_Release(transform);
1098 ok(ret == 0, "Release returned %lu\n", ret);
1100 failed:
1101 winetest_pop_context();
1102 CoUninitialize();
1105 static void test_wma_decoder(void)
1107 const GUID *const class_id = &CLSID_CWMADecMediaObject;
1108 const struct transform_info expect_mft_info =
1110 .name = L"WMAudio Decoder MFT",
1111 .major_type = &MFMediaType_Audio,
1112 .inputs =
1114 {.subtype = &MEDIASUBTYPE_MSAUDIO1},
1115 {.subtype = &MFAudioFormat_WMAudioV8},
1116 {.subtype = &MFAudioFormat_WMAudioV9},
1117 {.subtype = &MFAudioFormat_WMAudio_Lossless},
1119 .outputs =
1121 {.subtype = &MFAudioFormat_PCM},
1122 {.subtype = &MFAudioFormat_Float},
1125 const struct transform_info expect_dmo_info =
1127 .name = L"WMAudio Decoder DMO",
1128 .major_type = &MEDIATYPE_Audio,
1129 .inputs =
1131 {.subtype = &MEDIASUBTYPE_MSAUDIO1},
1132 {.subtype = &MEDIASUBTYPE_WMAUDIO2},
1133 {.subtype = &MEDIASUBTYPE_WMAUDIO3},
1134 {.subtype = &MEDIASUBTYPE_WMAUDIO_LOSSLESS},
1136 .outputs =
1138 {.subtype = &MEDIASUBTYPE_PCM},
1139 {.subtype = &MEDIASUBTYPE_IEEE_FLOAT},
1143 static const media_type_desc expect_available_inputs[] =
1146 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1147 ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_MSAUDIO1),
1148 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
1151 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1152 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
1153 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
1156 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1157 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV9),
1158 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
1161 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1162 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudio_Lossless),
1163 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
1166 static const media_type_desc expect_available_outputs[] =
1169 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1170 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
1171 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
1172 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
1173 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
1174 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
1175 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
1176 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
1177 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
1178 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
1181 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1182 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1183 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
1184 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
1185 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
1186 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
1187 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
1188 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
1189 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
1190 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
1194 const struct attribute_desc input_type_desc[] =
1196 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1197 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
1198 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)),
1199 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size),
1200 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
1201 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
1202 {0},
1204 static const struct attribute_desc output_type_desc[] =
1206 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
1207 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
1208 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
1209 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
1210 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
1211 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
1212 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
1213 {0},
1216 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8};
1217 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_Float};
1218 IUnknown *unknown, *tmp_unknown, outer = {&test_unk_vtbl};
1219 ULONG wmadec_data_len, wmaenc_data_len;
1220 const BYTE *wmadec_data, *wmaenc_data;
1221 MFT_OUTPUT_STREAM_INFO output_info;
1222 MFT_OUTPUT_DATA_BUFFER outputs[2];
1223 MFT_INPUT_STREAM_INFO input_info;
1224 MFT_OUTPUT_DATA_BUFFER output;
1225 DWORD status, flags, length;
1226 WCHAR output_path[MAX_PATH];
1227 IMediaObject *media_object;
1228 IPropertyBag *property_bag;
1229 IMFMediaType *media_type;
1230 IMFTransform *transform;
1231 LONGLONG time, duration;
1232 HANDLE output_file;
1233 IMFSample *sample;
1234 ULONG i, ret, ref;
1235 HRSRC resource;
1236 UINT32 value;
1237 HRESULT hr;
1239 hr = CoInitialize(NULL);
1240 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
1242 winetest_push_context("wmadec");
1244 if (!check_mft_enum(MFT_CATEGORY_AUDIO_DECODER, &input_type, &output_type, class_id))
1245 goto failed;
1246 check_mft_get_info(class_id, &expect_mft_info);
1247 check_dmo_get_info(class_id, &expect_dmo_info);
1249 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
1250 &IID_IMFTransform, (void **)&transform)))
1251 goto failed;
1253 check_interface(transform, &IID_IMFTransform, TRUE);
1254 check_interface(transform, &IID_IMediaObject, TRUE);
1255 todo_wine
1256 check_interface(transform, &IID_IPropertyStore, TRUE);
1257 check_interface(transform, &IID_IPropertyBag, TRUE);
1259 /* check default media types */
1261 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
1262 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
1263 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
1264 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
1265 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
1266 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
1268 i = -1;
1269 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
1271 winetest_push_context("in %lu", i);
1272 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
1273 check_media_type(media_type, expect_available_inputs[i], -1);
1274 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
1275 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
1276 ret = IMFMediaType_Release(media_type);
1277 ok(ret == 0, "Release returned %lu\n", ret);
1278 winetest_pop_context();
1280 todo_wine
1281 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
1282 todo_wine
1283 ok(i == 4, "%lu input media types\n", i);
1285 /* setting output media type first doesn't work */
1287 hr = MFCreateMediaType(&media_type);
1288 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
1289 init_media_type(media_type, output_type_desc, -1);
1290 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
1291 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr);
1292 ret = IMFMediaType_Release(media_type);
1293 ok(ret == 0, "Release returned %lu\n", ret);
1295 /* check required input media type attributes */
1297 hr = MFCreateMediaType(&media_type);
1298 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
1299 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
1300 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
1301 init_media_type(media_type, input_type_desc, 1);
1302 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
1303 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
1304 init_media_type(media_type, input_type_desc, 2);
1305 for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i)
1307 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
1308 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
1309 init_media_type(media_type, input_type_desc, i + 1);
1311 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
1312 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
1313 ret = IMFMediaType_Release(media_type);
1314 ok(ret == 0, "Release returned %lu\n", ret);
1316 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
1317 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
1318 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
1319 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
1321 /* check new output media types */
1323 i = -1;
1324 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
1326 winetest_push_context("out %lu", i);
1327 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
1328 check_media_type(media_type, expect_available_outputs[i], -1);
1329 ret = IMFMediaType_Release(media_type);
1330 ok(ret == 0, "Release returned %lu\n", ret);
1331 winetest_pop_context();
1333 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
1334 ok(i == 2, "%lu output media types\n", i);
1336 /* check required output media type attributes */
1338 hr = MFCreateMediaType(&media_type);
1339 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
1340 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
1341 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
1342 init_media_type(media_type, output_type_desc, 1);
1343 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
1344 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
1345 init_media_type(media_type, output_type_desc, 2);
1346 for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i)
1348 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
1349 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
1350 init_media_type(media_type, output_type_desc, i + 1);
1352 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
1353 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
1354 ret = IMFMediaType_Release(media_type);
1355 ok(ret == 0, "Release returned %lu\n", ret);
1357 memset(&input_info, 0xcd, sizeof(input_info));
1358 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
1359 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
1360 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
1361 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
1362 ok(input_info.cbSize == wmaenc_block_size, "got cbSize %lu\n", input_info.cbSize);
1363 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
1364 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
1366 memset(&output_info, 0xcd, sizeof(output_info));
1367 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
1368 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
1369 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
1370 todo_wine
1371 ok(output_info.cbSize == 0, "got cbSize %#lx\n", output_info.cbSize);
1372 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
1374 /* MF_MT_AUDIO_AVG_BYTES_PER_SECOND isn't required by SetInputType, but is needed for the transform to work */
1376 hr = MFCreateMediaType(&media_type);
1377 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
1378 init_media_type(media_type, input_type_desc, -1);
1379 hr = IMFMediaType_SetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003);
1380 ok(hr == S_OK, "SetUINT32 returned %#lx\n", hr);
1381 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
1382 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
1384 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
1385 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
1387 init_media_type(media_type, output_type_desc, -1);
1388 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
1389 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
1390 ret = IMFMediaType_Release(media_type);
1391 ok(ret == 0, "Release returned %lu\n", ret);
1393 memset(&output_info, 0xcd, sizeof(output_info));
1394 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
1395 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
1396 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
1397 ok(output_info.cbSize == wmadec_block_size, "got cbSize %#lx\n", output_info.cbSize);
1398 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
1400 resource = FindResourceW(NULL, L"wmaencdata.bin", (const WCHAR *)RT_RCDATA);
1401 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
1402 wmaenc_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
1403 wmaenc_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
1404 ok(wmaenc_data_len % wmaenc_block_size == 0, "got length %lu\n", wmaenc_data_len);
1406 sample = create_sample(wmaenc_data, wmaenc_block_size / 2);
1407 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
1408 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
1409 ret = IMFSample_Release(sample);
1410 ok(ret == 0, "Release returned %lu\n", ret);
1411 sample = create_sample(wmaenc_data, wmaenc_block_size + 1);
1412 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
1413 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
1414 ret = IMFSample_Release(sample);
1415 ok(ret == 0, "Release returned %lu\n", ret);
1416 sample = create_sample(wmaenc_data, wmaenc_block_size);
1417 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
1418 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
1419 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
1420 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
1421 ret = IMFSample_Release(sample);
1422 ok(ret == 1, "Release returned %lu\n", ret);
1424 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
1425 * IMFTransform_ProcessOutput needs a sample or returns MF_E_TRANSFORM_NEED_MORE_INPUT */
1427 status = 0xdeadbeef;
1428 memset(&output, 0, sizeof(output));
1429 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
1430 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
1431 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
1432 ok(!output.pSample, "got pSample %p\n", output.pSample);
1433 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE ||
1434 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
1435 "got dwStatus %#lx\n", output.dwStatus);
1436 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
1437 ok(status == 0, "got status %#lx\n", status);
1439 sample = create_sample(wmaenc_data, wmaenc_block_size);
1440 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
1441 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
1442 ret = IMFSample_Release(sample);
1443 ok(ret == 0, "Release returned %lu\n", ret);
1445 status = 0xdeadbeef;
1446 memset(&output, 0, sizeof(output));
1447 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
1448 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
1449 ok(!output.pSample, "got pSample %p\n", output.pSample);
1450 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE ||
1451 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
1452 "got dwStatus %#lx\n", output.dwStatus);
1453 ok(status == 0, "got status %#lx\n", status);
1455 status = 0xdeadbeef;
1456 memset(&output, 0, sizeof(output));
1457 output_info.cbSize = wmadec_block_size;
1458 sample = create_sample(NULL, output_info.cbSize);
1459 outputs[0].pSample = sample;
1460 sample = create_sample(NULL, output_info.cbSize);
1461 outputs[1].pSample = sample;
1462 hr = IMFTransform_ProcessOutput(transform, 0, 2, outputs, &status);
1463 ok(hr == E_INVALIDARG, "ProcessOutput returned %#lx\n", hr);
1464 ref = IMFSample_Release(outputs[0].pSample);
1465 ok(ref == 0, "Release returned %ld\n", ref);
1466 ref = IMFSample_Release(outputs[1].pSample);
1467 ok(ref == 0, "Release returned %ld\n", ref);
1469 resource = FindResourceW(NULL, L"wmadecdata.bin", (const WCHAR *)RT_RCDATA);
1470 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
1471 wmadec_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
1472 wmadec_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
1473 ok(wmadec_data_len == wmadec_block_size * 7 / 2, "got length %lu\n", wmadec_data_len);
1475 /* and generate a new one as well in a temporary directory */
1476 GetTempPathW(ARRAY_SIZE(output_path), output_path);
1477 lstrcatW(output_path, L"wmadecdata.bin");
1478 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
1479 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
1481 status = 0xdeadbeef;
1482 output_info.cbSize = wmadec_block_size;
1483 sample = create_sample(NULL, output_info.cbSize);
1484 memset(&output, 0, sizeof(output));
1485 output.pSample = sample;
1486 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
1488 for (i = 0; i < 4; ++i)
1490 winetest_push_context("%lu", i);
1492 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
1493 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
1494 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || output.dwStatus == 0 ||
1495 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7) || output.dwStatus == 7) /* Win7 */,
1496 "got dwStatus %#lx\n", output.dwStatus);
1497 ok(status == 0, "got status %#lx\n", status);
1498 value = 0xdeadbeef;
1499 hr = IMFSample_GetUINT32(sample, &MFSampleExtension_CleanPoint, &value);
1500 ok(hr == S_OK, "GetUINT32 MFSampleExtension_CleanPoint returned %#lx\n", hr);
1501 ok(value == 1, "got MFSampleExtension_CleanPoint %u\n", value);
1502 hr = IMFSample_GetTotalLength(sample, &length);
1503 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
1504 flags = 0xdeadbeef;
1505 hr = IMFSample_GetSampleFlags(sample, &flags);
1506 ok(hr == S_OK, "GetSampleFlags returned %#lx\n", hr);
1507 ok(flags == 0, "got flags %#lx\n", flags);
1508 time = 0xdeadbeef;
1509 hr = IMFSample_GetSampleTime(sample, &time);
1510 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
1511 ok(time == i * 928798, "got time %I64d\n", time);
1512 duration = 0xdeadbeef;
1513 hr = IMFSample_GetSampleDuration(sample, &duration);
1514 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
1515 if (output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE ||
1516 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)))
1518 ok(length == wmadec_block_size, "got length %lu\n", length);
1519 ok(duration == 928798, "got duration %I64d\n", duration);
1520 check_sample_pcm16(sample, wmadec_data, output_file, TRUE);
1521 wmadec_data += wmadec_block_size;
1522 wmadec_data_len -= wmadec_block_size;
1524 else
1526 /* FFmpeg doesn't seem to decode WMA buffers in the same way as native */
1527 todo_wine
1528 ok(length == wmadec_block_size / 2, "got length %lu\n", length);
1529 todo_wine
1530 ok(duration == 464399, "got duration %I64d\n", duration);
1532 if (length == wmadec_block_size / 2)
1533 check_sample_pcm16(sample, wmadec_data, output_file, FALSE);
1534 wmadec_data += length;
1535 wmadec_data_len -= length;
1537 ret = IMFSample_Release(sample);
1538 ok(ret == 0, "Release returned %lu\n", ret);
1540 status = 0xdeadbeef;
1541 sample = create_sample(NULL, output_info.cbSize);
1542 memset(&output, 0, sizeof(output));
1543 output.pSample = sample;
1544 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
1546 winetest_pop_context();
1548 /* some FFmpeg version request more input to complete decoding */
1549 if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT && i == 2) break;
1551 todo_wine
1552 ok(wmadec_data_len == 0, "missing %#lx bytes\n", wmadec_data_len);
1554 trace("created %s\n", debugstr_w(output_path));
1555 CloseHandle(output_file);
1557 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
1558 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
1559 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
1560 ok(status == 0, "got status %#lx\n", status);
1561 ret = IMFSample_Release(sample);
1562 ok(ret == 0, "Release returned %lu\n", ret);
1564 status = 0xdeadbeef;
1565 sample = create_sample(NULL, output_info.cbSize);
1566 memset(&output, 0, sizeof(output));
1567 output.pSample = sample;
1568 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
1569 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
1570 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
1571 ok(output.dwStatus == 0 ||
1572 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)) /* Win7 */,
1573 "got dwStatus %#lx\n", output.dwStatus);
1574 ok(status == 0, "got status %#lx\n", status);
1575 hr = IMFSample_GetTotalLength(sample, &length);
1576 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
1577 ok(length == 0, "got length %lu\n", length);
1578 ret = IMFSample_Release(sample);
1579 ok(ret == 0, "Release returned %lu\n", ret);
1581 sample = create_sample(wmaenc_data, wmaenc_block_size);
1582 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
1583 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
1585 ret = IMFTransform_Release(transform);
1586 ok(ret == 0, "Release returned %lu\n", ret);
1587 ret = IMFSample_Release(sample);
1588 ok(ret == 0, "Release returned %lu\n", ret);
1590 hr = CoCreateInstance( &CLSID_CWMADecMediaObject, &outer, CLSCTX_INPROC_SERVER, &IID_IUnknown,
1591 (void **)&unknown );
1592 ok( hr == S_OK, "CoCreateInstance returned %#lx\n", hr );
1593 hr = IUnknown_QueryInterface( unknown, &IID_IMFTransform, (void **)&transform );
1594 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
1595 hr = IUnknown_QueryInterface( unknown, &IID_IMediaObject, (void **)&media_object );
1596 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
1597 hr = IUnknown_QueryInterface( unknown, &IID_IPropertyBag, (void **)&property_bag );
1598 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
1599 hr = IUnknown_QueryInterface( media_object, &IID_IUnknown, (void **)&tmp_unknown );
1600 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
1602 ok( unknown != &outer, "got outer IUnknown\n" );
1603 ok( transform != (void *)unknown, "got IUnknown == IMFTransform\n" );
1604 ok( media_object != (void *)unknown, "got IUnknown == IMediaObject\n" );
1605 ok( property_bag != (void *)unknown, "got IUnknown == IPropertyBag\n" );
1606 ok( tmp_unknown != unknown, "got inner IUnknown\n" );
1608 check_interface( unknown, &IID_IPersistPropertyBag, FALSE );
1609 check_interface( unknown, &IID_IAMFilterMiscFlags, FALSE );
1610 check_interface( unknown, &IID_IMediaSeeking, FALSE );
1611 check_interface( unknown, &IID_IMediaPosition, FALSE );
1612 check_interface( unknown, &IID_IReferenceClock, FALSE );
1613 check_interface( unknown, &IID_IBasicAudio, FALSE );
1615 ref = IUnknown_Release( tmp_unknown );
1616 ok( ref == 1, "Release returned %lu\n", ref );
1617 ref = IPropertyBag_Release( property_bag );
1618 ok( ref == 1, "Release returned %lu\n", ref );
1619 ref = IMediaObject_Release( media_object );
1620 ok( ref == 1, "Release returned %lu\n", ref );
1621 ref = IMFTransform_Release( transform );
1622 ok( ref == 1, "Release returned %lu\n", ref );
1623 ref = IUnknown_Release( unknown );
1624 ok( ref == 0, "Release returned %lu\n", ref );
1626 failed:
1627 winetest_pop_context();
1628 CoUninitialize();
1631 #define next_h264_sample(a, b) next_h264_sample_(__LINE__, a, b)
1632 static IMFSample *next_h264_sample_(int line, const BYTE **h264_buf, ULONG *h264_len)
1634 const BYTE *sample_data;
1636 ok_(__FILE__, line)(*h264_len > 4, "invalid h264 length\n");
1637 ok_(__FILE__, line)(*(UINT32 *)*h264_buf == 0x01000000, "invalid h264 buffer\n");
1638 sample_data = *h264_buf;
1640 (*h264_len) -= 4;
1641 (*h264_buf) += 4;
1643 while (*h264_len >= 4 && *(UINT32 *)*h264_buf != 0x01000000)
1645 (*h264_len)--;
1646 (*h264_buf)++;
1649 return create_sample(sample_data, *h264_buf - sample_data);
1652 static void test_h264_decoder(void)
1654 const GUID *const class_id = &CLSID_MSH264DecoderMFT;
1655 const struct transform_info expect_mft_info =
1657 .name = L"Microsoft H264 Video Decoder MFT",
1658 .major_type = &MFMediaType_Video,
1659 .inputs =
1661 {.subtype = &MFVideoFormat_H264},
1662 {.subtype = &MFVideoFormat_H264_ES},
1664 .outputs =
1666 {.subtype = &MFVideoFormat_NV12},
1667 {.subtype = &MFVideoFormat_YV12},
1668 {.subtype = &MFVideoFormat_IYUV},
1669 {.subtype = &MFVideoFormat_I420},
1670 {.subtype = &MFVideoFormat_YUY2},
1673 static const media_type_desc default_inputs[] =
1676 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
1677 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
1680 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
1681 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264_ES),
1684 static const DWORD input_width = 120, input_height = 248;
1685 const media_type_desc default_outputs[] =
1688 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
1689 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
1690 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
1691 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
1692 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
1693 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
1694 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
1695 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
1696 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
1697 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
1698 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
1701 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
1702 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
1703 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
1704 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
1705 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
1706 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
1707 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
1708 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
1709 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
1710 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
1711 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
1714 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
1715 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
1716 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
1717 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
1718 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
1719 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
1720 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
1721 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
1722 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
1723 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
1724 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
1727 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
1728 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
1729 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
1730 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
1731 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
1732 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
1733 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
1734 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
1735 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
1736 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
1737 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
1740 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
1741 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
1742 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
1743 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
1744 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width * 2),
1745 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
1746 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
1747 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
1748 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
1749 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 2),
1750 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
1753 const struct attribute_desc input_type_desc[] =
1755 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
1756 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
1757 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
1758 {0},
1760 const struct attribute_desc minimal_output_type_desc[] =
1762 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
1763 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
1764 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
1765 {0},
1767 const struct attribute_desc output_type_desc[] =
1769 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
1770 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
1771 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
1772 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
1773 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 2, 1),
1774 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
1775 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * input_height * 3 / 2),
1776 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
1777 {0},
1779 static const struct attribute_desc new_output_type_desc[] =
1781 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
1782 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
1783 ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96),
1784 ATTR_RATIO(MF_MT_FRAME_RATE, 1, 1),
1785 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 2),
1786 {0},
1788 static const MFVideoArea actual_aperture = {.Area={82,84}};
1789 static const DWORD actual_width = 96, actual_height = 96;
1790 const media_type_desc actual_outputs[] =
1793 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
1794 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
1795 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
1796 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
1797 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
1798 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
1799 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
1800 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
1801 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
1802 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
1803 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
1804 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
1807 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
1808 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
1809 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
1810 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
1811 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
1812 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
1813 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
1814 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
1815 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
1816 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
1817 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
1818 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
1821 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
1822 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
1823 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
1824 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
1825 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
1826 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
1827 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
1828 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
1829 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
1830 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
1831 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
1832 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
1835 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
1836 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
1837 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
1838 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
1839 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
1840 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
1841 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
1842 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
1843 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
1844 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
1845 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
1846 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
1849 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
1850 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
1851 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
1852 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
1853 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
1854 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
1855 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
1856 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
1857 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
1858 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
1859 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
1860 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
1864 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_H264};
1865 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
1866 const BYTE *h264_encoded_data, *nv12_frame_data, *i420_frame_data;
1867 ULONG h264_encoded_data_len, nv12_frame_len, i420_frame_len;
1868 DWORD input_id, output_id, input_count, output_count;
1869 MFT_OUTPUT_STREAM_INFO output_info;
1870 MFT_INPUT_STREAM_INFO input_info;
1871 MFT_OUTPUT_DATA_BUFFER output;
1872 IMFMediaBuffer *media_buffer;
1873 DWORD status, length, count;
1874 WCHAR output_path[MAX_PATH];
1875 IMFAttributes *attributes;
1876 IMFMediaType *media_type;
1877 LONGLONG time, duration;
1878 IMFTransform *transform;
1879 ULONG i, ret, flags;
1880 HANDLE output_file;
1881 IMFSample *sample;
1882 HRSRC resource;
1883 UINT32 value;
1884 BYTE *data;
1885 HRESULT hr;
1887 hr = CoInitialize(NULL);
1888 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
1890 winetest_push_context("h264dec");
1892 if (!check_mft_enum(MFT_CATEGORY_VIDEO_DECODER, &input_type, &output_type, class_id))
1893 goto failed;
1894 check_mft_get_info(class_id, &expect_mft_info);
1896 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
1897 &IID_IMFTransform, (void **)&transform)))
1898 goto failed;
1900 hr = IMFTransform_GetAttributes(transform, &attributes);
1901 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
1902 hr = IMFAttributes_SetUINT32(attributes, &MF_LOW_LATENCY, 1);
1903 ok(hr == S_OK, "SetUINT32 returned %#lx\n", hr);
1904 ret = IMFAttributes_Release(attributes);
1905 todo_wine
1906 ok(ret == 1, "Release returned %ld\n", ret);
1908 /* no output type is available before an input type is set */
1910 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
1911 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
1912 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
1913 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputCurrentType returned %#lx\n", hr);
1915 /* setting output media type first doesn't work */
1917 hr = MFCreateMediaType(&media_type);
1918 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
1919 init_media_type(media_type, default_outputs[0], -1);
1920 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
1921 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr);
1922 ret = IMFMediaType_Release(media_type);
1923 ok(ret == 0, "Release returned %lu\n", ret);
1925 /* check available input types */
1927 flags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE;
1928 memset(&input_info, 0xcd, sizeof(input_info));
1929 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
1930 todo_wine
1931 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
1932 todo_wine
1933 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
1934 todo_wine
1935 ok(input_info.dwFlags == flags, "got dwFlags %#lx\n", input_info.dwFlags);
1936 todo_wine
1937 ok(input_info.cbSize == 0x1000, "got cbSize %lu\n", input_info.cbSize);
1938 todo_wine
1939 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
1940 todo_wine
1941 ok(input_info.cbAlignment == 0, "got cbAlignment %#lx\n", input_info.cbAlignment);
1943 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
1944 memset(&output_info, 0xcd, sizeof(output_info));
1945 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
1946 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
1947 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
1948 ok(output_info.cbSize == 1920 * 1088 * 2, "got cbSize %#lx\n", output_info.cbSize);
1949 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
1951 i = -1;
1952 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
1954 winetest_push_context("in %lu", i);
1955 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
1956 check_media_type(media_type, default_inputs[i], -1);
1957 ret = IMFMediaType_Release(media_type);
1958 ok(ret == 0, "Release returned %lu\n", ret);
1959 winetest_pop_context();
1961 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
1962 ok(i == 2 || broken(i == 1) /* Win7 */, "%lu input media types\n", i);
1964 /* check required input media type attributes */
1966 hr = MFCreateMediaType(&media_type);
1967 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
1968 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
1969 ok(hr == E_INVALIDARG, "SetInputType returned %#lx.\n", hr);
1970 init_media_type(media_type, input_type_desc, 1);
1971 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
1972 todo_wine
1973 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
1974 init_media_type(media_type, input_type_desc, 2);
1975 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
1976 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
1977 init_media_type(media_type, input_type_desc, -1);
1978 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
1979 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
1980 ret = IMFMediaType_Release(media_type);
1981 ok(ret == 1, "Release returned %lu\n", ret);
1983 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
1984 memset(&output_info, 0xcd, sizeof(output_info));
1985 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
1986 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
1987 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
1988 todo_wine
1989 ok(output_info.cbSize == input_width * input_height * 2, "got cbSize %#lx\n", output_info.cbSize);
1990 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
1992 /* output types can now be enumerated (though they are actually the same for all input types) */
1994 i = -1;
1995 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
1997 winetest_push_context("out %lu", i);
1998 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
1999 check_media_type(media_type, default_outputs[i], -1);
2000 ret = IMFMediaType_Release(media_type);
2001 ok(ret == 0, "Release returned %lu\n", ret);
2002 winetest_pop_context();
2004 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
2005 ok(i == 5, "%lu output media types\n", i);
2007 /* check required output media type attributes */
2009 hr = MFCreateMediaType(&media_type);
2010 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
2011 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
2012 todo_wine
2013 ok(hr == E_INVALIDARG, "SetOutputType returned %#lx.\n", hr);
2014 init_media_type(media_type, minimal_output_type_desc, 1);
2015 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
2016 todo_wine
2017 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
2018 init_media_type(media_type, minimal_output_type_desc, 2);
2019 for (i = 2; i < ARRAY_SIZE(minimal_output_type_desc) - 1; ++i)
2021 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
2022 todo_wine
2023 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
2024 init_media_type(media_type, minimal_output_type_desc, i + 1);
2026 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
2027 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
2028 init_media_type(media_type, output_type_desc, -1);
2029 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
2030 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
2031 ret = IMFMediaType_Release(media_type);
2032 ok(ret == 1, "Release returned %lu\n", ret);
2034 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
2035 ok(hr == S_OK, "GetOutputCurrentType returned %#lx\n", hr);
2036 check_media_type(media_type, output_type_desc, -1);
2037 ret = IMFMediaType_Release(media_type);
2038 ok(ret == 0, "Release returned %lu\n", ret);
2040 /* check that the output media type we've selected don't change the enumeration */
2042 i = -1;
2043 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
2045 winetest_push_context("out %lu", i);
2046 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
2047 check_media_type(media_type, default_outputs[i], -1);
2048 ret = IMFMediaType_Release(media_type);
2049 ok(ret == 0, "Release returned %lu\n", ret);
2050 winetest_pop_context();
2052 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
2053 ok(i == 5, "%lu output media types\n", i);
2055 flags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE;
2056 memset(&input_info, 0xcd, sizeof(input_info));
2057 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
2058 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
2059 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
2060 ok(input_info.dwFlags == flags, "got dwFlags %#lx\n", input_info.dwFlags);
2061 ok(input_info.cbSize == 0x1000, "got cbSize %lu\n", input_info.cbSize);
2062 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
2063 ok(input_info.cbAlignment == 0, "got cbAlignment %#lx\n", input_info.cbAlignment);
2065 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
2066 memset(&output_info, 0xcd, sizeof(output_info));
2067 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
2068 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
2069 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
2070 todo_wine
2071 ok(output_info.cbSize == input_width * input_height * 2, "got cbSize %#lx\n", output_info.cbSize);
2072 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
2074 input_count = output_count = 0xdeadbeef;
2075 hr = IMFTransform_GetStreamCount(transform, &input_count, &output_count);
2076 todo_wine
2077 ok(hr == S_OK, "GetStreamCount returned %#lx\n", hr);
2078 todo_wine
2079 ok(input_count == 1, "got input_count %lu\n", input_count);
2080 todo_wine
2081 ok(output_count == 1, "got output_count %lu\n", output_count);
2082 hr = IMFTransform_GetStreamIDs(transform, 1, &input_id, 1, &output_id);
2083 ok(hr == E_NOTIMPL, "GetStreamIDs returned %#lx\n", hr);
2085 resource = FindResourceW(NULL, L"h264data.bin", (const WCHAR *)RT_RCDATA);
2086 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
2087 h264_encoded_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
2088 h264_encoded_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
2090 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
2091 * IMFTransform_ProcessOutput needs a sample or returns an error */
2093 status = 0;
2094 memset(&output, 0, sizeof(output));
2095 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
2096 ok(hr == E_INVALIDARG || hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2097 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
2098 ok(!output.pSample, "got pSample %p\n", output.pSample);
2099 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
2100 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
2101 ok(status == 0, "got status %#lx\n", status);
2103 i = 0;
2104 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
2105 while (1)
2107 status = 0;
2108 memset(&output, 0, sizeof(output));
2109 output.pSample = create_sample(NULL, output_info.cbSize);
2110 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
2111 if (hr != MF_E_TRANSFORM_NEED_MORE_INPUT) break;
2112 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2113 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
2114 ok(!!output.pSample, "got pSample %p\n", output.pSample);
2115 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
2116 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
2117 ok(status == 0, "got status %#lx\n", status);
2118 hr = IMFSample_GetTotalLength(output.pSample, &length);
2119 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
2120 ok(length == 0, "got length %lu\n", length);
2121 ret = IMFSample_Release(output.pSample);
2122 ok(ret == 0, "Release returned %lu\n", ret);
2124 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
2125 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2126 ret = IMFSample_Release(sample);
2127 ok(ret <= 1, "Release returned %lu\n", ret);
2128 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
2130 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
2131 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2132 ret = IMFSample_Release(sample);
2133 ok(ret <= 1, "Release returned %lu\n", ret);
2134 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
2135 i++;
2137 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
2138 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
2140 todo_wine
2141 ok(i == 2, "got %lu iterations\n", i);
2142 todo_wine
2143 ok(h264_encoded_data_len == 1180, "got h264_encoded_data_len %lu\n", h264_encoded_data_len);
2144 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
2145 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
2146 ok(!!output.pSample, "got pSample %p\n", output.pSample);
2147 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE,
2148 "got dwStatus %#lx\n", output.dwStatus);
2149 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
2150 ok(status == MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS,
2151 "got status %#lx\n", status);
2152 hr = IMFSample_GetTotalLength(output.pSample, &length);
2153 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
2154 ok(length == 0, "got length %lu\n", length);
2155 ret = IMFSample_Release(output.pSample);
2156 ok(ret == 0, "Release returned %lu\n", ret);
2158 flags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE;
2159 memset(&output_info, 0xcd, sizeof(output_info));
2160 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
2161 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
2162 ok(output_info.dwFlags == flags, "got dwFlags %#lx\n", output_info.dwFlags);
2163 ok(output_info.cbSize == actual_width * actual_height * 2, "got cbSize %#lx\n", output_info.cbSize);
2164 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
2166 i = -1;
2167 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
2169 winetest_push_context("out %lu", i);
2170 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
2171 check_media_type(media_type, actual_outputs[i], -1);
2172 ret = IMFMediaType_Release(media_type);
2173 ok(ret == 0, "Release returned %lu\n", ret);
2174 winetest_pop_context();
2176 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
2177 ok(i == 5, "%lu output media types\n", i);
2179 /* current output type is still the one we selected */
2180 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
2181 ok(hr == S_OK, "GetOutputCurrentType returned %#lx\n", hr);
2182 check_media_type(media_type, output_type_desc, -1);
2183 hr = IMFMediaType_GetItemType(media_type, &MF_MT_MINIMUM_DISPLAY_APERTURE, NULL);
2184 ok(hr == MF_E_ATTRIBUTENOTFOUND, "GetItemType returned %#lx\n", hr);
2185 ret = IMFMediaType_Release(media_type);
2186 ok(ret == 0, "Release returned %lu\n", ret);
2188 /* and generate a new one as well in a temporary directory */
2189 GetTempPathW(ARRAY_SIZE(output_path), output_path);
2190 lstrcatW(output_path, L"nv12frame.bin");
2191 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
2192 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
2194 resource = FindResourceW(NULL, L"nv12frame.bin", (const WCHAR *)RT_RCDATA);
2195 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
2196 nv12_frame_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
2197 nv12_frame_len = SizeofResource(GetModuleHandleW(NULL), resource);
2198 ok(nv12_frame_len == actual_width * actual_height * 3 / 2, "got frame length %lu\n", nv12_frame_len);
2200 status = 0;
2201 memset(&output, 0, sizeof(output));
2202 output.pSample = create_sample(NULL, nv12_frame_len);
2203 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
2204 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
2205 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
2206 ok(!!output.pSample, "got pSample %p\n", output.pSample);
2207 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
2208 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
2209 ok(status == 0, "got status %#lx\n", status);
2211 hr = IMFSample_GetUINT32(sample, &MFSampleExtension_CleanPoint, &value);
2212 ok(hr == MF_E_ATTRIBUTENOTFOUND, "GetUINT32 MFSampleExtension_CleanPoint returned %#lx\n", hr);
2214 count = 0xdeadbeef;
2215 hr = IMFSample_GetBufferCount(output.pSample, &count);
2216 ok(hr == S_OK, "GetBufferCount returned %#lx\n", hr);
2217 ok(count == 1, "got count %#lx\n", count);
2219 flags = 0xdeadbeef;
2220 hr = IMFSample_GetSampleFlags(output.pSample, &flags);
2221 ok(hr == S_OK, "GetSampleFlags returned %#lx\n", hr);
2222 ok(flags == 0, "got flags %#lx\n", flags);
2224 time = 0xdeadbeef;
2225 hr = IMFSample_GetSampleTime(output.pSample, &time);
2226 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
2227 ok(time == 0, "got time %I64d\n", time);
2229 /* doesn't matter what frame rate we've selected, duration is defined by the stream */
2230 duration = 0xdeadbeef;
2231 hr = IMFSample_GetSampleDuration(output.pSample, &duration);
2232 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
2233 ok(duration - 333666 <= 2, "got duration %I64d\n", duration);
2235 /* Win8 and before pad the data with garbage instead of original
2236 * buffer data, make sure it's consistent. */
2237 hr = IMFSample_ConvertToContiguousBuffer(output.pSample, &media_buffer);
2238 ok(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
2239 hr = IMFMediaBuffer_Lock(media_buffer, &data, NULL, &length);
2240 ok(hr == S_OK, "Lock returned %#lx\n", hr);
2241 ok(length == nv12_frame_len, "got length %lu\n", length);
2243 for (i = 0; i < actual_aperture.Area.cy; ++i)
2245 memset(data + actual_width * i + actual_aperture.Area.cx, 0xcd, actual_width - actual_aperture.Area.cx);
2246 memset(data + actual_width * (actual_height + i / 2) + actual_aperture.Area.cx, 0xcd, actual_width - actual_aperture.Area.cx);
2248 memset(data + actual_width * actual_aperture.Area.cy, 0xcd, (actual_height - actual_aperture.Area.cy) * actual_width);
2249 memset(data + actual_width * (actual_height + actual_aperture.Area.cy / 2), 0xcd, (actual_height - actual_aperture.Area.cy) / 2 * actual_width);
2251 hr = IMFMediaBuffer_Unlock(media_buffer);
2252 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
2253 IMFMediaBuffer_Release(media_buffer);
2255 check_sample(output.pSample, nv12_frame_data, output_file);
2257 ret = IMFSample_Release(output.pSample);
2258 ok(ret == 0, "Release returned %lu\n", ret);
2260 trace("created %s\n", debugstr_w(output_path));
2261 CloseHandle(output_file);
2263 /* we can change it, but only with the correct frame size */
2264 hr = MFCreateMediaType(&media_type);
2265 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
2266 init_media_type(media_type, output_type_desc, -1);
2267 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
2268 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
2269 init_media_type(media_type, new_output_type_desc, -1);
2270 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
2271 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
2272 ret = IMFMediaType_Release(media_type);
2273 ok(ret == 1, "Release returned %lu\n", ret);
2275 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
2276 ok(hr == S_OK, "GetOutputCurrentType returned %#lx\n", hr);
2277 check_media_type(media_type, new_output_type_desc, -1);
2278 hr = IMFMediaType_GetItemType(media_type, &MF_MT_MINIMUM_DISPLAY_APERTURE, NULL);
2279 ok(hr == MF_E_ATTRIBUTENOTFOUND, "GetItemType returned %#lx\n", hr);
2280 ret = IMFMediaType_Release(media_type);
2281 ok(ret == 0, "Release returned %lu\n", ret);
2283 status = 0;
2284 memset(&output, 0, sizeof(output));
2285 output.pSample = create_sample(NULL, actual_width * actual_height * 2);
2286 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
2287 todo_wine
2288 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
2290 while (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
2292 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
2293 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2294 ret = IMFSample_Release(sample);
2295 ok(ret <= 1, "Release returned %lu\n", ret);
2296 sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
2297 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
2298 todo_wine_if(hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
2299 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
2302 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
2303 ok(!!output.pSample, "got pSample %p\n", output.pSample);
2304 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got dwStatus %#lx\n", output.dwStatus);
2305 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
2306 ok(status == MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS, "got status %#lx\n", status);
2307 hr = IMFSample_GetTotalLength(output.pSample, &length);
2308 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
2309 ok(length == 0, "got length %lu\n", length);
2310 ret = IMFSample_Release(output.pSample);
2311 ok(ret == 0, "Release returned %lu\n", ret);
2313 GetTempPathW(ARRAY_SIZE(output_path), output_path);
2314 lstrcatW(output_path, L"i420frame.bin");
2315 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
2316 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
2318 resource = FindResourceW(NULL, L"i420frame.bin", (const WCHAR *)RT_RCDATA);
2319 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
2320 i420_frame_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
2321 i420_frame_len = SizeofResource(GetModuleHandleW(NULL), resource);
2322 ok(i420_frame_len == actual_width * actual_height * 3 / 2, "got frame length %lu\n", i420_frame_len);
2324 status = 0;
2325 memset(&output, 0, sizeof(output));
2326 output.pSample = create_sample(NULL, actual_width * actual_height * 2);
2327 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
2328 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
2329 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
2330 ok(!!output.pSample, "got pSample %p\n", output.pSample);
2331 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
2332 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
2333 ok(status == 0, "got status %#lx\n", status);
2335 hr = IMFSample_GetSampleTime(output.pSample, &time);
2336 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
2337 todo_wine_if(time == 1334666) /* when VA-API plugin is used */
2338 ok(time - 333666 <= 2, "got time %I64d\n", time);
2340 duration = 0xdeadbeef;
2341 hr = IMFSample_GetSampleDuration(output.pSample, &duration);
2342 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
2343 ok(duration - 333666 <= 2, "got duration %I64d\n", duration);
2345 /* Win8 and before pad the data with garbage instead of original
2346 * buffer data, make sure it's consistent. */
2347 hr = IMFSample_ConvertToContiguousBuffer(output.pSample, &media_buffer);
2348 ok(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
2349 hr = IMFMediaBuffer_Lock(media_buffer, &data, NULL, &length);
2350 ok(hr == S_OK, "Lock returned %#lx\n", hr);
2351 ok(length == i420_frame_len, "got length %lu\n", length);
2353 for (i = 0; i < actual_aperture.Area.cy; ++i)
2355 memset(data + actual_width * i + actual_aperture.Area.cx, 0xcd, actual_width - actual_aperture.Area.cx);
2356 memset(data + actual_width * actual_height + actual_width / 2 * i + actual_aperture.Area.cx / 2, 0xcd,
2357 actual_width / 2 - actual_aperture.Area.cx / 2);
2358 memset(data + actual_width * actual_height + actual_width / 2 * (actual_height / 2 + i) + actual_aperture.Area.cx / 2, 0xcd,
2359 actual_width / 2 - actual_aperture.Area.cx / 2);
2361 memset(data + actual_width * actual_aperture.Area.cy, 0xcd, (actual_height - actual_aperture.Area.cy) * actual_width);
2362 memset(data + actual_width * actual_height + actual_width / 2 * actual_aperture.Area.cy / 2, 0xcd,
2363 (actual_height - actual_aperture.Area.cy) / 2 * actual_width / 2);
2364 memset(data + actual_width * actual_height + actual_width / 2 * (actual_height / 2 + actual_aperture.Area.cy / 2), 0xcd,
2365 (actual_height - actual_aperture.Area.cy) / 2 * actual_width / 2);
2367 hr = IMFMediaBuffer_Unlock(media_buffer);
2368 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
2369 IMFMediaBuffer_Release(media_buffer);
2371 check_sample(output.pSample, i420_frame_data, output_file);
2373 ret = IMFSample_Release(output.pSample);
2374 ok(ret == 0, "Release returned %lu\n", ret);
2376 trace("created %s\n", debugstr_w(output_path));
2377 CloseHandle(output_file);
2379 status = 0;
2380 memset(&output, 0, sizeof(output));
2381 output.pSample = create_sample(NULL, actual_width * actual_height * 2);
2382 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
2383 todo_wine_if(hr == S_OK) /* when VA-API plugin is used */
2384 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2385 ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
2386 ok(!!output.pSample, "got pSample %p\n", output.pSample);
2387 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
2388 ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
2389 ok(status == 0, "got status %#lx\n", status);
2390 ret = IMFSample_Release(output.pSample);
2391 ok(ret == 0, "Release returned %lu\n", ret);
2393 ret = IMFTransform_Release(transform);
2394 ok(ret == 0, "Release returned %lu\n", ret);
2395 ret = IMFSample_Release(sample);
2396 ok(ret == 0, "Release returned %lu\n", ret);
2398 failed:
2399 winetest_pop_context();
2400 CoUninitialize();
2403 static void test_audio_convert(void)
2405 const GUID *const class_id = &CLSID_CResamplerMediaObject;
2406 const struct transform_info expect_mft_info =
2408 .name = L"Resampler MFT",
2409 .major_type = &MFMediaType_Audio,
2410 .inputs =
2412 {.subtype = &MFAudioFormat_PCM},
2413 {.subtype = &MFAudioFormat_Float},
2415 .outputs =
2417 {.subtype = &MFAudioFormat_PCM},
2418 {.subtype = &MFAudioFormat_Float},
2421 const struct transform_info expect_dmo_info =
2423 .name = L"Resampler DMO",
2424 .major_type = &MEDIATYPE_Audio,
2425 .inputs =
2427 {.subtype = &MEDIASUBTYPE_PCM},
2428 {.subtype = &MEDIASUBTYPE_IEEE_FLOAT},
2430 .outputs =
2432 {.subtype = &MEDIASUBTYPE_PCM},
2433 {.subtype = &MEDIASUBTYPE_IEEE_FLOAT},
2437 static const media_type_desc expect_available_inputs[] =
2440 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2441 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
2442 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2445 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2446 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2447 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2450 static const media_type_desc expect_available_outputs[] =
2453 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2454 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
2455 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2458 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2459 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2460 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2463 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2464 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
2465 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
2466 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2467 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
2468 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 384000),
2469 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
2470 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2471 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2474 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2475 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2476 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
2477 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2478 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
2479 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 192000),
2480 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
2481 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2482 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2486 static const struct attribute_desc input_type_desc[] =
2488 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2489 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
2490 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
2491 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2492 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
2493 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
2494 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
2495 {0},
2497 const struct attribute_desc output_type_desc[] =
2499 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2500 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2501 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
2502 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2503 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2504 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
2505 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
2506 {0},
2509 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_PCM};
2510 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_Float};
2511 static const ULONG audioconv_block_size = 0x4000;
2512 ULONG audio_data_len, audioconv_data_len;
2513 const BYTE *audio_data, *audioconv_data;
2514 MFT_OUTPUT_STREAM_INFO output_info;
2515 MFT_INPUT_STREAM_INFO input_info;
2516 MFT_OUTPUT_DATA_BUFFER output;
2517 WCHAR output_path[MAX_PATH];
2518 IMFMediaType *media_type;
2519 LONGLONG time, duration;
2520 IMFTransform *transform;
2521 DWORD length, status;
2522 HANDLE output_file;
2523 IMFSample *sample;
2524 HRSRC resource;
2525 ULONG i, ret;
2526 HRESULT hr;
2528 hr = CoInitialize(NULL);
2529 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
2531 winetest_push_context("resampler");
2533 if (!check_mft_enum(MFT_CATEGORY_AUDIO_EFFECT, &input_type, &output_type, class_id))
2534 goto failed;
2535 check_mft_get_info(class_id, &expect_mft_info);
2536 check_dmo_get_info(class_id, &expect_dmo_info);
2538 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
2539 &IID_IMFTransform, (void **)&transform)))
2540 goto failed;
2542 check_interface(transform, &IID_IMFTransform, TRUE);
2543 check_interface(transform, &IID_IMediaObject, TRUE);
2544 check_interface(transform, &IID_IPropertyStore, TRUE);
2545 check_interface(transform, &IID_IPropertyBag, TRUE);
2546 /* check_interface(transform, &IID_IWMResamplerProps, TRUE); */
2548 /* check default media types */
2550 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
2551 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
2552 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
2553 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
2555 i = -1;
2556 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
2558 winetest_push_context("out %lu", i);
2559 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
2560 check_media_type(media_type, expect_available_outputs[i], -1);
2561 ret = IMFMediaType_Release(media_type);
2562 ok(ret == 0, "Release returned %lu\n", ret);
2563 winetest_pop_context();
2565 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
2566 ok(i == 4, "%lu output media types\n", i);
2568 i = -1;
2569 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
2571 winetest_push_context("in %lu", i);
2572 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
2573 check_media_type(media_type, expect_available_inputs[i], -1);
2574 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
2575 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
2576 ret = IMFMediaType_Release(media_type);
2577 ok(ret == 0, "Release returned %lu\n", ret);
2578 winetest_pop_context();
2580 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
2581 ok(i == 2, "%lu input media types\n", i);
2583 /* setting output media type first doesn't work */
2585 hr = MFCreateMediaType(&media_type);
2586 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
2587 init_media_type(media_type, output_type_desc, -1);
2588 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
2589 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr);
2590 ret = IMFMediaType_Release(media_type);
2591 ok(ret == 0, "Release returned %lu\n", ret);
2593 /* check required input media type attributes */
2595 hr = MFCreateMediaType(&media_type);
2596 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
2597 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
2598 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
2599 init_media_type(media_type, input_type_desc, 1);
2600 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
2601 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
2602 init_media_type(media_type, input_type_desc, 2);
2603 for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i)
2605 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
2606 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
2607 init_media_type(media_type, input_type_desc, i + 1);
2609 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
2610 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
2611 ret = IMFMediaType_Release(media_type);
2612 ok(ret == 0, "Release returned %lu\n", ret);
2614 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
2615 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
2616 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
2617 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
2619 /* check new output media types */
2621 i = -1;
2622 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
2624 winetest_push_context("out %lu", i);
2625 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
2626 check_media_type(media_type, expect_available_outputs[i], -1);
2627 ret = IMFMediaType_Release(media_type);
2628 ok(ret == 0, "Release returned %lu\n", ret);
2629 winetest_pop_context();
2631 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
2632 ok(i == 4, "%lu output media types\n", i);
2634 /* check required output media type attributes */
2636 hr = MFCreateMediaType(&media_type);
2637 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
2638 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
2639 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
2640 init_media_type(media_type, output_type_desc, 1);
2641 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
2642 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
2643 init_media_type(media_type, output_type_desc, 2);
2644 for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i)
2646 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
2647 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
2648 init_media_type(media_type, output_type_desc, i + 1);
2650 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
2651 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
2652 ret = IMFMediaType_Release(media_type);
2653 ok(ret == 0, "Release returned %lu\n", ret);
2655 memset(&input_info, 0xcd, sizeof(input_info));
2656 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
2657 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
2658 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
2659 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
2660 ok(input_info.cbSize == 8, "got cbSize %lu\n", input_info.cbSize);
2661 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
2662 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
2664 memset(&output_info, 0xcd, sizeof(output_info));
2665 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
2666 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
2667 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
2668 ok(output_info.cbSize == 4, "got cbSize %#lx\n", output_info.cbSize);
2669 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
2671 resource = FindResourceW(NULL, L"audiodata.bin", (const WCHAR *)RT_RCDATA);
2672 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
2673 audio_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
2674 audio_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
2675 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
2677 sample = create_sample(audio_data, audio_data_len);
2678 hr = IMFSample_SetSampleTime(sample, 0);
2679 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
2680 hr = IMFSample_SetSampleDuration(sample, 10000000);
2681 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
2682 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
2683 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2684 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
2685 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
2686 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
2687 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2688 ret = IMFSample_Release(sample);
2689 ok(ret <= 1, "Release returned %ld\n", ret);
2691 status = 0xdeadbeef;
2692 sample = create_sample(NULL, audioconv_block_size);
2693 memset(&output, 0, sizeof(output));
2694 output.pSample = sample;
2696 resource = FindResourceW(NULL, L"audioconvdata.bin", (const WCHAR *)RT_RCDATA);
2697 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
2698 audioconv_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
2699 audioconv_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
2700 ok(audioconv_data_len == 179924, "got length %lu\n", audioconv_data_len);
2702 /* and generate a new one as well in a temporary directory */
2703 GetTempPathW(ARRAY_SIZE(output_path), output_path);
2704 lstrcatW(output_path, L"audioconvdata.bin");
2705 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
2706 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
2708 i = 0;
2709 while (SUCCEEDED(hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status)))
2711 winetest_push_context("%lu", i);
2712 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
2713 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
2714 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || output.dwStatus == 0 ||
2715 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|6) || output.dwStatus == 6) /* win7 */,
2716 "got dwStatus %#lx\n", output.dwStatus);
2717 ok(status == 0, "got status %#lx\n", status);
2718 if (!(output.dwStatus & MFT_OUTPUT_DATA_BUFFER_INCOMPLETE))
2720 winetest_pop_context();
2721 break;
2724 hr = IMFSample_GetSampleTime(sample, &time);
2725 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
2726 ok(time == i * 928798, "got time %I64d\n", time);
2727 hr = IMFSample_GetSampleDuration(sample, &duration);
2728 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
2729 ok(duration == 928798, "got duration %I64d\n", duration);
2730 hr = IMFSample_GetTotalLength(sample, &length);
2731 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
2732 ok(length == audioconv_block_size, "got length %lu\n", length);
2733 ok(audioconv_data_len > audioconv_block_size, "got remaining length %lu\n", audioconv_data_len);
2734 check_sample_pcm16(sample, audioconv_data, output_file, FALSE);
2735 audioconv_data_len -= audioconv_block_size;
2736 audioconv_data += audioconv_block_size;
2738 winetest_pop_context();
2739 i++;
2742 hr = IMFSample_GetSampleTime(sample, &time);
2743 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
2744 ok(time == i * 928798, "got time %I64d\n", time);
2745 hr = IMFSample_GetSampleDuration(sample, &duration);
2746 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
2747 todo_wine
2748 ok(duration == 897506, "got duration %I64d\n", duration);
2749 hr = IMFSample_GetTotalLength(sample, &length);
2750 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
2751 todo_wine
2752 ok(length == 15832, "got length %lu\n", length);
2753 ok(audioconv_data_len == 16084, "got remaining length %lu\n", audioconv_data_len);
2754 check_sample_pcm16(sample, audioconv_data, output_file, FALSE);
2755 audioconv_data_len -= length;
2756 audioconv_data += length;
2758 memset(&output, 0, sizeof(output));
2759 output.pSample = sample;
2760 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
2761 todo_wine
2762 ok(hr == S_OK || broken(hr == MF_E_TRANSFORM_NEED_MORE_INPUT) /* win7 */, "ProcessOutput returned %#lx\n", hr);
2763 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
2764 todo_wine
2765 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || broken(output.dwStatus == 0) /* win7 */,
2766 "got dwStatus %#lx\n", output.dwStatus);
2767 ok(status == 0, "got status %#lx\n", status);
2769 if (hr == S_OK)
2771 hr = IMFSample_GetSampleTime(sample, &time);
2772 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
2773 todo_wine
2774 ok(time == 10185486, "got time %I64d\n", time);
2775 hr = IMFSample_GetSampleDuration(sample, &duration);
2776 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
2777 todo_wine
2778 ok(duration == 14286, "got duration %I64d\n", duration);
2779 hr = IMFSample_GetTotalLength(sample, &length);
2780 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
2781 todo_wine
2782 ok(length == audioconv_data_len, "got length %lu\n", length);
2783 if (length == audioconv_data_len)
2784 check_sample_pcm16(sample, audioconv_data, output_file, FALSE);
2787 trace("created %s\n", debugstr_w(output_path));
2788 CloseHandle(output_file);
2790 ret = IMFSample_Release(sample);
2791 ok(ret == 0, "Release returned %lu\n", ret);
2793 status = 0xdeadbeef;
2794 sample = create_sample(NULL, audioconv_block_size);
2795 memset(&output, 0, sizeof(output));
2796 output.pSample = sample;
2797 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
2798 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2799 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
2800 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
2801 ok(status == 0, "got status %#lx\n", status);
2802 hr = IMFSample_GetTotalLength(sample, &length);
2803 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
2804 ok(length == 0, "got length %lu\n", length);
2805 ret = IMFSample_Release(sample);
2806 ok(ret == 0, "Release returned %lu\n", ret);
2808 ret = IMFTransform_Release(transform);
2809 ok(ret == 0, "Release returned %lu\n", ret);
2811 failed:
2812 winetest_pop_context();
2813 CoUninitialize();
2816 static void test_color_convert(void)
2818 const GUID *const class_id = &CLSID_CColorConvertDMO;
2819 const struct transform_info expect_mft_info =
2821 .name = L"Color Converter MFT",
2822 .major_type = &MFMediaType_Video,
2823 .inputs =
2825 {.subtype = &MFVideoFormat_YV12},
2826 {.subtype = &MFVideoFormat_YUY2},
2827 {.subtype = &MFVideoFormat_UYVY},
2828 {.subtype = &MFVideoFormat_AYUV},
2829 {.subtype = &MFVideoFormat_NV12},
2830 {.subtype = &DMOVideoFormat_RGB32},
2831 {.subtype = &DMOVideoFormat_RGB565},
2832 {.subtype = &MFVideoFormat_I420},
2833 {.subtype = &MFVideoFormat_IYUV},
2834 {.subtype = &MFVideoFormat_YVYU},
2835 {.subtype = &DMOVideoFormat_RGB24},
2836 {.subtype = &DMOVideoFormat_RGB555},
2837 {.subtype = &DMOVideoFormat_RGB8},
2838 {.subtype = &MEDIASUBTYPE_V216},
2839 {.subtype = &MEDIASUBTYPE_V410},
2840 {.subtype = &MFVideoFormat_NV11},
2841 {.subtype = &MFVideoFormat_Y41P},
2842 {.subtype = &MFVideoFormat_Y41T},
2843 {.subtype = &MFVideoFormat_Y42T},
2844 {.subtype = &MFVideoFormat_YVU9},
2846 .outputs =
2848 {.subtype = &MFVideoFormat_YV12},
2849 {.subtype = &MFVideoFormat_YUY2},
2850 {.subtype = &MFVideoFormat_UYVY},
2851 {.subtype = &MFVideoFormat_AYUV},
2852 {.subtype = &MFVideoFormat_NV12},
2853 {.subtype = &DMOVideoFormat_RGB32},
2854 {.subtype = &DMOVideoFormat_RGB565},
2855 {.subtype = &MFVideoFormat_I420},
2856 {.subtype = &MFVideoFormat_IYUV},
2857 {.subtype = &MFVideoFormat_YVYU},
2858 {.subtype = &DMOVideoFormat_RGB24},
2859 {.subtype = &DMOVideoFormat_RGB555},
2860 {.subtype = &DMOVideoFormat_RGB8},
2861 {.subtype = &MEDIASUBTYPE_V216},
2862 {.subtype = &MEDIASUBTYPE_V410},
2863 {.subtype = &MFVideoFormat_NV11},
2866 const struct transform_info expect_dmo_info =
2868 .name = L"Color Converter DMO",
2869 .major_type = &MEDIATYPE_Video,
2870 .inputs =
2872 {.subtype = &MEDIASUBTYPE_YV12},
2873 {.subtype = &MEDIASUBTYPE_YUY2},
2874 {.subtype = &MEDIASUBTYPE_UYVY},
2875 {.subtype = &MEDIASUBTYPE_AYUV},
2876 {.subtype = &MEDIASUBTYPE_NV12},
2877 {.subtype = &MEDIASUBTYPE_RGB32},
2878 {.subtype = &MEDIASUBTYPE_RGB565},
2879 {.subtype = &MEDIASUBTYPE_I420},
2880 {.subtype = &MEDIASUBTYPE_IYUV},
2881 {.subtype = &MEDIASUBTYPE_YVYU},
2882 {.subtype = &MEDIASUBTYPE_RGB24},
2883 {.subtype = &MEDIASUBTYPE_RGB555},
2884 {.subtype = &MEDIASUBTYPE_RGB8},
2885 {.subtype = &MEDIASUBTYPE_V216},
2886 {.subtype = &MEDIASUBTYPE_V410},
2887 {.subtype = &MEDIASUBTYPE_NV11},
2888 {.subtype = &MEDIASUBTYPE_Y41P},
2889 {.subtype = &MEDIASUBTYPE_Y41T},
2890 {.subtype = &MEDIASUBTYPE_Y42T},
2891 {.subtype = &MEDIASUBTYPE_YVU9},
2893 .outputs =
2895 {.subtype = &MEDIASUBTYPE_YV12},
2896 {.subtype = &MEDIASUBTYPE_YUY2},
2897 {.subtype = &MEDIASUBTYPE_UYVY},
2898 {.subtype = &MEDIASUBTYPE_AYUV},
2899 {.subtype = &MEDIASUBTYPE_NV12},
2900 {.subtype = &MEDIASUBTYPE_RGB32},
2901 {.subtype = &MEDIASUBTYPE_RGB565},
2902 {.subtype = &MEDIASUBTYPE_I420},
2903 {.subtype = &MEDIASUBTYPE_IYUV},
2904 {.subtype = &MEDIASUBTYPE_YVYU},
2905 {.subtype = &MEDIASUBTYPE_RGB24},
2906 {.subtype = &MEDIASUBTYPE_RGB555},
2907 {.subtype = &MEDIASUBTYPE_RGB8},
2908 {.subtype = &MEDIASUBTYPE_V216},
2909 {.subtype = &MEDIASUBTYPE_V410},
2910 {.subtype = &MEDIASUBTYPE_NV11},
2914 static const media_type_desc expect_available_inputs[20] =
2916 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12), },
2917 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), },
2918 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY), },
2919 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_AYUV), },
2920 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), },
2921 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), },
2922 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565), },
2923 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420), },
2924 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV), },
2925 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU), },
2926 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24), },
2927 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555), },
2928 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_RGB8), },
2929 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V216), },
2930 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V410), },
2931 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11), },
2932 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y41P), },
2933 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y41T), },
2934 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y42T), },
2935 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVU9), },
2937 static const media_type_desc expect_available_outputs[16] =
2939 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12), },
2940 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), },
2941 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY), },
2942 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_AYUV), },
2943 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), },
2944 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), },
2945 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565), },
2946 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420), },
2947 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV), },
2948 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU), },
2949 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24), },
2950 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555), },
2951 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_RGB8), },
2952 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V216), },
2953 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V410), },
2954 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11), },
2956 static const media_type_desc expect_available_common =
2958 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2959 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2960 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2963 static const MFVideoArea actual_aperture = {.Area={82,84}};
2964 static const DWORD actual_width = 96, actual_height = 96;
2965 const struct attribute_desc input_type_desc[] =
2967 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2968 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
2969 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
2970 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
2971 {0},
2973 const struct attribute_desc output_type_desc[] =
2975 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
2976 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
2977 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
2978 {0},
2981 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
2982 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_I420};
2983 ULONG nv12frame_data_len, rgb32_data_len;
2984 const BYTE *nv12frame_data, *rgb32_data;
2985 MFT_OUTPUT_STREAM_INFO output_info;
2986 MFT_INPUT_STREAM_INFO input_info;
2987 MFT_OUTPUT_DATA_BUFFER output;
2988 WCHAR output_path[MAX_PATH];
2989 IMFMediaType *media_type;
2990 LONGLONG time, duration;
2991 IMFTransform *transform;
2992 DWORD length, status;
2993 HANDLE output_file;
2994 IMFSample *sample;
2995 HRSRC resource;
2996 ULONG i, ret;
2997 HRESULT hr;
2999 hr = CoInitialize(NULL);
3000 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
3002 winetest_push_context("colorconv");
3004 if (!check_mft_enum(MFT_CATEGORY_VIDEO_EFFECT, &input_type, &output_type, class_id))
3005 goto failed;
3006 check_mft_get_info(class_id, &expect_mft_info);
3007 check_dmo_get_info(class_id, &expect_dmo_info);
3009 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
3010 &IID_IMFTransform, (void **)&transform)))
3011 goto failed;
3013 check_interface(transform, &IID_IMFTransform, TRUE);
3014 check_interface(transform, &IID_IMediaObject, TRUE);
3015 check_interface(transform, &IID_IPropertyStore, TRUE);
3016 todo_wine
3017 check_interface(transform, &IID_IMFRealTimeClient, TRUE);
3018 /* check_interface(transform, &IID_IWMColorConvProps, TRUE); */
3020 /* check default media types */
3022 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
3023 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
3024 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
3025 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
3027 i = -1;
3028 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
3030 winetest_push_context("out %lu", i);
3031 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3032 check_media_type(media_type, expect_available_common, -1);
3033 check_media_type(media_type, expect_available_outputs[i], -1);
3034 ret = IMFMediaType_Release(media_type);
3035 ok(ret == 0, "Release returned %lu\n", ret);
3036 winetest_pop_context();
3038 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3039 ok(i == 16, "%lu output media types\n", i);
3041 i = -1;
3042 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
3044 winetest_push_context("in %lu", i);
3045 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
3046 check_media_type(media_type, expect_available_common, -1);
3047 check_media_type(media_type, expect_available_inputs[i], -1);
3048 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3049 if (i == 12)
3051 todo_wine
3052 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
3054 else
3055 ok(hr == E_INVALIDARG, "SetInputType returned %#lx.\n", hr);
3056 ret = IMFMediaType_Release(media_type);
3057 ok(ret == 0, "Release returned %lu\n", ret);
3058 winetest_pop_context();
3060 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
3061 ok(i == 20, "%lu input media types\n", i);
3063 /* check required output media type attributes */
3065 hr = MFCreateMediaType(&media_type);
3066 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
3067 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3068 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
3069 init_media_type(media_type, output_type_desc, 1);
3070 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3071 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
3072 init_media_type(media_type, output_type_desc, 2);
3073 for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i)
3075 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3076 ok(hr == E_INVALIDARG, "SetOutputType returned %#lx.\n", hr);
3077 init_media_type(media_type, output_type_desc, i + 1);
3079 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3080 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
3081 ret = IMFMediaType_Release(media_type);
3082 ok(ret == 0, "Release returned %lu\n", ret);
3084 /* check required input media type attributes */
3086 hr = MFCreateMediaType(&media_type);
3087 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
3088 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3089 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
3090 init_media_type(media_type, input_type_desc, 1);
3091 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3092 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
3093 init_media_type(media_type, input_type_desc, 2);
3094 for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i)
3096 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3097 ok(hr == E_INVALIDARG, "SetInputType returned %#lx.\n", hr);
3098 init_media_type(media_type, input_type_desc, i + 1);
3100 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3101 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
3102 ret = IMFMediaType_Release(media_type);
3103 ok(ret == 0, "Release returned %lu\n", ret);
3105 memset(&input_info, 0xcd, sizeof(input_info));
3106 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
3107 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
3108 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
3109 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
3110 ok(input_info.cbSize == actual_width * actual_height * 3 / 2, "got cbSize %#lx\n", input_info.cbSize);
3111 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
3112 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
3114 memset(&output_info, 0xcd, sizeof(output_info));
3115 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
3116 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
3117 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
3118 ok(output_info.cbSize == actual_width * actual_height * 4, "got cbSize %#lx\n", output_info.cbSize);
3119 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
3121 resource = FindResourceW(NULL, L"nv12frame.bin", (const WCHAR *)RT_RCDATA);
3122 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
3123 nv12frame_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
3124 nv12frame_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
3125 ok(nv12frame_data_len == 13824, "got length %lu\n", nv12frame_data_len);
3127 sample = create_sample(nv12frame_data, nv12frame_data_len);
3128 hr = IMFSample_SetSampleTime(sample, 0);
3129 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
3130 hr = IMFSample_SetSampleDuration(sample, 10000000);
3131 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
3132 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
3133 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3134 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
3135 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
3136 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
3137 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
3138 ret = IMFSample_Release(sample);
3139 ok(ret <= 1, "Release returned %ld\n", ret);
3141 resource = FindResourceW(NULL, L"rgb32frame.bin", (const WCHAR *)RT_RCDATA);
3142 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
3143 rgb32_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
3144 rgb32_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
3145 ok(rgb32_data_len == output_info.cbSize, "got length %lu\n", rgb32_data_len);
3147 /* and generate a new one as well in a temporary directory */
3148 GetTempPathW(ARRAY_SIZE(output_path), output_path);
3149 lstrcatW(output_path, L"rgb32frame.bin");
3150 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
3151 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
3153 status = 0xdeadbeef;
3154 sample = create_sample(NULL, output_info.cbSize);
3155 memset(&output, 0, sizeof(output));
3156 output.pSample = sample;
3157 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
3158 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
3159 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
3160 ok(output.dwStatus == 0 || broken(output.dwStatus == 6) /* win7 */, "got dwStatus %#lx\n", output.dwStatus);
3161 ok(status == 0, "got status %#lx\n", status);
3163 hr = IMFSample_GetSampleTime(sample, &time);
3164 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
3165 ok(time == 0, "got time %I64d\n", time);
3166 hr = IMFSample_GetSampleDuration(sample, &duration);
3167 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
3168 ok(duration == 10000000, "got duration %I64d\n", duration);
3169 hr = IMFSample_GetTotalLength(sample, &length);
3170 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
3171 ok(length == output_info.cbSize, "got length %lu\n", length);
3172 check_sample_rgb32(sample, rgb32_data, output_file);
3173 rgb32_data_len -= output_info.cbSize;
3174 rgb32_data += output_info.cbSize;
3176 trace("created %s\n", debugstr_w(output_path));
3177 CloseHandle(output_file);
3179 ret = IMFSample_Release(sample);
3180 ok(ret == 0, "Release returned %lu\n", ret);
3182 status = 0xdeadbeef;
3183 sample = create_sample(NULL, output_info.cbSize);
3184 memset(&output, 0, sizeof(output));
3185 output.pSample = sample;
3186 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
3187 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3188 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
3189 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
3190 ok(status == 0, "got status %#lx\n", status);
3191 hr = IMFSample_GetTotalLength(sample, &length);
3192 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
3193 ok(length == 0, "got length %lu\n", length);
3194 ret = IMFSample_Release(sample);
3195 ok(ret == 0, "Release returned %lu\n", ret);
3197 ret = IMFTransform_Release(transform);
3198 ok(ret == 0, "Release returned %ld\n", ret);
3200 failed:
3201 winetest_pop_context();
3202 CoUninitialize();
3205 static void test_video_processor(void)
3207 const GUID *const class_id = &CLSID_VideoProcessorMFT;
3208 const struct transform_info expect_mft_info =
3210 .name = L"Microsoft Video Processor MFT",
3211 .major_type = &MFMediaType_Video,
3212 .inputs =
3214 {.subtype = &MFVideoFormat_IYUV},
3215 {.subtype = &MFVideoFormat_YV12},
3216 {.subtype = &MFVideoFormat_NV12},
3217 {.subtype = &MFVideoFormat_YUY2},
3218 {.subtype = &MFVideoFormat_ARGB32},
3219 {.subtype = &MFVideoFormat_RGB32},
3220 {.subtype = &MFVideoFormat_NV11},
3221 {.subtype = &MFVideoFormat_AYUV},
3222 {.subtype = &MFVideoFormat_UYVY},
3223 {.subtype = &MEDIASUBTYPE_P208},
3224 {.subtype = &MFVideoFormat_RGB24},
3225 {.subtype = &MFVideoFormat_RGB555},
3226 {.subtype = &MFVideoFormat_RGB565},
3227 {.subtype = &MFVideoFormat_RGB8},
3228 {.subtype = &MFVideoFormat_I420},
3229 {.subtype = &MFVideoFormat_Y216},
3230 {.subtype = &MFVideoFormat_v410},
3231 {.subtype = &MFVideoFormat_Y41P},
3232 {.subtype = &MFVideoFormat_Y41T},
3233 {.subtype = &MFVideoFormat_Y42T},
3234 {.subtype = &MFVideoFormat_YVYU},
3235 {.subtype = &MFVideoFormat_420O},
3237 .outputs =
3239 {.subtype = &MFVideoFormat_IYUV},
3240 {.subtype = &MFVideoFormat_YV12},
3241 {.subtype = &MFVideoFormat_NV12},
3242 {.subtype = &MFVideoFormat_YUY2},
3243 {.subtype = &MFVideoFormat_ARGB32},
3244 {.subtype = &MFVideoFormat_RGB32},
3245 {.subtype = &MFVideoFormat_NV11},
3246 {.subtype = &MFVideoFormat_AYUV},
3247 {.subtype = &MFVideoFormat_UYVY},
3248 {.subtype = &MEDIASUBTYPE_P208},
3249 {.subtype = &MFVideoFormat_RGB24},
3250 {.subtype = &MFVideoFormat_RGB555},
3251 {.subtype = &MFVideoFormat_RGB565},
3252 {.subtype = &MFVideoFormat_RGB8},
3253 {.subtype = &MFVideoFormat_I420},
3254 {.subtype = &MFVideoFormat_Y216},
3255 {.subtype = &MFVideoFormat_v410},
3256 {.subtype = &MFVideoFormat_Y41P},
3257 {.subtype = &MFVideoFormat_Y41T},
3258 {.subtype = &MFVideoFormat_Y42T},
3259 {.subtype = &MFVideoFormat_YVYU},
3262 const GUID expect_available_inputs_w8[] =
3264 MFVideoFormat_IYUV,
3265 MFVideoFormat_YV12,
3266 MFVideoFormat_NV12,
3267 MFVideoFormat_420O,
3268 MFVideoFormat_UYVY,
3269 MFVideoFormat_YUY2,
3270 MFVideoFormat_P208,
3271 MFVideoFormat_NV11,
3272 MFVideoFormat_AYUV,
3273 MFVideoFormat_ARGB32,
3274 MFVideoFormat_RGB32,
3275 MFVideoFormat_RGB24,
3276 MFVideoFormat_I420,
3277 MFVideoFormat_YVYU,
3278 MFVideoFormat_RGB555,
3279 MFVideoFormat_RGB565,
3280 MFVideoFormat_RGB8,
3281 MFVideoFormat_Y216,
3282 MFVideoFormat_v410,
3283 MFVideoFormat_Y41P,
3284 MFVideoFormat_Y41T,
3285 MFVideoFormat_Y42T,
3287 const GUID expect_available_inputs_w10[] =
3289 MFVideoFormat_L8,
3290 MFVideoFormat_L16,
3291 MFAudioFormat_MPEG,
3292 MFVideoFormat_IYUV,
3293 MFVideoFormat_YV12,
3294 MFVideoFormat_NV12,
3295 MFVideoFormat_420O,
3296 MFVideoFormat_P010,
3297 MFVideoFormat_P016,
3298 MFVideoFormat_UYVY,
3299 MFVideoFormat_YUY2,
3300 MFVideoFormat_P208,
3301 MFVideoFormat_NV11,
3302 MFVideoFormat_AYUV,
3303 MFVideoFormat_ARGB32,
3304 MFVideoFormat_ABGR32,
3305 MFVideoFormat_RGB32,
3306 MFVideoFormat_A2R10G10B10,
3307 MFVideoFormat_A16B16G16R16F,
3308 MFVideoFormat_RGB24,
3309 MFVideoFormat_I420,
3310 MFVideoFormat_YVYU,
3311 MFVideoFormat_RGB555,
3312 MFVideoFormat_RGB565,
3313 MFVideoFormat_RGB8,
3314 MFVideoFormat_Y216,
3315 MFVideoFormat_v410,
3316 MFVideoFormat_Y41P,
3317 MFVideoFormat_Y41T,
3318 MFVideoFormat_Y42T,
3320 const GUID expect_available_outputs[] =
3322 MFVideoFormat_A2R10G10B10, /* enumerated with MFVideoFormat_P010 input */
3323 MFVideoFormat_P010, /* enumerated with MFVideoFormat_A2R10G10B10 input */
3324 MFVideoFormat_YUY2,
3325 MFVideoFormat_IYUV,
3326 MFVideoFormat_I420,
3327 MFVideoFormat_NV12,
3328 MFVideoFormat_RGB24,
3329 MFVideoFormat_ARGB32,
3330 MFVideoFormat_RGB32,
3331 MFVideoFormat_YV12,
3332 MFVideoFormat_Y216, /* enumerated with some input formats */
3333 MFVideoFormat_UYVY, /* enumerated with some input formats */
3334 MFVideoFormat_YVYU, /* enumerated with some input formats */
3335 MFVideoFormat_AYUV,
3336 MFVideoFormat_RGB555,
3337 MFVideoFormat_RGB565,
3338 MFVideoFormat_AYUV, /* some inputs enumerate MFVideoFormat_AYUV after RGB565 */
3339 MFVideoFormat_NV12, /* P010 enumerates NV12 after (A)RGB32 formats */
3340 MFVideoFormat_A16B16G16R16F, /* enumerated with MFVideoFormat_P010 input */
3342 static const media_type_desc expect_available_common =
3344 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3347 static const MFVideoArea actual_aperture = {.Area={82,84}};
3348 static const DWORD actual_width = 96, actual_height = 96;
3349 const struct attribute_desc input_type_desc[] =
3351 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3352 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
3353 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
3354 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3355 {0},
3357 const struct attribute_desc output_type_desc[] =
3359 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3360 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
3361 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
3362 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3363 {0},
3366 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
3367 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_I420};
3368 DWORD input_count, output_count, input_id, output_id, flags;
3369 DWORD input_min, input_max, output_min, output_max, i, j, k;
3370 ULONG nv12frame_data_len, rgb32_data_len;
3371 IMFMediaType *media_type, *media_type2;
3372 IMFAttributes *attributes, *attributes2;
3373 const BYTE *nv12frame_data, *rgb32_data;
3374 MFT_OUTPUT_DATA_BUFFER output_buffer;
3375 const GUID *expect_available_inputs;
3376 MFT_OUTPUT_STREAM_INFO output_info;
3377 MFT_INPUT_STREAM_INFO input_info;
3378 MFT_OUTPUT_DATA_BUFFER output;
3379 IMFSample *sample, *sample2;
3380 WCHAR output_path[MAX_PATH];
3381 LONGLONG time, duration;
3382 IMFTransform *transform;
3383 IMFMediaBuffer *buffer;
3384 IMFMediaEvent *event;
3385 DWORD length, status;
3386 unsigned int value;
3387 HANDLE output_file;
3388 HRSRC resource;
3389 BYTE *ptr, tmp;
3390 UINT32 count;
3391 HRESULT hr;
3392 ULONG ret;
3393 GUID guid;
3394 LONG ref;
3396 hr = CoInitialize(NULL);
3397 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
3399 winetest_push_context("videoproc");
3401 if (!check_mft_enum(MFT_CATEGORY_VIDEO_PROCESSOR, &input_type, &output_type, class_id))
3402 goto failed;
3403 check_mft_get_info(class_id, &expect_mft_info);
3405 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
3406 &IID_IMFTransform, (void **)&transform)))
3407 goto failed;
3409 todo_wine
3410 check_interface(transform, &IID_IMFVideoProcessorControl, TRUE);
3411 todo_wine
3412 check_interface(transform, &IID_IMFRealTimeClientEx, TRUE);
3413 check_interface(transform, &IID_IMFMediaEventGenerator, FALSE);
3414 check_interface(transform, &IID_IMFShutdown, FALSE);
3416 /* Transform global attributes. */
3417 hr = IMFTransform_GetAttributes(transform, &attributes);
3418 ok(hr == S_OK, "Failed to get attributes, hr %#lx.\n", hr);
3420 hr = IMFAttributes_GetCount(attributes, &count);
3421 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3422 todo_wine
3423 ok(!!count, "Unexpected attribute count %u.\n", count);
3425 value = 0;
3426 hr = IMFAttributes_GetUINT32(attributes, &MF_SA_D3D11_AWARE, &value);
3427 todo_wine {
3428 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3429 ok(value == 1, "Unexpected attribute value %u.\n", value);
3431 hr = IMFTransform_GetAttributes(transform, &attributes2);
3432 ok(hr == S_OK, "Failed to get attributes, hr %#lx.\n", hr);
3433 ok(attributes == attributes2, "Unexpected instance.\n");
3434 IMFAttributes_Release(attributes);
3435 IMFAttributes_Release(attributes2);
3437 hr = IMFTransform_GetStreamLimits(transform, &input_min, &input_max, &output_min, &output_max);
3438 ok(hr == S_OK, "Failed to get stream limits, hr %#lx.\n", hr);
3439 ok(input_min == input_max && input_min == 1 && output_min == output_max && output_min == 1,
3440 "Unexpected stream limits.\n");
3442 hr = IMFTransform_GetStreamCount(transform, &input_count, &output_count);
3443 ok(hr == S_OK, "Failed to get stream count, hr %#lx.\n", hr);
3444 ok(input_count == 1 && output_count == 1, "Unexpected stream count %lu, %lu.\n", input_count, output_count);
3446 hr = IMFTransform_GetStreamIDs(transform, 1, &input_id, 1, &output_id);
3447 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3449 input_id = 100;
3450 hr = IMFTransform_AddInputStreams(transform, 1, &input_id);
3451 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3453 hr = IMFTransform_DeleteInputStream(transform, 0);
3454 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3456 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
3457 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3459 hr = IMFTransform_GetInputStreamAttributes(transform, 0, &attributes);
3460 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3462 hr = IMFTransform_GetOutputStatus(transform, &flags);
3463 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3465 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes);
3466 ok(hr == S_OK, "Failed to get output attributes, hr %#lx.\n", hr);
3467 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes2);
3468 ok(hr == S_OK, "Failed to get output attributes, hr %#lx.\n", hr);
3469 ok(attributes == attributes2, "Unexpected instance.\n");
3470 IMFAttributes_Release(attributes);
3471 IMFAttributes_Release(attributes2);
3473 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
3474 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
3476 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type);
3477 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3479 hr = IMFTransform_GetInputCurrentType(transform, 1, &media_type);
3480 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
3482 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type);
3483 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3485 hr = IMFTransform_GetOutputCurrentType(transform, 1, &media_type);
3486 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
3488 hr = IMFTransform_GetInputStreamInfo(transform, 1, &input_info);
3489 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
3491 memset(&input_info, 0xcc, sizeof(input_info));
3492 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
3493 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
3494 ok(input_info.dwFlags == 0, "Unexpected flag %#lx.\n", input_info.dwFlags);
3495 ok(input_info.cbSize == 0, "Unexpected size %lu.\n", input_info.cbSize);
3496 ok(input_info.cbMaxLookahead == 0, "Unexpected lookahead length %lu.\n", input_info.cbMaxLookahead);
3497 ok(input_info.cbAlignment == 0, "Unexpected alignment %lu.\n", input_info.cbAlignment);
3498 hr = MFCreateMediaEvent(MEUnknown, &GUID_NULL, S_OK, NULL, &event);
3499 ok(hr == S_OK, "Failed to create event object, hr %#lx.\n", hr);
3500 hr = IMFTransform_ProcessEvent(transform, 0, event);
3501 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3502 hr = IMFTransform_ProcessEvent(transform, 1, event);
3503 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
3504 ref = IMFMediaEvent_Release(event);
3505 ok(ref == 0, "Release returned %ld\n", ref);
3507 /* Configure stream types. */
3508 for (i = 0;;++i)
3510 if (FAILED(hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type)))
3512 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
3513 break;
3516 hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type2);
3517 ok(hr == S_OK, "Failed to get available type, hr %#lx.\n", hr);
3518 ok(media_type != media_type2, "Unexpected instance.\n");
3519 ref = IMFMediaType_Release(media_type2);
3520 ok(ref == 0, "Release returned %ld\n", ref);
3522 hr = IMFMediaType_GetMajorType(media_type, &guid);
3523 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
3524 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type.\n");
3526 hr = IMFMediaType_GetCount(media_type, &count);
3527 ok(hr == S_OK, "Failed to get attributes count, hr %#lx.\n", hr);
3528 ok(count == 2, "Unexpected count %u.\n", count);
3530 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
3531 ok(hr == S_OK, "Failed to get subtype, hr %#lx.\n", hr);
3532 ok(is_supported_video_type(&guid), "Unexpected media type %s.\n", wine_dbgstr_guid(&guid));
3534 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
3535 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
3537 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3538 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
3540 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type2);
3541 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
3543 /* FIXME: figure out if those require additional attributes or simply advertised but not supported */
3544 if (IsEqualGUID(&guid, &MFVideoFormat_L8) || IsEqualGUID(&guid, &MFVideoFormat_L16)
3545 || IsEqualGUID(&guid, &MFVideoFormat_D16) || IsEqualGUID(&guid, &MFVideoFormat_420O)
3546 || IsEqualGUID(&guid, &MFVideoFormat_A16B16G16R16F))
3548 ref = IMFMediaType_Release(media_type);
3549 ok(ref == 0, "Release returned %ld\n", ref);
3550 continue;
3553 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
3554 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3556 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
3557 ok(hr == S_OK, "Failed to test input type %s, hr %#lx.\n", wine_dbgstr_guid(&guid), hr);
3559 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3560 ok(hr == S_OK, "Failed to test input type, hr %#lx.\n", hr);
3562 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type2);
3563 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
3564 ok(media_type != media_type2, "Unexpected instance.\n");
3565 IMFMediaType_Release(media_type2);
3567 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
3568 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
3569 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected input status %#lx.\n", flags);
3571 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
3572 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
3573 ok(input_info.dwFlags == 0, "Unexpected flags %#lx.\n", input_info.dwFlags);
3574 ok(input_info.cbMaxLookahead == 0, "Unexpected lookahead length %lu.\n", input_info.cbMaxLookahead);
3575 ok(input_info.cbAlignment == 0, "Unexpected alignment %lu.\n", input_info.cbAlignment);
3577 IMFMediaType_Release(media_type);
3580 /* IYUV -> RGB32 */
3581 hr = MFCreateMediaType(&media_type);
3582 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
3584 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
3585 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3587 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_IYUV);
3588 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3590 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
3591 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3593 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3594 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
3596 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
3597 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
3599 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3600 ok(hr == S_OK, "Failed to set output type, hr %#lx.\n", hr);
3602 memset(&output_info, 0, sizeof(output_info));
3603 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
3604 ok(hr == S_OK, "Failed to get stream info, hr %#lx.\n", hr);
3605 ok(output_info.dwFlags == 0, "Unexpected flags %#lx.\n", output_info.dwFlags);
3606 ok(output_info.cbSize > 0, "Unexpected size %lu.\n", output_info.cbSize);
3607 ok(output_info.cbAlignment == 0, "Unexpected alignment %lu.\n", output_info.cbAlignment);
3609 hr = MFCreateSample(&sample);
3610 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
3612 hr = MFCreateSample(&sample2);
3613 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
3615 memset(&output_buffer, 0, sizeof(output_buffer));
3616 output_buffer.pSample = sample;
3617 flags = 0;
3618 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3619 todo_wine
3620 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#lx.\n", hr);
3621 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
3622 ok(flags == 0, "Unexpected status %#lx.\n", flags);
3624 hr = IMFTransform_ProcessInput(transform, 0, sample2, 0);
3625 todo_wine
3626 ok(hr == S_OK, "Failed to push a sample, hr %#lx.\n", hr);
3628 hr = IMFTransform_ProcessInput(transform, 0, sample2, 0);
3629 todo_wine
3630 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#lx.\n", hr);
3632 memset(&output_buffer, 0, sizeof(output_buffer));
3633 output_buffer.pSample = sample;
3634 flags = 0;
3635 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3636 todo_wine
3637 ok(hr == MF_E_NO_SAMPLE_TIMESTAMP, "Unexpected hr %#lx.\n", hr);
3638 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
3639 ok(flags == 0, "Unexpected status %#lx.\n", flags);
3641 hr = IMFSample_SetSampleTime(sample2, 0);
3642 ok(hr == S_OK, "Failed to set sample time, hr %#lx.\n", hr);
3643 memset(&output_buffer, 0, sizeof(output_buffer));
3644 output_buffer.pSample = sample;
3645 flags = 0;
3646 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3647 todo_wine
3648 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3649 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
3650 ok(flags == 0, "Unexpected status %#lx.\n", flags);
3652 hr = MFCreateMemoryBuffer(1024 * 1024, &buffer);
3653 ok(hr == S_OK, "Failed to create a buffer, hr %#lx.\n", hr);
3655 hr = IMFSample_AddBuffer(sample2, buffer);
3656 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
3658 hr = IMFSample_AddBuffer(sample, buffer);
3659 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
3661 memset(&output_buffer, 0, sizeof(output_buffer));
3662 output_buffer.pSample = sample;
3663 flags = 0;
3664 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3665 todo_wine
3666 ok(hr == S_OK || broken(FAILED(hr)) /* Win8 */, "Failed to get output buffer, hr %#lx.\n", hr);
3667 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
3668 ok(flags == 0, "Unexpected status %#lx.\n", flags);
3670 if (SUCCEEDED(hr))
3672 memset(&output_buffer, 0, sizeof(output_buffer));
3673 output_buffer.pSample = sample;
3674 flags = 0;
3675 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output_buffer, &flags);
3676 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#lx.\n", hr);
3677 ok(output_buffer.dwStatus == 0, "Unexpected buffer status, %#lx.\n", output_buffer.dwStatus);
3678 ok(flags == 0, "Unexpected status %#lx.\n", flags);
3681 ref = IMFTransform_Release(transform);
3682 ok(ref == 0, "Release returned %ld\n", ref);
3684 ref = IMFMediaType_Release(media_type);
3685 ok(ref == 0, "Release returned %ld\n", ref);
3686 ref = IMFSample_Release(sample2);
3687 ok(ref == 0, "Release returned %ld\n", ref);
3688 ref = IMFSample_Release(sample);
3689 ok(ref == 0, "Release returned %ld\n", ref);
3690 ref = IMFMediaBuffer_Release(buffer);
3691 ok(ref == 0, "Release returned %ld\n", ref);
3694 hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)&transform);
3695 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3697 /* check default media types */
3699 memset(&input_info, 0xcd, sizeof(input_info));
3700 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
3701 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
3702 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
3703 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
3704 ok(input_info.cbSize == 0, "got cbSize %#lx\n", input_info.cbSize);
3705 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
3706 ok(input_info.cbAlignment == 0, "got cbAlignment %#lx\n", input_info.cbAlignment);
3708 memset(&output_info, 0xcd, sizeof(output_info));
3709 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
3710 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
3711 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
3712 ok(output_info.cbSize == 0, "got cbSize %#lx\n", output_info.cbSize);
3713 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
3715 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
3716 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3718 hr = IMFTransform_GetInputAvailableType(transform, 0, 23, &media_type);
3719 ok(hr == S_OK || hr == MF_E_NO_MORE_TYPES /* w8 */, "GetOutputAvailableType returned %#lx\n", hr);
3720 if (hr == MF_E_NO_MORE_TYPES)
3721 expect_available_inputs = expect_available_inputs_w8;
3722 else
3724 hr = IMFTransform_GetInputAvailableType(transform, 0, 27, &media_type);
3725 ok(hr == S_OK || broken(hr == MF_E_NO_MORE_TYPES) /* w1064v1507 */, "GetOutputAvailableType returned %#lx\n", hr);
3726 if (hr == MF_E_NO_MORE_TYPES)
3727 expect_available_inputs = expect_available_inputs_w10 + 3;
3728 else
3729 expect_available_inputs = expect_available_inputs_w10;
3732 i = -1;
3733 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
3735 /* FIXME: Skip exotic input types which aren't directly accepted */
3736 if (IsEqualGUID(&expect_available_inputs[i], &MFVideoFormat_L8)
3737 || IsEqualGUID(&expect_available_inputs[i], &MFVideoFormat_L16)
3738 || IsEqualGUID(&expect_available_inputs[i], &MFAudioFormat_MPEG)
3739 || IsEqualGUID(&expect_available_inputs[i], &MFVideoFormat_420O)
3740 || IsEqualGUID(&expect_available_inputs[i], &MFVideoFormat_A16B16G16R16F) /* w1064v1507 */)
3741 continue;
3743 winetest_push_context("in %lu", i);
3744 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
3745 check_media_type(media_type, expect_available_common, -1);
3747 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
3748 ok(hr == S_OK, "GetGUID returned %#lx\n", hr);
3750 /* w1064v1507 doesn't expose MFVideoFormat_ABGR32 input */
3751 if (broken(IsEqualGUID(&expect_available_inputs[i], &MFVideoFormat_ABGR32)
3752 && IsEqualGUID(&guid, &MFVideoFormat_RGB32)))
3753 expect_available_inputs++;
3755 ok(IsEqualGUID(&expect_available_inputs[i], &guid), "got subtype %s\n", debugstr_guid(&guid));
3757 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3758 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
3760 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)actual_width << 32 | actual_height);
3761 ok(hr == S_OK, "SetUINT64 returned %#lx.\n", hr);
3762 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3763 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
3765 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type2);
3766 ok(hr == S_OK, "GetOutputAvailableType returned %#lx.\n", hr);
3767 hr = IMFMediaType_IsEqual(media_type, media_type2, &flags);
3768 ok(hr == S_OK, "IsEqual returned %#lx.\n", hr);
3769 IMFMediaType_Release(media_type2);
3771 ret = IMFMediaType_Release(media_type);
3772 ok(ret == 1, "Release returned %lu\n", ret);
3774 j = k = 0;
3775 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++j, &media_type)))
3777 winetest_push_context("out %lu", j);
3778 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3779 check_media_type(media_type, expect_available_common, -1);
3781 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
3782 ok(hr == S_OK, "GetGUID returned %#lx\n", hr);
3784 for (; k < ARRAY_SIZE(expect_available_outputs); k++)
3785 if (IsEqualGUID(&expect_available_outputs[k], &guid))
3786 break;
3787 ok(k < ARRAY_SIZE(expect_available_outputs), "got subtype %s\n", debugstr_guid(&guid));
3789 ret = IMFMediaType_Release(media_type);
3790 ok(ret == 0, "Release returned %lu\n", ret);
3791 winetest_pop_context();
3793 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3795 winetest_pop_context();
3797 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
3798 ok(i == 22 || i == 30 || broken(i == 26) /* w1064v1507 */, "%lu input media types\n", i);
3800 /* check required input media type attributes */
3802 hr = MFCreateMediaType(&media_type);
3803 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
3804 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3805 ok(hr == E_INVALIDARG, "SetInputType returned %#lx.\n", hr);
3806 init_media_type(media_type, input_type_desc, 1);
3807 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3808 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
3809 init_media_type(media_type, input_type_desc, 2);
3810 for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i)
3812 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3813 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
3814 init_media_type(media_type, input_type_desc, i + 1);
3816 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
3817 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
3818 ret = IMFMediaType_Release(media_type);
3819 ok(ret == 1, "Release returned %lu\n", ret);
3821 /* check required output media type attributes */
3823 hr = MFCreateMediaType(&media_type);
3824 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
3825 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3826 ok(hr == E_INVALIDARG, "SetOutputType returned %#lx.\n", hr);
3827 init_media_type(media_type, output_type_desc, 1);
3828 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3829 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
3830 init_media_type(media_type, output_type_desc, 2);
3831 for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i)
3833 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3834 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
3835 init_media_type(media_type, output_type_desc, i + 1);
3837 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3838 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
3839 ret = IMFMediaType_Release(media_type);
3840 ok(ret == 1, "Release returned %lu\n", ret);
3842 memset(&input_info, 0xcd, sizeof(input_info));
3843 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
3844 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
3845 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
3846 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
3847 ok(input_info.cbSize == actual_width * actual_height * 3 / 2, "got cbSize %#lx\n", input_info.cbSize);
3848 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
3849 ok(input_info.cbAlignment == 0, "got cbAlignment %#lx\n", input_info.cbAlignment);
3851 memset(&output_info, 0xcd, sizeof(output_info));
3852 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
3853 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
3854 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
3855 ok(output_info.cbSize == actual_width * actual_height * 4, "got cbSize %#lx\n", output_info.cbSize);
3856 ok(output_info.cbAlignment == 0, "got cbAlignment %#lx\n", output_info.cbAlignment);
3858 resource = FindResourceW(NULL, L"nv12frame.bin", (const WCHAR *)RT_RCDATA);
3859 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
3860 nv12frame_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
3861 nv12frame_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
3862 ok(nv12frame_data_len == 13824, "got length %lu\n", nv12frame_data_len);
3864 sample = create_sample(nv12frame_data, nv12frame_data_len);
3865 hr = IMFSample_SetSampleTime(sample, 0);
3866 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
3867 hr = IMFSample_SetSampleDuration(sample, 10000000);
3868 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
3869 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
3870 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3871 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
3872 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
3873 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
3874 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
3875 ret = IMFSample_Release(sample);
3876 ok(ret <= 1, "Release returned %ld\n", ret);
3878 resource = FindResourceW(NULL, L"rgb32frame-vp.bin", (const WCHAR *)RT_RCDATA);
3879 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
3880 rgb32_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
3881 rgb32_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
3882 ok(rgb32_data_len == output_info.cbSize, "got length %lu\n", rgb32_data_len);
3884 /* and generate a new one as well in a temporary directory */
3885 GetTempPathW(ARRAY_SIZE(output_path), output_path);
3886 lstrcatW(output_path, L"rgb32frame-vp.bin");
3887 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
3888 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
3890 status = 0xdeadbeef;
3891 sample = create_sample(NULL, rgb32_data_len);
3892 memset(&output, 0, sizeof(output));
3893 output.pSample = sample;
3894 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
3895 ok(hr == S_OK || broken(hr == MF_E_SHUTDOWN) /* w8 */, "ProcessOutput returned %#lx\n", hr);
3896 if (hr != S_OK)
3898 win_skip("ProcessOutput returned MF_E_SHUTDOWN, skipping tests.\n");
3899 CloseHandle(output_file);
3900 goto skip_output;
3902 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
3903 ok(output.dwStatus == 0 || broken(output.dwStatus == 6) /* win7 */, "got dwStatus %#lx\n", output.dwStatus);
3904 ok(status == 0xdeadbeef, "got status %#lx\n", status);
3906 hr = IMFSample_GetSampleTime(sample, &time);
3907 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
3908 ok(time == 0, "got time %I64d\n", time);
3909 hr = IMFSample_GetSampleDuration(sample, &duration);
3910 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
3911 ok(duration == 10000000, "got duration %I64d\n", duration);
3912 hr = IMFSample_GetTotalLength(sample, &length);
3913 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
3914 ok(length == output_info.cbSize, "got length %lu\n", length);
3916 hr = IMFSample_ConvertToContiguousBuffer(sample, &buffer);
3917 ok(hr == S_OK, "ConvertToContiguousBuffer returned %#lx\n", hr);
3918 hr = IMFMediaBuffer_Lock(buffer, &ptr, NULL, &length);
3919 ok(hr == S_OK, "Lock returned %#lx\n", hr);
3920 tmp = *ptr;
3921 hr = IMFMediaBuffer_Unlock(buffer);
3922 ok(hr == S_OK, "Lock returned %#lx\n", hr);
3923 IMFMediaBuffer_Release(buffer);
3925 /* w1064v1809 ignores MF_MT_MINIMUM_DISPLAY_APERTURE and resizes the frame */
3926 todo_wine
3927 ok(tmp == 0xcd || broken(tmp == 0x00), "got %#x\n", tmp);
3928 if (tmp == 0x00)
3929 win_skip("Frame got resized, skipping output comparison\n");
3930 else if (tmp == 0xcd) /* Wine doesn't flip the frame, yet */
3931 check_sample_rgb32(sample, rgb32_data, output_file);
3932 rgb32_data_len -= output_info.cbSize;
3933 rgb32_data += output_info.cbSize;
3935 trace("created %s\n", debugstr_w(output_path));
3936 CloseHandle(output_file);
3938 ret = IMFSample_Release(sample);
3939 ok(ret == 0, "Release returned %lu\n", ret);
3941 status = 0xdeadbeef;
3942 sample = create_sample(NULL, output_info.cbSize);
3943 memset(&output, 0, sizeof(output));
3944 output.pSample = sample;
3945 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
3946 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3947 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
3948 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
3949 ok(status == 0xdeadbeef, "got status %#lx\n", status);
3950 hr = IMFSample_GetTotalLength(sample, &length);
3951 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
3952 ok(length == 0, "got length %lu\n", length);
3954 skip_output:
3955 ret = IMFSample_Release(sample);
3956 ok(ret == 0, "Release returned %lu\n", ret);
3958 ret = IMFTransform_Release(transform);
3959 ok(ret == 0, "Release returned %ld\n", ret);
3961 failed:
3962 winetest_pop_context();
3963 CoUninitialize();
3966 static void test_mp3_decoder(void)
3968 const GUID *const class_id = &CLSID_CMP3DecMediaObject;
3969 const struct transform_info expect_mft_info =
3971 .name = L"MP3 Decoder MFT",
3972 .major_type = &MFMediaType_Audio,
3973 .inputs =
3975 {.subtype = &MFAudioFormat_MP3},
3977 .outputs =
3979 {.subtype = &MFAudioFormat_PCM},
3982 const struct transform_info expect_dmo_info =
3984 .name = L"MP3 Decoder DMO",
3985 .major_type = &MEDIATYPE_Audio,
3986 .inputs =
3988 {.subtype = &MFAudioFormat_MP3},
3990 .outputs =
3992 {.subtype = &MEDIASUBTYPE_PCM},
3996 static const media_type_desc expect_available_inputs[] =
3999 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
4000 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3),
4001 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4004 static const media_type_desc expect_available_outputs[] =
4007 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
4008 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
4009 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
4010 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
4011 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
4012 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
4013 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
4014 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4017 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
4018 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
4019 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
4020 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
4021 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
4022 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
4023 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
4024 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4027 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
4028 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
4029 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
4030 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
4031 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
4032 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
4033 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2),
4034 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4037 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
4038 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
4039 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
4040 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
4041 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
4042 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
4043 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
4044 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4047 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
4048 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
4049 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
4050 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
4051 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
4052 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
4053 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2),
4054 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4057 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
4058 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
4059 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
4060 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
4061 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
4062 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 22050),
4063 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
4064 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4068 const struct attribute_desc input_type_desc[] =
4070 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
4071 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3),
4072 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
4073 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
4074 {0},
4076 static const struct attribute_desc output_type_desc[] =
4078 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
4079 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
4080 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
4081 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
4082 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
4083 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
4084 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
4085 {0},
4088 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_PCM};
4089 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_MP3};
4090 static const ULONG mp3dec_block_size = 0x1200;
4091 ULONG mp3dec_data_len, mp3enc_data_len;
4092 const BYTE *mp3dec_data, *mp3enc_data;
4093 MFT_OUTPUT_STREAM_INFO output_info;
4094 MFT_INPUT_STREAM_INFO input_info;
4095 MFT_OUTPUT_DATA_BUFFER output;
4096 WCHAR output_path[MAX_PATH];
4097 IMFMediaType *media_type;
4098 IMFTransform *transform;
4099 LONGLONG time, duration;
4100 DWORD status, length;
4101 HANDLE output_file;
4102 IMFSample *sample;
4103 HRSRC resource;
4104 ULONG i, ret;
4105 HRESULT hr;
4107 hr = CoInitialize(NULL);
4108 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
4110 winetest_push_context("mp3dec");
4112 if (!check_mft_enum(MFT_CATEGORY_AUDIO_DECODER, &input_type, &output_type, class_id))
4113 goto failed;
4114 check_mft_get_info(class_id, &expect_mft_info);
4115 check_dmo_get_info(class_id, &expect_dmo_info);
4117 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
4118 &IID_IMFTransform, (void **)&transform)))
4119 goto failed;
4121 check_interface(transform, &IID_IMFTransform, TRUE);
4122 check_interface(transform, &IID_IMediaObject, TRUE);
4123 todo_wine
4124 check_interface(transform, &IID_IPropertyStore, TRUE);
4125 check_interface(transform, &IID_IPropertyBag, FALSE);
4127 /* check default media types */
4129 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
4130 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
4131 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
4132 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
4133 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
4134 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
4136 i = -1;
4137 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
4139 winetest_push_context("in %lu", i);
4140 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
4141 check_media_type(media_type, expect_available_inputs[i], -1);
4142 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
4143 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
4144 ret = IMFMediaType_Release(media_type);
4145 ok(ret == 0, "Release returned %lu\n", ret);
4146 winetest_pop_context();
4148 todo_wine
4149 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
4150 todo_wine
4151 ok(i == ARRAY_SIZE(expect_available_inputs), "%lu input media types\n", i);
4153 /* setting output media type first doesn't work */
4155 hr = MFCreateMediaType(&media_type);
4156 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
4157 init_media_type(media_type, output_type_desc, -1);
4158 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
4159 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr);
4160 ret = IMFMediaType_Release(media_type);
4161 ok(ret == 0, "Release returned %lu\n", ret);
4163 /* check required input media type attributes */
4165 hr = MFCreateMediaType(&media_type);
4166 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
4167 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
4168 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
4169 init_media_type(media_type, input_type_desc, 1);
4170 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
4171 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
4172 init_media_type(media_type, input_type_desc, 2);
4173 for (i = 2; i < ARRAY_SIZE(input_type_desc) - 1; ++i)
4175 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
4176 ok(hr == MF_E_INVALIDMEDIATYPE, "SetInputType returned %#lx.\n", hr);
4177 init_media_type(media_type, input_type_desc, i + 1);
4179 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
4180 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
4181 ret = IMFMediaType_Release(media_type);
4182 ok(ret == 0, "Release returned %lu\n", ret);
4184 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
4185 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr);
4186 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
4187 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr);
4189 /* check new output media types */
4191 i = -1;
4192 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
4194 winetest_push_context("out %lu", i);
4195 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
4196 check_media_type(media_type, expect_available_outputs[i], -1);
4197 ret = IMFMediaType_Release(media_type);
4198 ok(ret == 0, "Release returned %lu\n", ret);
4199 winetest_pop_context();
4201 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
4202 ok(i == ARRAY_SIZE(expect_available_outputs), "%lu output media types\n", i);
4204 /* check required output media type attributes */
4206 hr = MFCreateMediaType(&media_type);
4207 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
4208 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
4209 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
4210 init_media_type(media_type, output_type_desc, 1);
4211 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
4212 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetOutputType returned %#lx.\n", hr);
4213 init_media_type(media_type, output_type_desc, 2);
4214 for (i = 2; i < ARRAY_SIZE(output_type_desc) - 1; ++i)
4216 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
4217 ok(hr == E_INVALIDARG, "SetOutputType returned %#lx.\n", hr);
4218 init_media_type(media_type, output_type_desc, i + 1);
4220 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
4221 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
4222 ret = IMFMediaType_Release(media_type);
4223 ok(ret == 0, "Release returned %lu\n", ret);
4225 memset(&input_info, 0xcd, sizeof(input_info));
4226 hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info);
4227 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
4228 ok(input_info.hnsMaxLatency == 0, "got hnsMaxLatency %s\n", wine_dbgstr_longlong(input_info.hnsMaxLatency));
4229 ok(input_info.dwFlags == 0, "got dwFlags %#lx\n", input_info.dwFlags);
4230 ok(input_info.cbSize == 0, "got cbSize %lu\n", input_info.cbSize);
4231 ok(input_info.cbMaxLookahead == 0, "got cbMaxLookahead %#lx\n", input_info.cbMaxLookahead);
4232 ok(input_info.cbAlignment == 1, "got cbAlignment %#lx\n", input_info.cbAlignment);
4234 memset(&output_info, 0xcd, sizeof(output_info));
4235 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info);
4236 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
4237 ok(output_info.dwFlags == 0, "got dwFlags %#lx\n", output_info.dwFlags);
4238 todo_wine
4239 ok(output_info.cbSize == mp3dec_block_size, "got cbSize %#lx\n", output_info.cbSize);
4240 ok(output_info.cbAlignment == 1, "got cbAlignment %#lx\n", output_info.cbAlignment);
4242 resource = FindResourceW(NULL, L"mp3encdata.bin", (const WCHAR *)RT_RCDATA);
4243 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
4244 mp3enc_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
4245 mp3enc_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
4246 ok(mp3enc_data_len == 6295, "got length %lu\n", mp3enc_data_len);
4248 sample = create_sample(mp3enc_data, mp3enc_data_len);
4249 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
4250 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
4251 ret = IMFSample_Release(sample);
4252 ok(ret == 1, "Release returned %lu\n", ret);
4254 sample = create_sample(mp3enc_data, mp3enc_data_len);
4255 hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
4256 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
4257 ret = IMFSample_Release(sample);
4258 ok(ret == 0, "Release returned %lu\n", ret);
4260 status = 0xdeadbeef;
4261 sample = create_sample(NULL, mp3dec_block_size);
4262 memset(&output, 0, sizeof(output));
4263 output.pSample = sample;
4265 resource = FindResourceW(NULL, L"mp3decdata.bin", (const WCHAR *)RT_RCDATA);
4266 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
4267 mp3dec_data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
4268 mp3dec_data_len = SizeofResource(GetModuleHandleW(NULL), resource);
4269 ok(mp3dec_data_len == 94656, "got length %lu\n", mp3dec_data_len);
4271 /* and generate a new one as well in a temporary directory */
4272 GetTempPathW(ARRAY_SIZE(output_path), output_path);
4273 lstrcatW(output_path, L"mp3decdata.bin");
4274 output_file = CreateFileW(output_path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
4275 ok(output_file != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
4277 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
4278 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
4280 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
4281 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
4282 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
4283 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || output.dwStatus == 0 ||
4284 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7) || output.dwStatus == 7) /* win7 */,
4285 "got dwStatus %#lx\n", output.dwStatus);
4286 ok(status == 0, "got status %#lx\n", status);
4288 hr = IMFSample_GetSampleTime(sample, &time);
4289 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
4290 ok(time == 0, "got time %I64d\n", time);
4291 hr = IMFSample_GetSampleDuration(sample, &duration);
4292 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
4293 ok(duration == 282993 || broken(duration == 522449) /* win8 */ || broken(duration == 261224) /* win7 */,
4294 "got duration %I64d\n", duration);
4295 hr = IMFSample_GetTotalLength(sample, &length);
4296 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
4297 ok(length == 0x9c0 || broken(length == mp3dec_block_size) /* win8 */ || broken(length == 0x900) /* win7 */,
4298 "got length %lu\n", length);
4299 ok(mp3dec_data_len > length, "got remaining length %lu\n", mp3dec_data_len);
4300 if (length == 0x9c0) check_sample_pcm16(sample, mp3dec_data, output_file, FALSE);
4301 mp3dec_data_len -= 0x9c0;
4302 mp3dec_data += 0x9c0;
4304 i = duration;
4305 while (SUCCEEDED(hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status)))
4307 winetest_push_context("%lu", i);
4308 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
4309 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
4310 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || output.dwStatus == 0 ||
4311 broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7) || output.dwStatus == 7) /* win7 */,
4312 "got dwStatus %#lx\n", output.dwStatus);
4313 ok(status == 0, "got status %#lx\n", status);
4314 if (!(output.dwStatus & MFT_OUTPUT_DATA_BUFFER_INCOMPLETE))
4316 winetest_pop_context();
4317 break;
4320 hr = IMFSample_GetSampleTime(sample, &time);
4321 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
4322 ok(time == i, "got time %I64d\n", time);
4323 hr = IMFSample_GetSampleDuration(sample, &duration);
4324 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
4325 ok(duration == 522449 || broken(261225 - duration <= 1) /* win7 */,
4326 "got duration %I64d\n", duration);
4327 hr = IMFSample_GetTotalLength(sample, &length);
4328 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
4329 ok(length == mp3dec_block_size || broken(length == 0x900) /* win7 */,
4330 "got length %lu\n", length);
4331 ok(mp3dec_data_len > length || broken(mp3dec_data_len == 2304 || mp3dec_data_len == 0) /* win7 */,
4332 "got remaining length %lu\n", mp3dec_data_len);
4333 if (length == mp3dec_block_size) check_sample_pcm16(sample, mp3dec_data, output_file, FALSE);
4334 mp3dec_data += min(mp3dec_data_len, length);
4335 mp3dec_data_len -= min(mp3dec_data_len, length);
4337 winetest_pop_context();
4338 i += duration;
4341 hr = IMFSample_GetSampleTime(sample, &time);
4342 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
4343 ok(time == i || broken(time == i - duration) /* win7 */, "got time %I64d\n", time);
4344 hr = IMFSample_GetSampleDuration(sample, &duration);
4345 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
4346 todo_wine
4347 ok(duration == 522449 || broken(261225 - duration <= 1) /* win7 */, "got duration %I64d\n", duration);
4348 hr = IMFSample_GetTotalLength(sample, &length);
4349 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
4350 todo_wine
4351 ok(length == mp3dec_block_size || broken(length == 0) /* win7 */, "got length %lu\n", length);
4352 ok(mp3dec_data_len == mp3dec_block_size || broken(mp3dec_data_len == 0) /* win7 */, "got remaining length %lu\n", mp3dec_data_len);
4353 check_sample_pcm16(sample, mp3dec_data, output_file, FALSE);
4354 mp3dec_data_len -= length;
4355 mp3dec_data += length;
4357 memset(&output, 0, sizeof(output));
4358 output.pSample = sample;
4359 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
4360 todo_wine
4361 ok(hr == S_OK || broken(hr == MF_E_TRANSFORM_NEED_MORE_INPUT) /* win7 */, "ProcessOutput returned %#lx\n", hr);
4362 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
4363 todo_wine
4364 ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE || broken(output.dwStatus == 0) /* win7 */,
4365 "got dwStatus %#lx\n", output.dwStatus);
4366 ok(status == 0, "got status %#lx\n", status);
4368 if (hr == S_OK)
4370 hr = IMFSample_GetSampleTime(sample, &time);
4371 ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
4372 todo_wine
4373 ok(time == 10185486, "got time %I64d\n", time);
4374 hr = IMFSample_GetSampleDuration(sample, &duration);
4375 ok(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
4376 todo_wine
4377 ok(duration == 14286, "got duration %I64d\n", duration);
4378 hr = IMFSample_GetTotalLength(sample, &length);
4379 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
4380 todo_wine
4381 ok(length == mp3dec_data_len, "got length %lu\n", length);
4382 if (length == mp3dec_data_len)
4383 check_sample_pcm16(sample, mp3dec_data, output_file, FALSE);
4386 trace("created %s\n", debugstr_w(output_path));
4387 CloseHandle(output_file);
4389 ret = IMFSample_Release(sample);
4390 ok(ret == 0, "Release returned %lu\n", ret);
4392 status = 0xdeadbeef;
4393 sample = create_sample(NULL, mp3dec_block_size);
4394 memset(&output, 0, sizeof(output));
4395 output.pSample = sample;
4396 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
4397 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
4398 ok(output.pSample == sample, "got pSample %p\n", output.pSample);
4399 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
4400 ok(status == 0, "got status %#lx\n", status);
4401 hr = IMFSample_GetTotalLength(sample, &length);
4402 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
4403 ok(length == 0, "got length %lu\n", length);
4404 ret = IMFSample_Release(sample);
4405 ok(ret == 0, "Release returned %lu\n", ret);
4407 ret = IMFTransform_Release(transform);
4408 ok(ret == 0, "Release returned %lu\n", ret);
4410 failed:
4411 winetest_pop_context();
4412 CoUninitialize();
4415 START_TEST(transform)
4417 init_functions();
4419 test_sample_copier();
4420 test_sample_copier_output_processing();
4421 test_wma_encoder();
4422 test_wma_decoder();
4423 test_h264_decoder();
4424 test_audio_convert();
4425 test_color_convert();
4426 test_video_processor();
4427 test_mp3_decoder();