winegstreamer: Implement GetOutputSizeInfo for WMV decoder.
[wine.git] / dlls / mf / tests / transform.c
blob370b58def2b6a5a405f4443b09278c03d58569c2
1 /*
2 * Copyright 2017 Nikolay Sivov
3 * Copyright 2022 RĂ©mi Bernon for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include <stdarg.h>
21 #include <string.h>
23 #define COBJMACROS
24 #include "windef.h"
25 #include "winbase.h"
27 #include "control.h"
28 #include "d3d9types.h"
29 #include "dmo.h"
30 #include "mferror.h"
31 #include "mfidl.h"
32 #include "mftransform.h"
33 #include "propvarutil.h"
34 #include "uuids.h"
35 #include "wmcodecdsp.h"
36 #include "mediaerr.h"
37 #include "amvideo.h"
39 #include "mf_test.h"
41 #include "wine/test.h"
43 #include "initguid.h"
45 DEFINE_GUID(DMOVideoFormat_RGB24,D3DFMT_R8G8B8,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
46 DEFINE_GUID(DMOVideoFormat_RGB32,D3DFMT_X8R8G8B8,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
47 DEFINE_GUID(DMOVideoFormat_RGB555,D3DFMT_X1R5G5B5,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
48 DEFINE_GUID(DMOVideoFormat_RGB565,D3DFMT_R5G6B5,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
49 DEFINE_GUID(DMOVideoFormat_RGB8,D3DFMT_P8,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
50 DEFINE_GUID(MFAudioFormat_RAW_AAC1,WAVE_FORMAT_RAW_AAC1,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
51 DEFINE_GUID(MFVideoFormat_ABGR32,0x00000020,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
52 DEFINE_GUID(MFVideoFormat_P208,0x38303250,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
53 DEFINE_GUID(MFVideoFormat_VC1S,0x53314356,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
54 DEFINE_GUID(MFVideoFormat_WMV_Unknown,0x7ce12ca9,0xbfbf,0x43d9,0x9d,0x00,0x82,0xb8,0xed,0x54,0x31,0x6b);
56 DEFINE_GUID(mft_output_sample_incomplete,0xffffff,0xffff,0xffff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
58 static BOOL is_compressed_subtype(const GUID *subtype)
60 if (IsEqualGUID(subtype, &MEDIASUBTYPE_WMV1)
61 || IsEqualGUID(subtype, &MEDIASUBTYPE_WMV2)
62 || IsEqualGUID(subtype, &MEDIASUBTYPE_WMVA)
63 || IsEqualGUID(subtype, &MEDIASUBTYPE_WMVP)
64 || IsEqualGUID(subtype, &MEDIASUBTYPE_WVP2)
65 || IsEqualGUID(subtype, &MFVideoFormat_WMV_Unknown)
66 || IsEqualGUID(subtype, &MEDIASUBTYPE_WVC1)
67 || IsEqualGUID(subtype, &MEDIASUBTYPE_WMV3)
68 || IsEqualGUID(subtype, &MFVideoFormat_VC1S))
69 return TRUE;
70 return FALSE;
73 static DWORD subtype_to_compression(const GUID *subtype)
75 if (IsEqualGUID(subtype, &MEDIASUBTYPE_RGB32)
76 || IsEqualGUID(subtype, &MEDIASUBTYPE_RGB24)
77 || IsEqualGUID(subtype, &MEDIASUBTYPE_RGB555)
78 || IsEqualGUID(subtype, &MEDIASUBTYPE_RGB8))
79 return BI_RGB;
80 else if (IsEqualGUID(subtype, &MEDIASUBTYPE_RGB565))
81 return BI_BITFIELDS;
82 else
83 return subtype->Data1;
86 static DWORD subtype_to_bpp(const GUID *subtype)
88 if (IsEqualGUID(subtype, &MEDIASUBTYPE_RGB8))
89 return 8;
90 else if (IsEqualGUID(subtype, &MEDIASUBTYPE_NV12)
91 || IsEqualGUID(subtype, &MEDIASUBTYPE_YV12)
92 || IsEqualGUID(subtype, &MEDIASUBTYPE_IYUV)
93 || IsEqualGUID(subtype, &MEDIASUBTYPE_I420)
94 || IsEqualGUID(subtype, &MEDIASUBTYPE_NV11))
95 return 12;
96 else if (IsEqualGUID(subtype, &MEDIASUBTYPE_YUY2)
97 || IsEqualGUID(subtype, &MEDIASUBTYPE_UYVY)
98 || IsEqualGUID(subtype, &MEDIASUBTYPE_YVYU)
99 || IsEqualGUID(subtype, &MEDIASUBTYPE_RGB565)
100 || IsEqualGUID(subtype, &MEDIASUBTYPE_RGB555))
101 return 16;
102 else if (IsEqualGUID(subtype, &MEDIASUBTYPE_RGB24))
103 return 24;
104 else if (IsEqualGUID(subtype, &MEDIASUBTYPE_RGB32))
105 return 32;
106 else
107 return 0;
110 static void load_resource(const WCHAR *filename, const BYTE **data, DWORD *length)
112 HRSRC resource = FindResourceW(NULL, filename, (const WCHAR *)RT_RCDATA);
113 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
114 *data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
115 *length = SizeofResource(GetModuleHandleW(NULL), resource);
118 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
119 static void _expect_ref(IUnknown* obj, ULONG expected_refcount, int line)
121 ULONG refcount;
122 IUnknown_AddRef(obj);
123 refcount = IUnknown_Release(obj);
124 ok_(__FILE__, line)(refcount == expected_refcount, "Unexpected refcount %ld, expected %ld.\n", refcount,
125 expected_refcount);
128 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
129 static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported)
131 IUnknown *iface = iface_ptr;
132 HRESULT hr, expected_hr;
133 IUnknown *unk;
135 expected_hr = supported ? S_OK : E_NOINTERFACE;
137 hr = IUnknown_QueryInterface(iface, iid, (void **)&unk);
138 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#lx, expected %#lx.\n", hr, expected_hr);
139 if (SUCCEEDED(hr))
140 IUnknown_Release(unk);
143 #define check_member_(file, line, val, exp, fmt, member) \
144 ok_ (file, line)((val).member == (exp).member, "got " #member " " fmt "\n", (val).member)
145 #define check_member(val, exp, fmt, member) check_member_(__FILE__, __LINE__, val, exp, fmt, member)
147 void check_attributes_(const char *file, int line, IMFAttributes *attributes,
148 const struct attribute_desc *desc, ULONG limit)
150 char buffer[256], *buf = buffer;
151 PROPVARIANT value;
152 int i, j, ret;
153 HRESULT hr;
155 for (i = 0; i < limit && desc[i].key; ++i)
157 hr = IMFAttributes_GetItem(attributes, desc[i].key, &value);
158 todo_wine_if(desc[i].todo)
159 ok_(file, line)(hr == S_OK, "%s missing, hr %#lx\n", debugstr_a(desc[i].name), hr);
160 if (hr != S_OK) continue;
162 switch (value.vt)
164 default: sprintf(buffer, "??"); break;
165 case VT_CLSID: sprintf(buffer, "%s", debugstr_guid(value.puuid)); break;
166 case VT_UI4: sprintf(buffer, "%lu", value.ulVal); break;
167 case VT_UI8:
168 if (desc[i].ratio)
169 sprintf(buffer, "%lu:%lu", value.uhVal.HighPart, value.uhVal.LowPart);
170 else
171 sprintf(buffer, "%I64u", value.uhVal.QuadPart);
172 break;
173 case VT_VECTOR | VT_UI1:
174 buf += sprintf(buf, "size %lu, data {", value.caub.cElems);
175 for (j = 0; j < 16 && j < value.caub.cElems; ++j)
176 buf += sprintf(buf, "0x%02x,", value.caub.pElems[j]);
177 if (value.caub.cElems > 16)
178 buf += sprintf(buf, "...}");
179 else
180 buf += sprintf(buf - (j ? 1 : 0), "}");
181 break;
184 ret = PropVariantCompareEx(&value, &desc[i].value, 0, 0);
185 todo_wine_if(desc[i].todo_value)
186 ok_(file, line)(ret == 0, "%s mismatch, type %u, value %s\n",
187 debugstr_a(desc[i].name), value.vt, buffer);
191 struct transform_info
193 const WCHAR *name;
194 const GUID *major_type;
195 struct
197 const GUID *subtype;
198 BOOL broken;
199 } inputs[32], input_end, outputs[32], output_end;
202 static BOOL check_mft_enum(GUID category, MFT_REGISTER_TYPE_INFO *input_type,
203 MFT_REGISTER_TYPE_INFO *output_type, const GUID *expect_class_id)
205 GUID *class_ids = NULL;
206 UINT32 count = 0, i;
207 HRESULT hr;
209 hr = MFTEnum(category, 0, input_type, output_type, NULL, &class_ids, &count);
210 if (FAILED(hr) || count == 0)
212 todo_wine
213 win_skip("MFTEnum returned %#lx, count %u, skipping tests.\n", hr, count);
214 return FALSE;
217 ok(hr == S_OK, "MFTEnum returned %#lx\n", hr);
218 for (i = 0; i < count; ++i)
219 if (IsEqualGUID(expect_class_id, class_ids + i))
220 break;
221 ok(i < count, "Failed to find transform.\n");
222 CoTaskMemFree(class_ids);
224 return i < count;
227 static void check_mft_get_info(const GUID *class_id, const struct transform_info *expect)
229 MFT_REGISTER_TYPE_INFO *input_types = NULL, *output_types = NULL;
230 UINT32 input_count = 0, output_count = 0, i;
231 WCHAR *name;
232 HRESULT hr;
234 hr = MFTGetInfo(*class_id, &name, &input_types, &input_count, &output_types, &output_count, NULL);
235 ok(hr == S_OK, "MFTEnum returned %#lx\n", hr);
236 ok(!wcscmp(name, expect->name), "got name %s\n", debugstr_w(name));
238 for (i = 0; i < input_count && expect->inputs[i].subtype; ++i)
240 ok(IsEqualGUID(&input_types[i].guidMajorType, expect->major_type),
241 "got input[%u] major %s\n", i, debugstr_guid(&input_types[i].guidMajorType));
242 ok(IsEqualGUID(&input_types[i].guidSubtype, expect->inputs[i].subtype),
243 "got input[%u] subtype %s\n", i, debugstr_guid(&input_types[i].guidSubtype));
245 for (; expect->inputs[i].subtype; ++i)
246 ok(broken(expect->inputs[i].broken), "missing input[%u] subtype %s\n",
247 i, debugstr_guid(expect->inputs[i].subtype));
248 for (; i < input_count; ++i)
249 ok(0, "extra input[%u] subtype %s\n", i, debugstr_guid(&input_types[i].guidSubtype));
251 for (i = 0; expect->outputs[i].subtype; ++i)
253 ok(IsEqualGUID(&output_types[i].guidMajorType, expect->major_type),
254 "got output[%u] major %s\n", i, debugstr_guid(&output_types[i].guidMajorType));
255 ok(IsEqualGUID(&output_types[i].guidSubtype, expect->outputs[i].subtype),
256 "got output[%u] subtype %s\n", i, debugstr_guid(&output_types[i].guidSubtype));
258 for (; expect->outputs[i].subtype; ++i)
259 ok(0, "missing output[%u] subtype %s\n", i, debugstr_guid(expect->outputs[i].subtype));
260 for (; i < output_count; ++i)
261 ok(0, "extra output[%u] subtype %s\n", i, debugstr_guid(&output_types[i].guidSubtype));
263 CoTaskMemFree(output_types);
264 CoTaskMemFree(input_types);
265 CoTaskMemFree(name);
268 static void check_dmo_get_info(const GUID *class_id, const struct transform_info *expect)
270 DWORD input_count = 0, output_count = 0;
271 DMO_PARTIAL_MEDIATYPE output[32] = {{{0}}};
272 DMO_PARTIAL_MEDIATYPE input[32] = {{{0}}};
273 WCHAR name[80];
274 HRESULT hr;
275 int i;
277 hr = DMOGetName(class_id, name);
278 ok(hr == S_OK, "DMOGetName returned %#lx\n", hr);
279 ok(!wcscmp(name, expect->name), "got name %s\n", debugstr_w(name));
281 hr = DMOGetTypes(class_id, ARRAY_SIZE(input), &input_count, input,
282 ARRAY_SIZE(output), &output_count, output);
283 ok(hr == S_OK, "DMOGetTypes returned %#lx\n", hr);
285 for (i = 0; i < input_count && expect->inputs[i].subtype; ++i)
287 ok(IsEqualGUID(&input[i].type, expect->major_type),
288 "got input[%u] major %s\n", i, debugstr_guid(&input[i].type));
289 ok(IsEqualGUID(&input[i].subtype, expect->inputs[i].subtype),
290 "got input[%u] subtype %s\n", i, debugstr_guid(&input[i].subtype));
292 for (; expect->inputs[i].subtype; ++i)
293 ok(0, "missing input[%u] subtype %s\n", i, debugstr_guid(expect->inputs[i].subtype));
294 for (; i < input_count; ++i)
295 ok(0, "extra input[%u] subtype %s\n", i, debugstr_guid(&input[i].subtype));
297 for (i = 0; expect->outputs[i].subtype; ++i)
299 ok(IsEqualGUID(&output[i].type, expect->major_type),
300 "got output[%u] major %s\n", i, debugstr_guid(&output[i].type));
301 ok(IsEqualGUID(&output[i].subtype, expect->outputs[i].subtype),
302 "got output[%u] subtype %s\n", i, debugstr_guid(&output[i].subtype));
304 for (; expect->outputs[i].subtype; ++i)
305 ok(0, "missing output[%u] subtype %s\n", i, debugstr_guid(expect->outputs[i].subtype));
306 for (; i < output_count; ++i)
307 ok(0, "extra output[%u] subtype %s\n", i, debugstr_guid(&output[i].subtype));
310 void init_media_type(IMFMediaType *mediatype, const struct attribute_desc *desc, ULONG limit)
312 HRESULT hr;
313 ULONG i;
315 hr = IMFMediaType_DeleteAllItems(mediatype);
316 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
318 for (i = 0; i < limit && desc[i].key; ++i)
320 hr = IMFMediaType_SetItem(mediatype, desc[i].key, &desc[i].value);
321 ok(hr == S_OK, "SetItem %s returned %#lx\n", debugstr_a(desc[i].name), hr);
325 static void init_dmo_media_type_video(DMO_MEDIA_TYPE *media_type,
326 const GUID *subtype, const LONG width, const LONG height)
328 VIDEOINFOHEADER *header = (VIDEOINFOHEADER *)(media_type + 1);
329 BOOL compressed = is_compressed_subtype(subtype);
331 memset(header, 0, sizeof(*header));
332 header->bmiHeader.biSize = sizeof(header->bmiHeader);
333 header->bmiHeader.biWidth = width;
334 header->bmiHeader.biHeight = height;
335 header->bmiHeader.biBitCount = subtype_to_bpp(subtype);
336 header->bmiHeader.biCompression = subtype_to_compression(subtype);
338 media_type->majortype = MEDIATYPE_Video;
339 media_type->subtype = *subtype;
340 media_type->bFixedSizeSamples = !compressed;
341 media_type->bTemporalCompression = compressed;
342 media_type->lSampleSize = 0;
343 media_type->formattype = FORMAT_VideoInfo;
344 media_type->pUnk = NULL;
345 media_type->cbFormat = sizeof(*header) + 4; /* 4 bytes codec data. */
346 media_type->pbFormat = (BYTE *)header;
349 static void check_mft_optional_methods(IMFTransform *transform, DWORD output_count)
351 DWORD in_id, out_id, in_count, out_count, in_min, in_max, out_min, out_max;
352 PROPVARIANT propvar = {.vt = VT_EMPTY};
353 IMFMediaEvent *event;
354 HRESULT hr;
356 in_min = in_max = out_min = out_max = 0xdeadbeef;
357 hr = IMFTransform_GetStreamLimits(transform, &in_min, &in_max, &out_min, &out_max);
358 ok(hr == S_OK, "GetStreamLimits returned %#lx\n", hr);
359 ok(in_min == 1, "got input_min %lu\n", in_min);
360 ok(in_max == 1, "got input_max %lu\n", in_max);
361 ok(out_min == output_count, "got output_min %lu\n", out_min);
362 ok(out_max == output_count, "got output_max %lu\n", out_max);
364 in_count = out_count = 0xdeadbeef;
365 hr = IMFTransform_GetStreamCount(transform, &in_count, &out_count);
366 ok(hr == S_OK, "GetStreamCount returned %#lx\n", hr);
367 ok(in_count == 1, "got input_count %lu\n", in_count);
368 ok(out_count == output_count, "got output_count %lu\n", out_count);
370 in_count = out_count = 1;
371 in_id = out_id = 0xdeadbeef;
372 hr = IMFTransform_GetStreamIDs(transform, in_count, &in_id, out_count, &out_id);
373 ok(hr == E_NOTIMPL, "GetStreamIDs returned %#lx\n", hr);
375 hr = IMFTransform_DeleteInputStream(transform, 0);
376 ok(hr == E_NOTIMPL, "DeleteInputStream returned %#lx\n", hr);
377 hr = IMFTransform_DeleteInputStream(transform, 1);
378 ok(hr == E_NOTIMPL, "DeleteInputStream returned %#lx\n", hr);
380 hr = IMFTransform_AddInputStreams(transform, 0, NULL);
381 ok(hr == E_NOTIMPL, "AddInputStreams returned %#lx\n", hr);
382 in_id = 0xdeadbeef;
383 hr = IMFTransform_AddInputStreams(transform, 1, &in_id);
384 ok(hr == E_NOTIMPL, "AddInputStreams returned %#lx\n", hr);
386 hr = IMFTransform_SetOutputBounds(transform, 0, 0);
387 ok(hr == E_NOTIMPL || hr == S_OK, "SetOutputBounds returned %#lx\n", hr);
389 hr = MFCreateMediaEvent(MEEndOfStream, &GUID_NULL, S_OK, &propvar, &event);
390 ok(hr == S_OK, "MFCreateMediaEvent returned %#lx\n", hr);
391 hr = IMFTransform_ProcessEvent(transform, 0, NULL);
392 ok(hr == E_NOTIMPL || hr == E_POINTER || hr == E_INVALIDARG, "ProcessEvent returned %#lx\n", hr);
393 hr = IMFTransform_ProcessEvent(transform, 1, event);
394 ok(hr == E_NOTIMPL, "ProcessEvent returned %#lx\n", hr);
395 hr = IMFTransform_ProcessEvent(transform, 0, event);
396 ok(hr == E_NOTIMPL, "ProcessEvent returned %#lx\n", hr);
397 IMFMediaEvent_Release(event);
400 static void check_mft_get_attributes(IMFTransform *transform, const struct attribute_desc *expect_transform_attributes,
401 BOOL expect_output_attributes)
403 IMFAttributes *attributes, *tmp_attributes;
404 UINT32 count;
405 HRESULT hr;
406 ULONG ref;
408 hr = IMFTransform_GetAttributes(transform, &attributes);
409 todo_wine_if(expect_transform_attributes && hr == E_NOTIMPL)
410 ok(hr == (expect_transform_attributes ? S_OK : E_NOTIMPL), "GetAttributes returned %#lx\n", hr);
411 if (hr == S_OK)
413 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
414 check_attributes(attributes, expect_transform_attributes, -1);
416 hr = IMFTransform_GetAttributes(transform, &tmp_attributes);
417 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
418 ok(attributes == tmp_attributes, "got attributes %p\n", tmp_attributes);
419 IMFAttributes_Release(tmp_attributes);
421 ref = IMFAttributes_Release(attributes);
422 ok(ref == 1, "Release returned %lu\n", ref);
425 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes);
426 todo_wine_if(expect_output_attributes && hr == E_NOTIMPL)
427 ok(hr == (expect_output_attributes ? S_OK : E_NOTIMPL)
428 || broken(hr == MF_E_UNSUPPORTED_REPRESENTATION) /* Win7 */,
429 "GetOutputStreamAttributes returned %#lx\n", hr);
430 if (hr == S_OK)
432 ok(hr == S_OK, "GetOutputStreamAttributes returned %#lx\n", hr);
434 count = 0xdeadbeef;
435 hr = IMFAttributes_GetCount(attributes, &count);
436 ok(hr == S_OK, "GetCount returned %#lx\n", hr);
437 ok(!count, "got %u attributes\n", count);
439 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &tmp_attributes);
440 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
441 ok(attributes == tmp_attributes, "got attributes %p\n", tmp_attributes);
442 IMFAttributes_Release(tmp_attributes);
444 ref = IMFAttributes_Release(attributes);
445 ok(ref == 1, "Release returned %lu\n", ref);
447 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, NULL);
448 ok(hr == E_NOTIMPL || hr == E_POINTER, "GetOutputStreamAttributes returned %#lx\n", hr);
449 hr = IMFTransform_GetOutputStreamAttributes(transform, 1, &attributes);
450 ok(hr == MF_E_INVALIDSTREAMNUMBER, "GetOutputStreamAttributes returned %#lx\n", hr);
453 hr = IMFTransform_GetInputStreamAttributes(transform, 0, &attributes);
454 ok(hr == E_NOTIMPL || broken(hr == MF_E_UNSUPPORTED_REPRESENTATION) /* Win7 */,
455 "GetInputStreamAttributes returned %#lx\n", hr);
458 #define check_mft_input_stream_info(a, b) check_mft_input_stream_info_(__LINE__, a, b)
459 static void check_mft_input_stream_info_(int line, MFT_INPUT_STREAM_INFO *value, const MFT_INPUT_STREAM_INFO *expect)
461 check_member_(__FILE__, line, *value, *expect, "%I64d", hnsMaxLatency);
462 check_member_(__FILE__, line, *value, *expect, "%#lx", dwFlags);
463 check_member_(__FILE__, line, *value, *expect, "%#lx", cbSize);
464 check_member_(__FILE__, line, *value, *expect, "%#lx", cbMaxLookahead);
465 check_member_(__FILE__, line, *value, *expect, "%#lx", cbAlignment);
468 #define check_mft_get_input_stream_info(a, b, c) check_mft_get_input_stream_info_(__LINE__, a, b, c)
469 static void check_mft_get_input_stream_info_(int line, IMFTransform *transform, HRESULT expect_hr, const MFT_INPUT_STREAM_INFO *expect)
471 MFT_INPUT_STREAM_INFO info, empty = {0};
472 HRESULT hr;
474 memset(&info, 0xcd, sizeof(info));
475 hr = IMFTransform_GetInputStreamInfo(transform, 0, &info);
476 ok_(__FILE__, line)(hr == expect_hr, "GetInputStreamInfo returned %#lx\n", hr);
477 check_mft_input_stream_info_(line, &info, expect ? expect : &empty);
480 #define check_mft_output_stream_info(a, b) check_mft_output_stream_info_(__LINE__, a, b)
481 static void check_mft_output_stream_info_(int line, MFT_OUTPUT_STREAM_INFO *value, const MFT_OUTPUT_STREAM_INFO *expect)
483 check_member_(__FILE__, line, *value, *expect, "%#lx", dwFlags);
484 check_member_(__FILE__, line, *value, *expect, "%#lx", cbSize);
485 check_member_(__FILE__, line, *value, *expect, "%#lx", cbAlignment);
488 #define check_mft_get_output_stream_info(a, b, c) check_mft_get_output_stream_info_(__LINE__, a, b, c)
489 static void check_mft_get_output_stream_info_(int line, IMFTransform *transform, HRESULT expect_hr, const MFT_OUTPUT_STREAM_INFO *expect)
491 MFT_OUTPUT_STREAM_INFO info, empty = {0};
492 HRESULT hr;
494 memset(&info, 0xcd, sizeof(info));
495 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &info);
496 ok_(__FILE__, line)(hr == expect_hr, "GetOutputStreamInfo returned %#lx\n", hr);
497 check_mft_output_stream_info_(line, &info, expect ? expect : &empty);
500 #define check_mft_set_input_type_required(a, b) check_mft_set_input_type_required_(__LINE__, a, b)
501 static void check_mft_set_input_type_required_(int line, IMFTransform *transform, const struct attribute_desc *attributes)
503 const struct attribute_desc *attr;
504 IMFMediaType *media_type;
505 HRESULT hr;
506 ULONG ref;
508 hr = MFCreateMediaType(&media_type);
509 ok_(__FILE__, line)(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
510 init_media_type(media_type, attributes, -1);
512 for (attr = attributes; attr && attr->key; attr++)
514 winetest_push_context("%s", debugstr_a(attr->name));
515 hr = IMFMediaType_DeleteItem(media_type, attr->key);
516 ok_(__FILE__, line)(hr == S_OK, "DeleteItem returned %#lx\n", hr);
517 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
518 ok_(__FILE__, line)(FAILED(hr) == attr->required, "SetInputType returned %#lx.\n", hr);
519 hr = IMFMediaType_SetItem(media_type, attr->key, &attr->value);
520 ok_(__FILE__, line)(hr == S_OK, "SetItem returned %#lx\n", hr);
521 winetest_pop_context();
524 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
525 ok_(__FILE__, line)(hr == S_OK, "SetInputType returned %#lx.\n", hr);
526 ref = IMFMediaType_Release(media_type);
527 ok_(__FILE__, line)(!ref, "Release returned %lu\n", ref);
530 static void check_mft_set_input_type(IMFTransform *transform, const struct attribute_desc *attributes)
532 IMFMediaType *media_type;
533 HRESULT hr;
535 hr = MFCreateMediaType(&media_type);
536 ok(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
537 init_media_type(media_type, attributes, -1);
539 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
540 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
541 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
542 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
544 IMFMediaType_Release(media_type);
547 #define check_mft_get_input_current_type(a, b) check_mft_get_input_current_type_(a, b, FALSE, FALSE)
548 static void check_mft_get_input_current_type_(IMFTransform *transform, const struct attribute_desc *attributes,
549 BOOL todo_current, BOOL todo_compare)
551 HRESULT hr, expect_hr = attributes ? S_OK : MF_E_TRANSFORM_TYPE_NOT_SET;
552 IMFMediaType *media_type, *current_type;
553 BOOL result;
555 hr = IMFTransform_GetInputCurrentType(transform, 0, &current_type);
556 todo_wine_if(todo_current)
557 ok(hr == expect_hr, "GetInputCurrentType returned hr %#lx.\n", hr);
558 if (FAILED(hr))
559 return;
561 hr = MFCreateMediaType(&media_type);
562 ok(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
563 init_media_type(media_type, attributes, -1);
565 hr = IMFMediaType_Compare(current_type, (IMFAttributes *)media_type,
566 MF_ATTRIBUTES_MATCH_ALL_ITEMS, &result);
567 ok(hr == S_OK, "Compare returned hr %#lx.\n", hr);
568 todo_wine_if(todo_compare)
569 ok(result, "got result %u.\n", !!result);
571 IMFMediaType_Release(media_type);
572 IMFMediaType_Release(current_type);
575 #define check_mft_set_output_type_required(a, b) check_mft_set_output_type_required_(__LINE__, a, b)
576 static void check_mft_set_output_type_required_(int line, IMFTransform *transform, const struct attribute_desc *attributes)
578 const struct attribute_desc *attr;
579 IMFMediaType *media_type;
580 HRESULT hr;
581 ULONG ref;
583 hr = MFCreateMediaType(&media_type);
584 ok_(__FILE__, line)(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
585 init_media_type(media_type, attributes, -1);
587 for (attr = attributes; attr && attr->key; attr++)
589 winetest_push_context("%s", debugstr_a(attr->name));
590 hr = IMFMediaType_DeleteItem(media_type, attr->key);
591 ok_(__FILE__, line)(hr == S_OK, "DeleteItem returned %#lx\n", hr);
592 hr = IMFTransform_SetOutputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
593 ok_(__FILE__, line)(FAILED(hr) == attr->required, "SetOutputType returned %#lx.\n", hr);
594 hr = IMFMediaType_SetItem(media_type, attr->key, &attr->value);
595 ok_(__FILE__, line)(hr == S_OK, "SetItem returned %#lx\n", hr);
596 winetest_pop_context();
599 hr = IMFTransform_SetOutputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
600 ok_(__FILE__, line)(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
601 ref = IMFMediaType_Release(media_type);
602 ok_(__FILE__, line)(!ref, "Release returned %lu\n", ref);
605 static void check_mft_set_output_type(IMFTransform *transform, const struct attribute_desc *attributes,
606 HRESULT expect_hr)
608 IMFMediaType *media_type;
609 HRESULT hr;
611 hr = MFCreateMediaType(&media_type);
612 ok(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
613 init_media_type(media_type, attributes, -1);
615 hr = IMFTransform_SetOutputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
616 ok(hr == expect_hr, "SetOutputType returned %#lx.\n", hr);
617 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
618 ok(hr == expect_hr, "SetOutputType returned %#lx.\n", hr);
620 IMFMediaType_Release(media_type);
623 #define check_mft_get_output_current_type(a, b) check_mft_get_output_current_type_(a, b, FALSE, FALSE)
624 static void check_mft_get_output_current_type_(IMFTransform *transform, const struct attribute_desc *attributes,
625 BOOL todo_current, BOOL todo_compare)
627 HRESULT hr, expect_hr = attributes ? S_OK : MF_E_TRANSFORM_TYPE_NOT_SET;
628 IMFMediaType *media_type, *current_type;
629 BOOL result;
631 hr = IMFTransform_GetOutputCurrentType(transform, 0, &current_type);
632 todo_wine_if(todo_current)
633 ok(hr == expect_hr, "GetOutputCurrentType returned hr %#lx.\n", hr);
634 if (FAILED(hr))
635 return;
637 hr = MFCreateMediaType(&media_type);
638 ok(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
639 init_media_type(media_type, attributes, -1);
641 hr = IMFMediaType_Compare(current_type, (IMFAttributes *)media_type,
642 MF_ATTRIBUTES_MATCH_ALL_ITEMS, &result);
643 ok(hr == S_OK, "Compare returned hr %#lx.\n", hr);
644 todo_wine_if(todo_compare)
645 ok(result, "got result %u.\n", !!result);
647 IMFMediaType_Release(media_type);
648 IMFMediaType_Release(current_type);
651 #define check_mft_process_output(a, b, c) check_mft_process_output_(__LINE__, a, b, c)
652 static HRESULT check_mft_process_output_(int line, IMFTransform *transform, IMFSample *output_sample, DWORD *output_status)
654 static const DWORD expect_flags = MFT_OUTPUT_DATA_BUFFER_INCOMPLETE | MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE
655 | MFT_OUTPUT_DATA_BUFFER_STREAM_END | MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE;
656 MFT_OUTPUT_DATA_BUFFER output[3];
657 HRESULT hr, ret;
658 DWORD status;
660 status = 0;
661 memset(&output, 0, sizeof(output));
662 output[0].pSample = output_sample;
663 output[0].dwStreamID = 0;
664 ret = IMFTransform_ProcessOutput(transform, 0, 1, output, &status);
665 ok_(__FILE__, line)(output[0].dwStreamID == 0, "got dwStreamID %#lx\n", output[0].dwStreamID);
666 ok_(__FILE__, line)(output[0].pEvents == NULL, "got pEvents %p\n", output[0].pEvents);
667 ok_(__FILE__, line)(output[0].pSample == output_sample, "got pSample %p\n", output[0].pSample);
668 ok_(__FILE__, line)((output[0].dwStatus & ~expect_flags) == 0
669 || broken((output[0].dwStatus & ~expect_flags) == 6) /* Win7 */
670 || broken((output[0].dwStatus & ~expect_flags) == 7) /* Win7 */,
671 "got dwStatus %#lx\n", output[0].dwStatus);
672 *output_status = output[0].dwStatus & expect_flags;
674 if (!output_sample)
675 ok_(__FILE__, line)(status == 0, "got status %#lx\n", status);
676 else if (ret == MF_E_TRANSFORM_STREAM_CHANGE)
677 ok_(__FILE__, line)(status == MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS,
678 "got status %#lx\n", status);
679 else
681 if (*output_status & MFT_OUTPUT_DATA_BUFFER_INCOMPLETE)
683 hr = IMFSample_SetUINT32(output_sample, &mft_output_sample_incomplete, 1);
684 ok_(__FILE__, line)(hr == S_OK, "SetUINT32 returned %#lx\n", hr);
686 else
688 hr = IMFSample_DeleteItem(output_sample, &mft_output_sample_incomplete);
689 ok_(__FILE__, line)(hr == S_OK, "DeleteItem returned %#lx\n", hr);
691 ok_(__FILE__, line)(status == 0, "got status %#lx\n", status);
694 return ret;
697 DWORD compare_nv12(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
699 DWORD x, y, size, diff = 0, width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
701 /* skip BMP header and RGB data from the dump */
702 size = *(DWORD *)(expect + 2);
703 *length = *length + size;
704 expect = expect + size;
706 for (y = 0; y < height; y++, data += width, expect += width)
708 if (y < rect->top || y >= rect->bottom) continue;
709 for (x = 0; x < width; x++)
711 if (x < rect->left || x >= rect->right) continue;
712 diff += abs((int)expect[x] - (int)data[x]);
716 for (y = 0; y < height; y += 2, data += width, expect += width)
718 if (y < rect->top || y >= rect->bottom) continue;
719 for (x = 0; x < width; x += 2)
721 if (x < rect->left || x >= rect->right) continue;
722 diff += abs((int)expect[x + 0] - (int)data[x + 0]);
723 diff += abs((int)expect[x + 1] - (int)data[x + 1]);
727 size = (rect->right - rect->left) * (rect->bottom - rect->top) * 3 / 2;
728 return diff * 100 / 256 / size;
731 DWORD compare_i420(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
733 DWORD i, x, y, size, diff = 0, width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
735 /* skip BMP header and RGB data from the dump */
736 size = *(DWORD *)(expect + 2);
737 *length = *length + size;
738 expect = expect + size;
740 for (y = 0; y < height; y++, data += width, expect += width)
742 if (y < rect->top || y >= rect->bottom) continue;
743 for (x = 0; x < width; x++)
745 if (x < rect->left || x >= rect->right) continue;
746 diff += abs((int)expect[x] - (int)data[x]);
750 for (i = 0; i < 2; ++i) for (y = 0; y < height; y += 2, data += width / 2, expect += width / 2)
752 if (y < rect->top || y >= rect->bottom) continue;
753 for (x = 0; x < width; x += 2)
755 if (x < rect->left || x >= rect->right) continue;
756 diff += abs((int)expect[x / 2] - (int)data[x / 2]);
760 size = (rect->right - rect->left) * (rect->bottom - rect->top) * 3 / 2;
761 return diff * 100 / 256 / size;
764 DWORD compare_rgb32(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
766 DWORD x, y, size, diff = 0, width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
768 /* skip BMP header from the dump */
769 size = *(DWORD *)(expect + 2 + 2 * sizeof(DWORD));
770 *length = *length + size;
771 expect = expect + size;
773 for (y = 0; y < height; y++, data += width * 4, expect += width * 4)
775 if (y < rect->top || y >= rect->bottom) continue;
776 for (x = 0; x < width; x++)
778 if (x < rect->left || x >= rect->right) continue;
779 diff += abs((int)expect[4 * x + 0] - (int)data[4 * x + 0]);
780 diff += abs((int)expect[4 * x + 1] - (int)data[4 * x + 1]);
781 diff += abs((int)expect[4 * x + 2] - (int)data[4 * x + 2]);
785 size = (rect->right - rect->left) * (rect->bottom - rect->top) * 3;
786 return diff * 100 / 256 / size;
789 DWORD compare_pcm16(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
791 const INT16 *data_pcm = (INT16 *)data, *expect_pcm = (INT16 *)expect;
792 DWORD i, size = *length / 2, diff = 0;
794 for (i = 0; i < size; i++)
795 diff += abs((int)*expect_pcm++ - (int)*data_pcm++);
797 return diff * 100 / 65536 / size;
800 static DWORD compare_bytes(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
802 DWORD i, size = *length, diff = 0;
804 for (i = 0; i < size; i++)
805 diff += abs((int)*expect++ - (int)*data++);
807 return diff * 100 / 256 / size;
810 void dump_rgb32(const BYTE *data, DWORD length, const RECT *rect, HANDLE output)
812 DWORD width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
813 static const char magic[2] = "BM";
814 struct
816 DWORD length;
817 DWORD reserved;
818 DWORD offset;
819 BITMAPINFOHEADER biHeader;
820 } header =
822 .length = length + sizeof(header) + 2, .offset = sizeof(header) + 2,
823 .biHeader =
825 .biSize = sizeof(BITMAPINFOHEADER), .biWidth = width, .biHeight = height, .biPlanes = 1,
826 .biBitCount = 32, .biCompression = BI_RGB, .biSizeImage = width * height * 4,
829 DWORD written;
830 BOOL ret;
832 ret = WriteFile(output, magic, sizeof(magic), &written, NULL);
833 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
834 ok(written == sizeof(magic), "written %lu bytes\n", written);
835 ret = WriteFile(output, &header, sizeof(header), &written, NULL);
836 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
837 ok(written == sizeof(header), "written %lu bytes\n", written);
838 ret = WriteFile(output, data, length, &written, NULL);
839 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
840 ok(written == length, "written %lu bytes\n", written);
843 void dump_nv12(const BYTE *data, DWORD length, const RECT *rect, HANDLE output)
845 DWORD written, x, y, width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
846 BYTE *rgb32_data = malloc(width * height * 4), *rgb32 = rgb32_data;
847 BOOL ret;
849 for (y = 0; y < height; y++) for (x = 0; x < width; x++)
851 *rgb32++ = data[width * y + x];
852 *rgb32++ = data[width * height + width * (y / 2) + (x & ~1) + 0];
853 *rgb32++ = data[width * height + width * (y / 2) + (x & ~1) + 1];
854 *rgb32++ = 0xff;
857 dump_rgb32(rgb32_data, width * height * 4, rect, output);
858 free(rgb32_data);
860 ret = WriteFile(output, data, length, &written, NULL);
861 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
862 ok(written == length, "written %lu bytes\n", written);
865 void dump_i420(const BYTE *data, DWORD length, const RECT *rect, HANDLE output)
867 DWORD written, x, y, width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
868 BYTE *rgb32_data = malloc(width * height * 4), *rgb32 = rgb32_data;
869 BOOL ret;
871 for (y = 0; y < height; y++) for (x = 0; x < width; x++)
873 *rgb32++ = data[width * y + x];
874 *rgb32++ = data[width * height + (width / 2) * (y / 2) + x / 2];
875 *rgb32++ = data[width * height + (width / 2) * (y / 2) + (width / 2) * (height / 2) + x / 2];
876 *rgb32++ = 0xff;
879 dump_rgb32(rgb32_data, width * height * 4, rect, output);
880 free(rgb32_data);
882 ret = WriteFile(output, data, length, &written, NULL);
883 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
884 ok(written == length, "written %lu bytes\n", written);
887 typedef void (*enum_mf_media_buffers_cb)(IMFMediaBuffer *buffer, const struct buffer_desc *desc, void *context);
888 static void enum_mf_media_buffers(IMFSample *sample, const struct sample_desc *sample_desc,
889 enum_mf_media_buffers_cb callback, void *context)
891 IMFMediaBuffer *buffer;
892 HRESULT hr;
893 DWORD i;
895 for (i = 0; SUCCEEDED(hr = IMFSample_GetBufferByIndex(sample, i, &buffer)); i++)
897 winetest_push_context("buffer %lu", i);
898 ok(hr == S_OK, "GetBufferByIndex returned %#lx\n", hr);
899 ok(i < sample_desc->buffer_count, "got unexpected buffer\n");
901 callback(buffer, sample_desc->buffers + i, context);
903 IMFMediaBuffer_Release(buffer);
904 winetest_pop_context();
906 ok(hr == E_INVALIDARG, "GetBufferByIndex returned %#lx\n", hr);
909 struct enum_mf_sample_state
911 const struct sample_desc *next_sample;
912 struct sample_desc sample;
915 typedef void (*enum_mf_sample_cb)(IMFSample *sample, const struct sample_desc *sample_desc, void *context);
916 static void enum_mf_samples(IMFCollection *samples, const struct sample_desc *collection_desc,
917 enum_mf_sample_cb callback, void *context)
919 struct enum_mf_sample_state state = {.next_sample = collection_desc};
920 IMFSample *sample;
921 HRESULT hr;
922 DWORD i;
924 for (i = 0; SUCCEEDED(hr = IMFCollection_GetElement(samples, i, (IUnknown **)&sample)); i++)
926 winetest_push_context("sample %lu", i);
927 ok(hr == S_OK, "GetElement returned %#lx\n", hr);
929 state.sample.sample_time += state.sample.sample_duration;
930 if (!state.sample.repeat_count--)
931 state.sample = *state.next_sample++;
933 callback(sample, &state.sample, context);
935 IMFSample_Release(sample);
936 winetest_pop_context();
938 ok(hr == E_INVALIDARG, "GetElement returned %#lx\n", hr);
941 static void dump_mf_media_buffer(IMFMediaBuffer *buffer, const struct buffer_desc *buffer_desc, HANDLE output)
943 DWORD length, written;
944 HRESULT hr;
945 BYTE *data;
946 BOOL ret;
948 hr = IMFMediaBuffer_Lock(buffer, &data, NULL, &length);
949 ok(hr == S_OK, "Lock returned %#lx\n", hr);
951 if (buffer_desc->dump)
952 buffer_desc->dump(data, length, &buffer_desc->rect, output);
953 else
955 if (buffer_desc->length == -1)
957 ret = WriteFile(output, &length, sizeof(length), &written, NULL);
958 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
959 ok(written == sizeof(length), "written %lu bytes\n", written);
962 ret = WriteFile(output, data, length, &written, NULL);
963 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
964 ok(written == length, "written %lu bytes\n", written);
967 hr = IMFMediaBuffer_Unlock(buffer);
968 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
971 static void dump_mf_sample(IMFSample *sample, const struct sample_desc *sample_desc, HANDLE output)
973 enum_mf_media_buffers(sample, sample_desc, dump_mf_media_buffer, output);
976 static void dump_mf_sample_collection(IMFCollection *samples, const struct sample_desc *collection_desc,
977 const WCHAR *output_filename)
979 WCHAR path[MAX_PATH];
980 HANDLE output;
982 GetTempPathW(ARRAY_SIZE(path), path);
983 lstrcatW(path, output_filename);
985 output = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
986 ok(output != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
988 enum_mf_samples(samples, collection_desc, dump_mf_sample, output);
990 trace("created %s\n", debugstr_w(path));
991 CloseHandle(output);
994 #define check_mf_media_buffer(a, b, c) check_mf_media_buffer_(__FILE__, __LINE__, a, b, c)
995 static DWORD check_mf_media_buffer_(const char *file, int line, IMFMediaBuffer *buffer, const struct buffer_desc *expect,
996 const BYTE **expect_data, DWORD *expect_data_len)
998 DWORD length, diff = 0, expect_length = expect->length;
999 HRESULT hr;
1000 BYTE *data;
1002 if (expect_length == -1)
1004 expect_length = *(DWORD *)*expect_data;
1005 *expect_data = *expect_data + sizeof(DWORD);
1006 *expect_data_len = *expect_data_len - sizeof(DWORD);
1009 hr = IMFMediaBuffer_Lock(buffer, &data, NULL, &length);
1010 ok_(file, line)(hr == S_OK, "Lock returned %#lx\n", hr);
1011 todo_wine_if(expect->todo_length)
1012 ok_(file, line)(length == expect_length, "got length %#lx\n", length);
1014 if (*expect_data_len < length)
1015 todo_wine_if(expect->todo_length)
1016 ok_(file, line)(0, "missing %#lx bytes\n", length - *expect_data_len);
1017 else if (!expect->compare)
1018 diff = compare_bytes(data, &length, NULL, *expect_data);
1019 else
1020 diff = expect->compare(data, &length, &expect->rect, *expect_data);
1022 hr = IMFMediaBuffer_Unlock(buffer);
1023 ok_(file, line)(hr == S_OK, "Unlock returned %#lx\n", hr);
1025 *expect_data = *expect_data + min(length, *expect_data_len);
1026 *expect_data_len = *expect_data_len - min(length, *expect_data_len);
1028 return diff;
1031 struct check_mf_sample_context
1033 DWORD total_length;
1034 const BYTE *data;
1035 DWORD data_len;
1036 DWORD diff;
1037 const char *file;
1038 int line;
1041 static void check_mf_sample_buffer(IMFMediaBuffer *buffer, const struct buffer_desc *expect, void *context)
1043 struct check_mf_sample_context *ctx = context;
1044 DWORD expect_length = expect->length == -1 ? *(DWORD *)ctx->data : expect->length;
1045 ctx->diff += check_mf_media_buffer_(ctx->file, ctx->line, buffer, expect, &ctx->data, &ctx->data_len);
1046 ctx->total_length += expect_length;
1049 #define check_mf_sample(a, b, c, d) check_mf_sample_(__FILE__, __LINE__, a, b, c, d)
1050 static DWORD check_mf_sample_(const char *file, int line, IMFSample *sample, const struct sample_desc *expect,
1051 const BYTE **expect_data, DWORD *expect_data_len)
1053 struct check_mf_sample_context ctx = {.data = *expect_data, .data_len = *expect_data_len, .file = file, .line = line};
1054 DWORD buffer_count, total_length, sample_flags;
1055 LONGLONG timestamp;
1056 HRESULT hr;
1058 if (expect->attributes)
1059 check_attributes_(file, line, (IMFAttributes *)sample, expect->attributes, -1);
1061 buffer_count = 0xdeadbeef;
1062 hr = IMFSample_GetBufferCount(sample, &buffer_count);
1063 ok_(file, line)(hr == S_OK, "GetBufferCount returned %#lx\n", hr);
1064 ok_(file, line)(buffer_count == expect->buffer_count,
1065 "got %lu buffers\n", buffer_count);
1067 sample_flags = 0xdeadbeef;
1068 hr = IMFSample_GetSampleFlags(sample, &sample_flags);
1069 ok_(file, line)(hr == S_OK, "GetSampleFlags returned %#lx\n", hr);
1070 ok_(file, line)(sample_flags == 0,
1071 "got sample flags %#lx\n", sample_flags);
1073 timestamp = 0xdeadbeef;
1074 hr = IMFSample_GetSampleTime(sample, &timestamp);
1075 ok_(file, line)(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
1076 todo_wine_if(expect->todo_time && timestamp == expect->todo_time)
1077 ok_(file, line)(llabs(timestamp - expect->sample_time) <= 50,
1078 "got sample time %I64d\n", timestamp);
1080 timestamp = 0xdeadbeef;
1081 hr = IMFSample_GetSampleDuration(sample, &timestamp);
1082 ok_(file, line)(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
1083 todo_wine_if(expect->todo_length)
1084 ok_(file, line)(llabs(timestamp - expect->sample_duration) <= 1,
1085 "got sample duration %I64d\n", timestamp);
1087 enum_mf_media_buffers(sample, expect, check_mf_sample_buffer, &ctx);
1089 total_length = 0xdeadbeef;
1090 hr = IMFSample_GetTotalLength(sample, &total_length);
1091 ok_(file, line)(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
1092 todo_wine_if(expect->todo_length)
1093 ok_(file, line)(total_length == ctx.total_length,
1094 "got total length %#lx\n", total_length);
1095 ok_(file, line)(*expect_data_len >= ctx.total_length,
1096 "missing %#lx data\n", ctx.total_length - *expect_data_len);
1098 *expect_data = ctx.data;
1099 *expect_data_len = ctx.data_len;
1101 return ctx.diff / buffer_count;
1104 static void check_mf_sample_collection_enum(IMFSample *sample, const struct sample_desc *expect, void *context)
1106 struct check_mf_sample_context *ctx = context;
1107 ctx->diff += check_mf_sample_(ctx->file, ctx->line, sample, expect, &ctx->data, &ctx->data_len);
1110 DWORD check_mf_sample_collection_(const char *file, int line, IMFCollection *samples,
1111 const struct sample_desc *expect_samples, const WCHAR *expect_data_filename)
1113 struct check_mf_sample_context ctx = {.file = file, .line = line};
1114 DWORD count;
1115 HRESULT hr;
1117 load_resource(expect_data_filename, &ctx.data, &ctx.data_len);
1118 enum_mf_samples(samples, expect_samples, check_mf_sample_collection_enum, &ctx);
1120 dump_mf_sample_collection(samples, expect_samples, expect_data_filename);
1122 hr = IMFCollection_GetElementCount(samples, &count);
1123 ok_(file, line)(hr == S_OK, "GetElementCount returned %#lx\n", hr);
1125 return ctx.diff / count;
1128 #define check_video_info_header(a, b) check_video_info_header_(__LINE__, a, b)
1129 static void check_video_info_header_(int line, VIDEOINFOHEADER *info, const VIDEOINFOHEADER *expected)
1131 ok_(__FILE__, line)(info->rcSource.left == expected->rcSource.left
1132 && info->rcSource.top == expected->rcSource.top
1133 && info->rcSource.right == expected->rcSource.right
1134 && info->rcSource.bottom == expected->rcSource.bottom,
1135 "Got unexpected rcSource {%ld, %ld, %ld, %ld}, expected {%ld, %ld, %ld, %ld}.\n",
1136 info->rcSource.left, info->rcSource.top, info->rcSource.right, info->rcSource.bottom,
1137 expected->rcSource.left, expected->rcSource.top, expected->rcSource.right, expected->rcSource.bottom);
1138 ok_(__FILE__, line)(info->rcTarget.left == expected->rcTarget.left
1139 && info->rcTarget.top == expected->rcTarget.top
1140 && info->rcTarget.right == expected->rcTarget.right
1141 && info->rcTarget.bottom == expected->rcTarget.bottom,
1142 "Got unexpected rcTarget {%ld, %ld, %ld, %ld}, expected {%ld, %ld, %ld, %ld}.\n",
1143 info->rcTarget.left, info->rcTarget.top, info->rcTarget.right, info->rcTarget.bottom,
1144 expected->rcTarget.left, expected->rcTarget.top, expected->rcTarget.right, expected->rcTarget.bottom);
1145 ok_(__FILE__, line)(info->dwBitRate == expected->dwBitRate,
1146 "Got unexpected dwBitRate %lu, expected %lu.\n",
1147 info->dwBitRate, expected->dwBitRate);
1148 ok_(__FILE__, line)(info->dwBitErrorRate == expected->dwBitErrorRate,
1149 "Got unexpected dwBitErrorRate %lu, expected %lu.\n",
1150 info->dwBitErrorRate, expected->dwBitErrorRate);
1151 ok_(__FILE__, line)(info->AvgTimePerFrame == expected->AvgTimePerFrame,
1152 "Got unexpected AvgTimePerFrame %I64d, expected %I64d.\n",
1153 info->AvgTimePerFrame, expected->AvgTimePerFrame);
1154 ok_(__FILE__, line)(info->bmiHeader.biSize == expected->bmiHeader.biSize,
1155 "Got unexpected bmiHeader.biSize %lu, expected %lu.\n",
1156 info->bmiHeader.biSize, expected->bmiHeader.biSize);
1157 ok_(__FILE__, line)(info->bmiHeader.biWidth == expected->bmiHeader.biWidth,
1158 "Got unexpected bmiHeader.biWidth %ld, expected %ld.\n",
1159 info->bmiHeader.biWidth, expected->bmiHeader.biWidth);
1160 ok_(__FILE__, line)(info->bmiHeader.biHeight == expected->bmiHeader.biHeight,
1161 "Got unexpected bmiHeader.biHeight %ld, expected %ld.\n",
1162 info->bmiHeader.biHeight, expected->bmiHeader.biHeight);
1163 ok_(__FILE__, line)(info->bmiHeader.biPlanes == expected->bmiHeader.biPlanes,
1164 "Got unexpected bmiHeader.biPlanes %u, expected %u.\n",
1165 info->bmiHeader.biPlanes, expected->bmiHeader.biPlanes);
1166 ok_(__FILE__, line)(info->bmiHeader.biBitCount == expected->bmiHeader.biBitCount,
1167 "Got unexpected bmiHeader.biBitCount %u, expected %u.\n",
1168 info->bmiHeader.biBitCount, expected->bmiHeader.biBitCount);
1169 ok_(__FILE__, line)(info->bmiHeader.biCompression == expected->bmiHeader.biCompression,
1170 "Got unexpected bmiHeader.biCompression %#lx, expected %#lx.\n",
1171 info->bmiHeader.biCompression, expected->bmiHeader.biCompression);
1172 ok_(__FILE__, line)(info->bmiHeader.biSizeImage == expected->bmiHeader.biSizeImage,
1173 "Got unexpected bmiHeader.biSizeImage %lu, expected %lu.\n",
1174 info->bmiHeader.biSizeImage, expected->bmiHeader.biSizeImage);
1175 ok_(__FILE__, line)(info->bmiHeader.biXPelsPerMeter == expected->bmiHeader.biXPelsPerMeter,
1176 "Got unexpected bmiHeader.biXPelsPerMeter %ld, expected %ld.\n",
1177 info->bmiHeader.biXPelsPerMeter, expected->bmiHeader.biXPelsPerMeter);
1178 ok_(__FILE__, line)(info->bmiHeader.biYPelsPerMeter == expected->bmiHeader.biYPelsPerMeter,
1179 "Got unexpected bmiHeader.xxxxxx %ld, expected %ld.\n",
1180 info->bmiHeader.biYPelsPerMeter, expected->bmiHeader.biYPelsPerMeter);
1181 todo_wine_if(expected->bmiHeader.biClrUsed != 0)
1182 ok_(__FILE__, line)(info->bmiHeader.biClrUsed == expected->bmiHeader.biClrUsed,
1183 "Got unexpected bmiHeader.biClrUsed %lu, expected %lu.\n",
1184 info->bmiHeader.biClrUsed, expected->bmiHeader.biClrUsed);
1185 todo_wine_if(expected->bmiHeader.biClrImportant != 0)
1186 ok_(__FILE__, line)(info->bmiHeader.biClrImportant == expected->bmiHeader.biClrImportant,
1187 "Got unexpected bmiHeader.biClrImportant %lu, expected %lu.\n",
1188 info->bmiHeader.biClrImportant, expected->bmiHeader.biClrImportant);
1191 #define check_dmo_media_type(a, b) check_dmo_media_type_(__LINE__, a, b)
1192 static void check_dmo_media_type_(int line, DMO_MEDIA_TYPE *media_type, const DMO_MEDIA_TYPE *expected)
1194 ok_(__FILE__, line)(IsEqualGUID(&media_type->majortype, &expected->majortype),
1195 "Got unexpected majortype %s, expected %s.\n",
1196 debugstr_guid(&media_type->majortype), debugstr_guid(&expected->majortype));
1197 ok_(__FILE__, line)(IsEqualGUID(&media_type->subtype, &expected->subtype),
1198 "Got unexpected subtype %s, expected %s.\n",
1199 debugstr_guid(&media_type->subtype), debugstr_guid(&expected->subtype));
1200 ok_(__FILE__, line)(media_type->bFixedSizeSamples == expected->bFixedSizeSamples,
1201 "Got unexpected bFixedSizeSamples %d, expected %d.\n",
1202 media_type->bFixedSizeSamples, expected->bFixedSizeSamples);
1203 ok_(__FILE__, line)(media_type->bTemporalCompression == expected->bTemporalCompression,
1204 "Got unexpected bTemporalCompression %d, expected %d.\n",
1205 media_type->bTemporalCompression, expected->bTemporalCompression);
1206 ok_(__FILE__, line)(media_type->lSampleSize == expected->lSampleSize,
1207 "Got unexpected lSampleSize %lu, expected %lu.\n",
1208 media_type->lSampleSize, expected->lSampleSize);
1209 ok_(__FILE__, line)(IsEqualGUID(&media_type->formattype, &expected->formattype),
1210 "Got unexpected formattype %s.\n",
1211 debugstr_guid(&media_type->formattype));
1212 ok_(__FILE__, line)(media_type->pUnk == NULL, "Got unexpected pUnk %p.\n", media_type->pUnk);
1213 todo_wine_if(expected->cbFormat && expected->cbFormat != sizeof(VIDEOINFOHEADER))
1214 ok_(__FILE__, line)(media_type->cbFormat == expected->cbFormat,
1215 "Got unexpected cbFormat %lu, expected %lu.\n",
1216 media_type->cbFormat, expected->cbFormat);
1218 if (expected->pbFormat)
1220 ok_(__FILE__, line)(!!media_type->pbFormat, "Got NULL pbFormat.\n");
1221 if (!media_type->pbFormat)
1222 return;
1224 if (IsEqualGUID(&media_type->formattype, &FORMAT_VideoInfo)
1225 && IsEqualGUID(&expected->formattype, &FORMAT_VideoInfo))
1226 check_video_info_header((VIDEOINFOHEADER *)media_type->pbFormat, (VIDEOINFOHEADER *)expected->pbFormat);
1230 static void check_dmo_get_input_type(IMediaObject *media_object, const DMO_MEDIA_TYPE *expected_type, ULONG count)
1232 DMO_MEDIA_TYPE media_type;
1233 HRESULT hr;
1234 DWORD i;
1236 hr = IMediaObject_GetInputType(media_object, 1, 0, NULL);
1237 ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetInputType returned %#lx.\n", hr);
1238 hr = IMediaObject_GetInputType(media_object, 1, 0, &media_type);
1239 ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetInputType returned %#lx.\n", hr);
1240 hr = IMediaObject_GetInputType(media_object, 1, count, &media_type);
1241 ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetInputType returned %#lx.\n", hr);
1242 hr = IMediaObject_GetInputType(media_object, 0, count, &media_type);
1243 ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned %#lx.\n", hr);
1244 hr = IMediaObject_GetInputType(media_object, 0, count, NULL);
1245 ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned %#lx.\n", hr);
1246 hr = IMediaObject_GetInputType(media_object, 0, 0xdeadbeef, NULL);
1247 ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned %#lx.\n", hr);
1248 hr = IMediaObject_GetInputType(media_object, 0, count - 1, NULL);
1249 ok(hr == S_OK, "GetInputType returned %#lx.\n", hr);
1250 hr = IMediaObject_GetInputType(media_object, 0, count - 1, &media_type);
1251 ok(hr == S_OK, "GetInputType returned %#lx.\n", hr);
1252 if (hr == S_OK)
1253 MoFreeMediaType(&media_type);
1255 i = -1;
1256 while (SUCCEEDED(hr = IMediaObject_GetInputType(media_object, 0, ++i, &media_type)))
1258 winetest_push_context("in %lu", i);
1259 check_dmo_media_type(&media_type, &expected_type[i]);
1260 MoFreeMediaType(&media_type);
1261 winetest_pop_context();
1264 ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned %#lx.\n", hr);
1265 ok(i == count, "%lu types.\n", i);
1268 static void check_dmo_get_output_type(IMediaObject *media_object, const DMO_MEDIA_TYPE *expected_type, ULONG count)
1270 DMO_MEDIA_TYPE media_type;
1271 HRESULT hr;
1272 DWORD i;
1274 hr = IMediaObject_GetOutputType(media_object, 1, 0, NULL);
1275 ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetOutputType returned %#lx.\n", hr);
1276 hr = IMediaObject_GetOutputType(media_object, 1, 0, &media_type);
1277 ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetOutputType returned %#lx.\n", hr);
1278 hr = IMediaObject_GetOutputType(media_object, 1, count, &media_type);
1279 ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetOutputType returned %#lx.\n", hr);
1280 hr = IMediaObject_GetOutputType(media_object, 0, count, &media_type);
1281 ok(hr == DMO_E_NO_MORE_ITEMS, "GetOutputType returned %#lx.\n", hr);
1282 hr = IMediaObject_GetOutputType(media_object, 0, count, NULL);
1283 ok(hr == DMO_E_NO_MORE_ITEMS || broken(hr == S_OK), "GetOutputType returned %#lx.\n", hr);
1284 hr = IMediaObject_GetOutputType(media_object, 0, 0xdeadbeef, NULL);
1285 ok(hr == DMO_E_NO_MORE_ITEMS || broken(hr == S_OK), "GetOutputType returned %#lx.\n", hr);
1286 hr = IMediaObject_GetOutputType(media_object, 0, count - 1, NULL);
1287 ok(hr == S_OK, "GetOutputType returned %#lx.\n", hr);
1288 hr = IMediaObject_GetOutputType(media_object, 0, count - 1, &media_type);
1289 ok(hr == S_OK, "GetOutputType returned %#lx.\n", hr);
1290 if (hr == S_OK)
1291 MoFreeMediaType(&media_type);
1293 i = -1;
1294 while (SUCCEEDED(hr = IMediaObject_GetOutputType(media_object, 0, ++i, &media_type)))
1296 winetest_push_context("out %lu", i);
1297 check_dmo_media_type(&media_type, &expected_type[i]);
1298 MoFreeMediaType(&media_type);
1299 winetest_pop_context();
1302 ok(hr == DMO_E_NO_MORE_ITEMS, "GetOutputType returned %#lx.\n", hr);
1303 ok(i == count, "%lu types.\n", i);
1306 static void check_dmo_set_input_type(IMediaObject *media_object, const GUID *subtype)
1308 DMO_MEDIA_TYPE bad_media_type, *good_media_type;
1309 VIDEOINFOHEADER *header;
1310 char buffer[1024];
1311 DWORD i, flag;
1312 HRESULT hr;
1314 const DWORD flags[] = {0, 0x4, DMO_SET_TYPEF_CLEAR, DMO_SET_TYPEF_TEST_ONLY, DMO_SET_TYPEF_TEST_ONLY | 0x4};
1316 memset(&bad_media_type, 0, sizeof(bad_media_type));
1317 good_media_type = (DMO_MEDIA_TYPE *)buffer;
1318 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1319 header = (VIDEOINFOHEADER *)(good_media_type + 1);
1321 /* Test invalid stream index. */
1322 for (i = 0; i < ARRAY_SIZE(flags); ++i)
1324 flag = flags[i];
1325 hr = IMediaObject_SetInputType(media_object, 1, NULL, flag);
1326 ok(hr == DMO_E_INVALIDSTREAMINDEX, "SetInputType returned %#lx for flag %#lx.", hr, flag);
1327 hr = IMediaObject_SetInputType(media_object, 1, &bad_media_type, flag);
1328 ok(hr == DMO_E_INVALIDSTREAMINDEX, "SetInputType returned %#lx for flag %#lx.", hr, flag);
1329 hr = IMediaObject_SetInputType(media_object, 1, good_media_type, flag);
1330 ok(hr == DMO_E_INVALIDSTREAMINDEX, "SetInputType returned %#lx for flag %#lx.", hr, flag);
1333 /* Test unaccepted type. */
1334 for (i = 0; i < ARRAY_SIZE(flags); ++i)
1336 flag = flags[i];
1337 if (!(flag & DMO_SET_TYPEF_CLEAR))
1339 hr = IMediaObject_SetInputType(media_object, 0, NULL, flag);
1340 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx for flag %#lx.", hr, flag);
1342 hr = IMediaObject_SetInputType(media_object, 0, &bad_media_type, flag);
1343 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx for flag %#lx.", hr, flag);
1346 /* Test clearing the type. */
1347 for (i = 0; i < ARRAY_SIZE(flags); ++i)
1349 flag = DMO_SET_TYPEF_CLEAR | flags[i];
1350 hr = IMediaObject_SetInputType(media_object, 0, NULL, flag);
1351 ok(hr == S_OK, "SetInputType returned %#lx for flag %#lx.", hr, flag);
1354 /* Test accepted type. */
1355 for (i = 0; i < ARRAY_SIZE(flags); ++i)
1357 flag = flags[i];
1358 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, flag);
1359 ok(hr == S_OK, "SetInputType returned %#lx for flag %#lx.", hr, flag);
1362 /* Test unconsidered header member.*/
1363 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1364 header->dwBitRate = 0xdeadbeef;
1365 header->dwBitErrorRate = 0xdeadbeef;
1366 header->AvgTimePerFrame = 0xdeadbeef;
1367 header->bmiHeader.biPlanes = 0xdead;
1368 header->bmiHeader.biBitCount = 0xdead;
1369 header->bmiHeader.biSizeImage = 0xdeadbeef;
1370 header->bmiHeader.biXPelsPerMeter = 0xdead;
1371 header->bmiHeader.biYPelsPerMeter = 0xdead;
1372 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, 0);
1373 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
1375 /* Test invalid major type. */
1376 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1377 good_media_type->majortype = MFMediaType_Default;
1378 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1379 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1381 /* Test invalid subtype. */
1382 init_dmo_media_type_video(good_media_type, &MEDIASUBTYPE_None, 16, 16);
1383 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1384 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1386 /* Test invalid format type. */
1387 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1388 good_media_type->formattype = FORMAT_None;
1389 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1390 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1392 /* Test invalid format size. */
1393 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1394 good_media_type->cbFormat = 1;
1395 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1396 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1398 /* Test NULL format pointer. */
1399 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1400 good_media_type->pbFormat = NULL;
1401 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1402 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1404 /* Test video header struct size. */
1405 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1406 header->bmiHeader.biSize = 0;
1407 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1408 todo_wine
1409 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1410 header->bmiHeader.biSize = 1;
1411 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1412 todo_wine
1413 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1414 header->bmiHeader.biSize = 0xdeadbeef;
1415 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1416 todo_wine
1417 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1419 /* Test width. */
1420 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1421 header->bmiHeader.biWidth = 0;
1422 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1423 todo_wine
1424 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1425 header->bmiHeader.biWidth = -1;
1426 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1427 todo_wine
1428 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1429 header->bmiHeader.biWidth = 4096 + 1;
1430 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1431 todo_wine
1432 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1433 header->bmiHeader.biWidth = 4096;
1434 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1435 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
1437 /* Test height. */
1438 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1439 header->bmiHeader.biHeight = 0;
1440 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1441 todo_wine
1442 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1443 header->bmiHeader.biHeight = 4096 + 1;
1444 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1445 todo_wine
1446 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1447 header->bmiHeader.biHeight = 4096;
1448 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1449 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
1450 header->bmiHeader.biHeight = -4096;
1451 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1452 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
1454 /* Test compression. */
1455 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1456 header->bmiHeader.biCompression = 0;
1457 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1458 todo_wine
1459 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1460 header->bmiHeader.biCompression = 1;
1461 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1462 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
1463 header->bmiHeader.biCompression = 2;
1464 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1465 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
1466 header->bmiHeader.biCompression = 0xdeadbeef;
1467 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1468 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
1471 static void check_dmo_set_output_type(IMediaObject *media_object, const GUID *subtype)
1473 DMO_MEDIA_TYPE bad_media_type, *good_media_type;
1474 char buffer[1024];
1475 DWORD i, flag;
1476 HRESULT hr;
1478 const DWORD flags[] = {0, 0x4, DMO_SET_TYPEF_CLEAR, DMO_SET_TYPEF_TEST_ONLY, DMO_SET_TYPEF_TEST_ONLY | 0x4};
1480 memset(&bad_media_type, 0, sizeof(bad_media_type));
1481 good_media_type = (DMO_MEDIA_TYPE *)buffer;
1482 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1484 /* Test invalid stream index. */
1485 for (i = 0; i < ARRAY_SIZE(flags); ++i)
1487 flag = flags[i];
1488 hr = IMediaObject_SetOutputType(media_object, 1, NULL, flag);
1489 ok(hr == DMO_E_INVALIDSTREAMINDEX, "SetOutputType returned %#lx for flag %#lx.\n", hr, flag);
1490 hr = IMediaObject_SetOutputType(media_object, 1, &bad_media_type, flag);
1491 ok(hr == DMO_E_INVALIDSTREAMINDEX, "SetOutputType returned %#lx for flag %#lx.\n", hr, flag);
1492 hr = IMediaObject_SetOutputType(media_object, 1, good_media_type, flag);
1493 ok(hr == DMO_E_INVALIDSTREAMINDEX, "SetOutputType returned %#lx for flag %#lx.\n", hr, flag);
1496 /* Test unaccepted type. */
1497 for (i = 0; i < ARRAY_SIZE(flags); ++i)
1499 flag = flags[i];
1500 if (!(flag & DMO_SET_TYPEF_CLEAR))
1502 hr = IMediaObject_SetOutputType(media_object, 0, NULL, flag);
1503 ok(hr == E_POINTER, "SetOutputType returned %#lx for flag %#lx.\n", hr, flag);
1505 hr = IMediaObject_SetOutputType(media_object, 0, &bad_media_type, flag);
1506 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetOutputType returned %#lx for flag %#lx.\n", hr, flag);
1509 /* Test clearing the type. */
1510 for (i = 0; i < ARRAY_SIZE(flags); ++i)
1512 flag = DMO_SET_TYPEF_CLEAR | flags[i];
1513 hr = IMediaObject_SetOutputType(media_object, 0, NULL, flag);
1514 ok(hr == S_OK, "SetOutputType returned %#lx for flag %#lx.\n", hr, flag);
1517 /* Test accepted type. */
1518 for (i = 0; i < ARRAY_SIZE(flags); ++i)
1520 flag = flags[i];
1521 hr = IMediaObject_SetOutputType(media_object, 0, good_media_type, flag);
1522 ok(hr == S_OK, "SetOutputType returned %#lx for flag %#lx.\n", hr, flag);
1527 static HRESULT WINAPI test_unk_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
1529 if (IsEqualIID(riid, &IID_IUnknown))
1531 *obj = iface;
1532 IUnknown_AddRef(iface);
1533 return S_OK;
1536 *obj = NULL;
1537 return E_NOINTERFACE;
1540 static ULONG WINAPI test_unk_AddRef(IUnknown *iface)
1542 return 2;
1545 static ULONG WINAPI test_unk_Release(IUnknown *iface)
1547 return 1;
1550 static const IUnknownVtbl test_unk_vtbl =
1552 test_unk_QueryInterface,
1553 test_unk_AddRef,
1554 test_unk_Release,
1557 static BOOL is_supported_video_type(const GUID *guid)
1559 return IsEqualGUID(guid, &MFVideoFormat_L8)
1560 || IsEqualGUID(guid, &MFVideoFormat_L16)
1561 || IsEqualGUID(guid, &MFVideoFormat_D16)
1562 || IsEqualGUID(guid, &MFVideoFormat_IYUV)
1563 || IsEqualGUID(guid, &MFVideoFormat_YV12)
1564 || IsEqualGUID(guid, &MFVideoFormat_NV12)
1565 || IsEqualGUID(guid, &MFVideoFormat_NV21)
1566 || IsEqualGUID(guid, &MFVideoFormat_420O)
1567 || IsEqualGUID(guid, &MFVideoFormat_P010)
1568 || IsEqualGUID(guid, &MFVideoFormat_P016)
1569 || IsEqualGUID(guid, &MFVideoFormat_UYVY)
1570 || IsEqualGUID(guid, &MFVideoFormat_YUY2)
1571 || IsEqualGUID(guid, &MFVideoFormat_P208)
1572 || IsEqualGUID(guid, &MFVideoFormat_NV11)
1573 || IsEqualGUID(guid, &MFVideoFormat_AYUV)
1574 || IsEqualGUID(guid, &MFVideoFormat_ARGB32)
1575 || IsEqualGUID(guid, &MFVideoFormat_RGB32)
1576 || IsEqualGUID(guid, &MFVideoFormat_A2R10G10B10)
1577 || IsEqualGUID(guid, &MFVideoFormat_A16B16G16R16F)
1578 || IsEqualGUID(guid, &MFVideoFormat_RGB24)
1579 || IsEqualGUID(guid, &MFVideoFormat_I420)
1580 || IsEqualGUID(guid, &MFVideoFormat_YVYU)
1581 || IsEqualGUID(guid, &MFVideoFormat_RGB555)
1582 || IsEqualGUID(guid, &MFVideoFormat_RGB565)
1583 || IsEqualGUID(guid, &MFVideoFormat_RGB8)
1584 || IsEqualGUID(guid, &MFVideoFormat_Y216)
1585 || IsEqualGUID(guid, &MFVideoFormat_v410)
1586 || IsEqualGUID(guid, &MFVideoFormat_Y41P)
1587 || IsEqualGUID(guid, &MFVideoFormat_Y41T)
1588 || IsEqualGUID(guid, &MFVideoFormat_Y42T)
1589 || IsEqualGUID(guid, &MFVideoFormat_ABGR32);
1592 static BOOL is_sample_copier_available_type(IMFMediaType *type)
1594 GUID major = { 0 };
1595 UINT32 count;
1596 HRESULT hr;
1598 hr = IMFMediaType_GetMajorType(type, &major);
1599 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
1601 hr = IMFMediaType_GetCount(type, &count);
1602 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
1603 ok(count == 1, "Unexpected attribute count %u.\n", count);
1605 return IsEqualGUID(&major, &MFMediaType_Video) || IsEqualGUID(&major, &MFMediaType_Audio);
1608 static void test_sample_copier(void)
1610 static const struct attribute_desc expect_transform_attributes[] =
1612 ATTR_UINT32(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, 1),
1613 {0},
1615 const MFT_OUTPUT_STREAM_INFO initial_output_info = {0}, output_info = {.cbSize = 16 * 16};
1616 const MFT_INPUT_STREAM_INFO initial_input_info = {0}, input_info = {.cbSize = 16 * 16};
1617 IMFMediaType *mediatype, *mediatype2;
1618 IMFSample *sample, *client_sample;
1619 IMFMediaBuffer *media_buffer;
1620 MFT_INPUT_STREAM_INFO info;
1621 DWORD flags, output_status;
1622 IMFTransform *copier;
1623 HRESULT hr;
1624 LONG ref;
1626 if (!pMFCreateSampleCopierMFT)
1628 win_skip("MFCreateSampleCopierMFT() is not available.\n");
1629 return;
1632 winetest_push_context("copier");
1634 hr = pMFCreateSampleCopierMFT(&copier);
1635 ok(hr == S_OK, "Failed to create sample copier, hr %#lx.\n", hr);
1637 check_interface(copier, &IID_IMFTransform, TRUE);
1638 check_interface(copier, &IID_IMediaObject, FALSE);
1639 check_interface(copier, &IID_IPropertyStore, FALSE);
1640 check_interface(copier, &IID_IPropertyBag, FALSE);
1642 check_mft_optional_methods(copier, 1);
1643 check_mft_get_attributes(copier, expect_transform_attributes, FALSE);
1645 /* Available types. */
1646 hr = IMFTransform_GetInputAvailableType(copier, 0, 0, &mediatype);
1647 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1648 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
1649 IMFMediaType_Release(mediatype);
1651 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype);
1652 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1653 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
1654 IMFMediaType_Release(mediatype);
1656 hr = IMFTransform_GetInputAvailableType(copier, 0, 2, &mediatype);
1657 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
1659 hr = IMFTransform_GetInputAvailableType(copier, 1, 0, &mediatype);
1660 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
1662 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype);
1663 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
1665 hr = IMFTransform_GetOutputAvailableType(copier, 1, 0, &mediatype);
1666 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
1668 check_mft_get_input_current_type(copier, NULL);
1669 check_mft_get_output_current_type(copier, NULL);
1671 hr = MFCreateSample(&sample);
1672 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
1674 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
1675 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
1677 hr = MFCreateMediaType(&mediatype);
1678 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
1680 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
1681 ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr);
1683 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
1684 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1686 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8);
1687 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1689 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
1690 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1692 check_mft_get_input_stream_info(copier, S_OK, &initial_input_info);
1693 check_mft_get_output_stream_info(copier, S_OK, &initial_output_info);
1695 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
1696 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
1698 memset(&info, 0xcd, sizeof(info));
1699 hr = IMFTransform_GetInputStreamInfo(copier, 0, &info);
1700 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
1701 check_member(info, initial_input_info, "%I64d", hnsMaxLatency);
1702 check_member(info, initial_input_info, "%#lx", dwFlags);
1703 todo_wine
1704 check_member(info, initial_input_info, "%#lx", cbSize);
1705 check_member(info, initial_input_info, "%#lx", cbMaxLookahead);
1706 check_member(info, initial_input_info, "%#lx", cbAlignment);
1707 check_mft_get_output_stream_info(copier, S_OK, &output_info);
1709 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
1710 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
1711 IMFMediaType_Release(mediatype2);
1713 check_mft_get_input_current_type(copier, NULL);
1715 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
1716 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
1718 /* Setting input type resets output type. */
1719 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
1720 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1721 IMFMediaType_Release(mediatype2);
1723 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
1724 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
1726 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
1727 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
1729 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype2);
1730 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1731 ok(is_sample_copier_available_type(mediatype2), "Unexpected type.\n");
1732 IMFMediaType_Release(mediatype2);
1734 check_mft_get_input_stream_info(copier, S_OK, &input_info);
1735 check_mft_get_output_stream_info(copier, S_OK, &output_info);
1737 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype2);
1738 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1739 hr = IMFMediaType_IsEqual(mediatype2, mediatype, &flags);
1740 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1741 IMFMediaType_Release(mediatype2);
1743 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
1744 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
1745 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected flags %#lx.\n", flags);
1747 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2);
1748 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
1749 IMFMediaType_Release(mediatype2);
1751 hr = IMFTransform_GetOutputStatus(copier, &flags);
1752 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
1754 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
1755 ok(hr == S_OK, "Failed to set output type, hr %#lx.\n", hr);
1757 hr = IMFTransform_GetOutputStatus(copier, &flags);
1758 ok(hr == S_OK, "Failed to get output status, hr %#lx.\n", hr);
1759 ok(!flags, "Unexpected flags %#lx.\n", flags);
1761 /* Pushing samples. */
1762 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
1763 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
1765 hr = IMFSample_AddBuffer(sample, media_buffer);
1766 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
1767 IMFMediaBuffer_Release(media_buffer);
1769 EXPECT_REF(sample, 1);
1770 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
1771 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
1772 EXPECT_REF(sample, 2);
1774 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
1775 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
1776 ok(!flags, "Unexpected flags %#lx.\n", flags);
1778 hr = IMFTransform_GetOutputStatus(copier, &flags);
1779 ok(hr == S_OK, "Failed to get output status, hr %#lx.\n", hr);
1780 ok(flags == MFT_OUTPUT_STATUS_SAMPLE_READY, "Unexpected flags %#lx.\n", flags);
1782 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
1783 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#lx.\n", hr);
1785 check_mft_get_input_stream_info(copier, S_OK, &input_info);
1786 check_mft_get_output_stream_info(copier, S_OK, &output_info);
1788 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
1789 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
1791 hr = MFCreateSample(&client_sample);
1792 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
1794 hr = IMFSample_AddBuffer(client_sample, media_buffer);
1795 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
1796 IMFMediaBuffer_Release(media_buffer);
1798 hr = check_mft_process_output(copier, client_sample, &output_status);
1799 ok(hr == S_OK, "Failed to get output, hr %#lx.\n", hr);
1800 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
1801 EXPECT_REF(sample, 1);
1803 hr = check_mft_process_output(copier, client_sample, &output_status);
1804 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Failed to get output, hr %#lx.\n", hr);
1805 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
1807 /* Flushing. */
1808 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
1809 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
1810 EXPECT_REF(sample, 2);
1812 hr = IMFTransform_ProcessMessage(copier, MFT_MESSAGE_COMMAND_FLUSH, 0);
1813 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
1815 ref = IMFSample_Release(sample);
1816 ok(ref == 0, "Release returned %ld\n", ref);
1817 ref = IMFSample_Release(client_sample);
1818 ok(ref == 0, "Release returned %ld\n", ref);
1820 ref = IMFTransform_Release(copier);
1821 ok(ref == 0, "Release returned %ld\n", ref);
1822 ref = IMFMediaType_Release(mediatype);
1823 ok(ref == 0, "Release returned %ld\n", ref);
1825 winetest_pop_context();
1828 struct sample_metadata
1830 unsigned int flags;
1831 LONGLONG duration;
1832 LONGLONG time;
1835 static void sample_copier_process(IMFTransform *copier, IMFMediaBuffer *input_buffer,
1836 IMFMediaBuffer *output_buffer, const struct sample_metadata *md)
1838 static const struct sample_metadata zero_md = { 0, ~0u, ~0u };
1839 IMFSample *input_sample, *output_sample;
1840 DWORD flags, output_status;
1841 LONGLONG time;
1842 HRESULT hr;
1843 LONG ref;
1845 hr = MFCreateSample(&input_sample);
1846 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
1848 if (md)
1850 hr = IMFSample_SetSampleFlags(input_sample, md->flags);
1851 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1853 hr = IMFSample_SetSampleTime(input_sample, md->time);
1854 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1856 hr = IMFSample_SetSampleDuration(input_sample, md->duration);
1857 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1860 hr = MFCreateSample(&output_sample);
1861 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
1863 hr = IMFSample_SetSampleFlags(output_sample, ~0u);
1864 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1866 hr = IMFSample_SetSampleTime(output_sample, ~0u);
1867 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1869 hr = IMFSample_SetSampleDuration(output_sample, ~0u);
1870 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1872 hr = IMFSample_AddBuffer(input_sample, input_buffer);
1873 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1875 hr = IMFSample_AddBuffer(output_sample, output_buffer);
1876 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1878 hr = IMFTransform_ProcessInput(copier, 0, input_sample, 0);
1879 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
1881 hr = check_mft_process_output(copier, output_sample, &output_status);
1882 ok(hr == S_OK, "Failed to get output, hr %#lx.\n", hr);
1883 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
1885 if (!md) md = &zero_md;
1887 hr = IMFSample_GetSampleFlags(output_sample, &flags);
1888 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1889 ok(md->flags == flags, "Unexpected flags.\n");
1890 hr = IMFSample_GetSampleTime(output_sample, &time);
1891 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1892 ok(md->time == time, "Unexpected time.\n");
1893 hr = IMFSample_GetSampleDuration(output_sample, &time);
1894 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1895 ok(md->duration == time, "Unexpected duration.\n");
1897 ref = IMFSample_Release(input_sample);
1898 ok(ref == 0, "Release returned %ld\n", ref);
1899 ref = IMFSample_Release(output_sample);
1900 ok(ref == 0, "Release returned %ld\n", ref);
1903 static void test_sample_copier_output_processing(void)
1905 IMFMediaBuffer *input_buffer, *output_buffer;
1906 MFT_OUTPUT_STREAM_INFO output_info;
1907 struct sample_metadata md;
1908 IMFMediaType *mediatype;
1909 IMFTransform *copier;
1910 DWORD max_length;
1911 HRESULT hr;
1912 BYTE *ptr;
1913 LONG ref;
1915 if (!pMFCreateSampleCopierMFT)
1916 return;
1918 hr = pMFCreateSampleCopierMFT(&copier);
1919 ok(hr == S_OK, "Failed to create sample copier, hr %#lx.\n", hr);
1921 /* Configure for 16 x 16 of D3DFMT_X8R8G8B8. */
1922 hr = MFCreateMediaType(&mediatype);
1923 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
1925 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
1926 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1928 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
1929 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1931 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
1932 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1934 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
1935 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
1937 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
1938 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
1940 /* Source and destination are linear buffers, destination is twice as large. */
1941 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
1942 ok(hr == S_OK, "Failed to get output info, hr %#lx.\n", hr);
1944 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &output_buffer);
1945 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
1947 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
1948 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1949 memset(ptr, 0xcc, max_length);
1950 hr = IMFMediaBuffer_Unlock(output_buffer);
1951 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1953 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &input_buffer);
1954 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
1956 hr = IMFMediaBuffer_Lock(input_buffer, &ptr, &max_length, NULL);
1957 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1958 memset(ptr, 0xaa, max_length);
1959 hr = IMFMediaBuffer_Unlock(input_buffer);
1960 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1961 hr = IMFMediaBuffer_SetCurrentLength(input_buffer, 4);
1962 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1964 sample_copier_process(copier, input_buffer, output_buffer, NULL);
1966 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
1967 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1968 ok(ptr[0] == 0xaa && ptr[4] == 0xcc, "Unexpected buffer contents.\n");
1970 hr = IMFMediaBuffer_Unlock(output_buffer);
1971 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1973 md.flags = 123;
1974 md.time = 10;
1975 md.duration = 2;
1976 sample_copier_process(copier, input_buffer, output_buffer, &md);
1978 ref = IMFMediaBuffer_Release(input_buffer);
1979 ok(ref == 0, "Release returned %ld\n", ref);
1980 ref = IMFMediaBuffer_Release(output_buffer);
1981 ok(ref == 0, "Release returned %ld\n", ref);
1983 ref = IMFTransform_Release(copier);
1984 ok(ref == 0, "Release returned %ld\n", ref);
1985 ref = IMFMediaType_Release(mediatype);
1986 ok(ref == 0, "Release returned %ld\n", ref);
1989 static IMFSample *create_sample(const BYTE *data, ULONG size)
1991 IMFMediaBuffer *media_buffer;
1992 IMFSample *sample;
1993 DWORD length;
1994 BYTE *buffer;
1995 HRESULT hr;
1996 ULONG ret;
1998 hr = MFCreateSample(&sample);
1999 ok(hr == S_OK, "MFCreateSample returned %#lx\n", hr);
2000 hr = MFCreateMemoryBuffer(size, &media_buffer);
2001 ok(hr == S_OK, "MFCreateMemoryBuffer returned %#lx\n", hr);
2002 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
2003 ok(hr == S_OK, "Lock returned %#lx\n", hr);
2004 ok(length == 0, "got length %lu\n", length);
2005 if (!data) memset(buffer, 0xcd, size);
2006 else memcpy(buffer, data, size);
2007 hr = IMFMediaBuffer_Unlock(media_buffer);
2008 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
2009 hr = IMFMediaBuffer_SetCurrentLength(media_buffer, data ? size : 0);
2010 ok(hr == S_OK, "SetCurrentLength returned %#lx\n", hr);
2011 hr = IMFSample_AddBuffer(sample, media_buffer);
2012 ok(hr == S_OK, "AddBuffer returned %#lx\n", hr);
2013 ret = IMFMediaBuffer_Release(media_buffer);
2014 ok(ret == 1, "Release returned %lu\n", ret);
2016 return sample;
2019 static const BYTE aac_codec_data[14] = {0x00,0x00,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x08};
2021 static void test_aac_encoder(void)
2023 const GUID *const class_id = &CLSID_AACMFTEncoder;
2024 const struct transform_info expect_mft_info =
2026 .name = L"Microsoft AAC Audio Encoder MFT",
2027 .major_type = &MFMediaType_Audio,
2028 .inputs =
2030 {.subtype = &MFAudioFormat_PCM},
2032 .outputs =
2034 {.subtype = &MFAudioFormat_AAC},
2038 static const struct attribute_desc input_type_desc[] =
2040 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2041 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM, .required = TRUE),
2042 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1, .required = TRUE),
2043 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
2044 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .required = TRUE),
2045 {0},
2047 const struct attribute_desc output_type_desc[] =
2049 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2050 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC, .required = TRUE),
2051 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1, .required = TRUE),
2052 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
2053 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .required = TRUE),
2054 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 12000, .required = TRUE),
2055 {0},
2058 static const struct attribute_desc expect_input_type_desc[] =
2060 ATTR_GUID(MF_MT_AM_FORMAT_TYPE, FORMAT_WaveFormatEx),
2061 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2062 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2063 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
2064 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2065 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2),
2066 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2067 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 * 2),
2068 ATTR_UINT32(MF_MT_AVG_BITRATE, 44100 * 2 * 8),
2069 ATTR_UINT32(MF_MT_COMPRESSED, 0),
2070 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2071 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2072 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2073 {0},
2075 const struct attribute_desc expect_output_type_desc[] =
2077 ATTR_GUID(MF_MT_AM_FORMAT_TYPE, FORMAT_WaveFormatEx),
2078 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2079 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC),
2080 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
2081 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2082 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2083 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2084 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 12000),
2085 ATTR_UINT32(MF_MT_AVG_BITRATE, 96000),
2086 ATTR_UINT32(MF_MT_COMPRESSED, 1),
2087 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 0),
2088 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2089 ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 41),
2090 ATTR_UINT32(MF_MT_AAC_PAYLOAD_TYPE, 0),
2091 ATTR_BLOB(MF_MT_USER_DATA, aac_codec_data, sizeof(aac_codec_data)),
2092 {0},
2094 const MFT_OUTPUT_STREAM_INFO initial_output_info = {0}, output_info = {.cbSize = 0x600};
2095 const MFT_INPUT_STREAM_INFO input_info = {0};
2097 const struct buffer_desc output_buffer_desc[] =
2099 {.length = -1 /* variable */},
2101 const struct attribute_desc output_sample_attributes[] =
2103 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
2104 {0},
2106 const struct sample_desc output_sample_desc[] =
2109 .repeat_count = 88,
2110 .attributes = output_sample_attributes,
2111 .sample_time = 0, .sample_duration = 113823,
2112 .buffer_count = 1, .buffers = output_buffer_desc,
2116 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_AAC};
2117 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_PCM};
2118 IMFSample *input_sample, *output_sample;
2119 IMFCollection *output_samples;
2120 ULONG i, ret, audio_data_len;
2121 DWORD length, output_status;
2122 IMFTransform *transform;
2123 const BYTE *audio_data;
2124 HRESULT hr;
2125 LONG ref;
2127 hr = CoInitialize(NULL);
2128 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
2130 winetest_push_context("aacenc");
2132 if (!check_mft_enum(MFT_CATEGORY_AUDIO_ENCODER, &input_type, &output_type, class_id))
2133 goto failed;
2134 check_mft_get_info(class_id, &expect_mft_info);
2136 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
2137 &IID_IMFTransform, (void **)&transform)))
2138 goto failed;
2140 check_interface(transform, &IID_IMFTransform, TRUE);
2141 check_interface(transform, &IID_IMediaObject, FALSE);
2142 check_interface(transform, &IID_IPropertyStore, FALSE);
2143 check_interface(transform, &IID_IPropertyBag, FALSE);
2145 check_mft_optional_methods(transform, 1);
2146 check_mft_get_attributes(transform, NULL, FALSE);
2147 check_mft_get_input_stream_info(transform, S_OK, &input_info);
2148 check_mft_get_output_stream_info(transform, S_OK, &initial_output_info);
2150 check_mft_set_output_type_required(transform, output_type_desc);
2151 check_mft_set_output_type(transform, output_type_desc, S_OK);
2152 check_mft_get_output_current_type(transform, expect_output_type_desc);
2154 check_mft_set_input_type_required(transform, input_type_desc);
2155 check_mft_set_input_type(transform, input_type_desc);
2156 check_mft_get_input_current_type(transform, expect_input_type_desc);
2158 check_mft_get_input_stream_info(transform, S_OK, &input_info);
2159 check_mft_get_output_stream_info(transform, S_OK, &output_info);
2161 if (!has_video_processor)
2163 win_skip("Skipping AAC encoder tests on Win7\n");
2164 goto done;
2167 load_resource(L"audiodata.bin", &audio_data, &audio_data_len);
2168 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
2170 input_sample = create_sample(audio_data, audio_data_len);
2171 hr = IMFSample_SetSampleTime(input_sample, 0);
2172 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
2173 hr = IMFSample_SetSampleDuration(input_sample, 10000000);
2174 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
2175 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2176 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2177 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
2178 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
2179 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2180 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2181 ref = IMFSample_Release(input_sample);
2182 ok(ref <= 1, "Release returned %ld\n", ref);
2184 hr = MFCreateCollection(&output_samples);
2185 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
2187 output_sample = create_sample(NULL, output_info.cbSize);
2188 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
2190 winetest_push_context("%lu", i);
2191 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
2192 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
2193 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
2194 ref = IMFSample_Release(output_sample);
2195 ok(ref == 1, "Release returned %ld\n", ref);
2196 output_sample = create_sample(NULL, output_info.cbSize);
2197 winetest_pop_context();
2199 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2200 ret = IMFSample_Release(output_sample);
2201 ok(ret == 0, "Release returned %lu\n", ret);
2202 ok(i == 88, "got %lu output samples\n", i);
2204 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"aacencdata.bin");
2205 ok(ret == 0, "got %lu%% diff\n", ret);
2206 IMFCollection_Release(output_samples);
2208 output_sample = create_sample(NULL, output_info.cbSize);
2209 hr = check_mft_process_output(transform, output_sample, &output_status);
2210 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2211 hr = IMFSample_GetTotalLength(output_sample, &length);
2212 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
2213 ok(length == 0, "got length %lu\n", length);
2214 ret = IMFSample_Release(output_sample);
2215 ok(ret == 0, "Release returned %lu\n", ret);
2217 done:
2218 ret = IMFTransform_Release(transform);
2219 ok(ret == 0, "Release returned %lu\n", ret);
2221 failed:
2222 winetest_pop_context();
2223 CoUninitialize();
2226 static void test_aac_decoder(void)
2228 const GUID *const class_id = &CLSID_MSAACDecMFT;
2229 const struct transform_info expect_mft_info =
2231 .name = L"Microsoft AAC Audio Decoder MFT",
2232 .major_type = &MFMediaType_Audio,
2233 .inputs =
2235 {.subtype = &MFAudioFormat_AAC},
2236 {.subtype = &MFAudioFormat_RAW_AAC1},
2237 {.subtype = &MFAudioFormat_ADTS, .broken = TRUE /* <= w8 */},
2239 .outputs =
2241 {.subtype = &MFAudioFormat_Float},
2242 {.subtype = &MFAudioFormat_PCM},
2246 static const struct attribute_desc expect_input_attributes[] =
2248 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2249 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2250 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
2251 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 6),
2252 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 24),
2253 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
2254 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 1152000),
2255 {0},
2257 static const media_type_desc expect_available_inputs[] =
2260 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC),
2261 ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 0),
2262 ATTR_UINT32(MF_MT_AAC_PAYLOAD_TYPE, 0),
2263 /* MF_MT_USER_DATA with some AAC codec data */
2266 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_RAW_AAC1),
2269 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC),
2270 ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 0),
2271 ATTR_UINT32(MF_MT_AAC_PAYLOAD_TYPE, 1),
2272 /* MF_MT_USER_DATA with some AAC codec data */
2275 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC),
2276 ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 0),
2277 ATTR_UINT32(MF_MT_AAC_PAYLOAD_TYPE, 3),
2278 /* MF_MT_USER_DATA with some AAC codec data */
2281 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_ADTS),
2284 static const struct attribute_desc expect_output_attributes[] =
2286 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2287 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2288 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2289 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2290 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2291 {0},
2293 static const media_type_desc expect_available_outputs[] =
2296 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2297 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
2298 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
2299 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
2300 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4 * 44100),
2303 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2304 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2305 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
2306 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2),
2307 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * 44100),
2310 const struct attribute_desc expect_transform_attributes[] =
2312 ATTR_UINT32(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, !has_video_processor /* 1 on W7 */, .todo = TRUE),
2313 /* more AAC decoder specific attributes from CODECAPI */
2314 {0},
2316 const struct attribute_desc input_type_desc[] =
2318 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2319 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC, .required = TRUE),
2320 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .required = TRUE),
2321 ATTR_BLOB(MF_MT_USER_DATA, aac_codec_data, sizeof(aac_codec_data), .required = TRUE),
2322 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
2323 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2324 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 12000),
2325 ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 41),
2326 ATTR_UINT32(MF_MT_AAC_PAYLOAD_TYPE, 0),
2327 {0},
2329 static const struct attribute_desc output_type_desc[] =
2331 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2332 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM, .required = TRUE),
2333 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1, .required = TRUE),
2334 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
2335 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .required = TRUE),
2336 {0},
2338 const MFT_OUTPUT_STREAM_INFO output_info =
2340 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES,
2341 .cbSize = 0xc000,
2343 const MFT_INPUT_STREAM_INFO input_info =
2345 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
2346 MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE | MFT_INPUT_STREAM_HOLDS_BUFFERS,
2349 const struct buffer_desc output_buffer_desc[] =
2351 {.length = 0x800},
2353 const struct attribute_desc output_sample_attributes[] =
2355 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
2356 {0},
2358 const struct sample_desc output_sample_desc[] =
2361 .attributes = output_sample_attributes + (has_video_processor ? 0 : 1) /* MFSampleExtension_CleanPoint missing on Win7 */,
2362 .sample_time = 0, .sample_duration = 232200,
2363 .buffer_count = 1, .buffers = output_buffer_desc,
2367 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_Float};
2368 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_AAC};
2369 IMFSample *input_sample, *output_sample;
2370 ULONG i, ret, ref, aacenc_data_len;
2371 IMFCollection *output_samples;
2372 DWORD length, output_status;
2373 IMFMediaType *media_type;
2374 IMFTransform *transform;
2375 const BYTE *aacenc_data;
2376 HRESULT hr;
2378 hr = CoInitialize(NULL);
2379 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
2381 winetest_push_context("aacdec");
2383 if (!check_mft_enum(MFT_CATEGORY_AUDIO_DECODER, &input_type, &output_type, class_id))
2384 goto failed;
2385 check_mft_get_info(class_id, &expect_mft_info);
2387 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
2388 &IID_IMFTransform, (void **)&transform)))
2389 goto failed;
2391 check_interface(transform, &IID_IMFTransform, TRUE);
2392 check_interface(transform, &IID_IMediaObject, FALSE);
2393 check_interface(transform, &IID_IPropertyStore, FALSE);
2394 check_interface(transform, &IID_IPropertyBag, FALSE);
2396 check_mft_optional_methods(transform, 1);
2397 check_mft_get_attributes(transform, expect_transform_attributes, FALSE);
2398 check_mft_get_input_stream_info(transform, S_OK, &input_info);
2399 check_mft_get_output_stream_info(transform, S_OK, &output_info);
2401 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
2402 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
2404 i = -1;
2405 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
2407 winetest_push_context("in %lu", i);
2408 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
2409 check_media_type(media_type, expect_input_attributes, -1);
2410 check_media_type(media_type, expect_available_inputs[i], -1);
2411 ret = IMFMediaType_Release(media_type);
2412 ok(ret <= 1, "Release returned %lu\n", ret);
2413 winetest_pop_context();
2415 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
2416 ok(i == ARRAY_SIZE(expect_available_inputs)
2417 || broken(i == 2) /* w7 */ || broken(i == 4) /* w8 */,
2418 "%lu input media types\n", i);
2420 /* setting output media type first doesn't work */
2421 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
2422 check_mft_get_output_current_type(transform, NULL);
2424 check_mft_set_input_type_required(transform, input_type_desc);
2425 check_mft_set_input_type(transform, input_type_desc);
2426 check_mft_get_input_current_type(transform, input_type_desc);
2428 /* check new output media types */
2430 i = -1;
2431 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
2433 winetest_push_context("out %lu", i);
2434 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
2435 check_media_type(media_type, expect_output_attributes, -1);
2436 check_media_type(media_type, expect_available_outputs[i], -1);
2437 ret = IMFMediaType_Release(media_type);
2438 ok(ret <= 1, "Release returned %lu\n", ret);
2439 winetest_pop_context();
2441 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
2442 ok(i == ARRAY_SIZE(expect_available_outputs), "%lu input media types\n", i);
2444 check_mft_set_output_type_required(transform, output_type_desc);
2445 check_mft_set_output_type(transform, output_type_desc, S_OK);
2446 check_mft_get_output_current_type(transform, output_type_desc);
2448 check_mft_get_input_stream_info(transform, S_OK, &input_info);
2449 check_mft_get_output_stream_info(transform, S_OK, &output_info);
2451 load_resource(L"aacencdata.bin", &aacenc_data, &aacenc_data_len);
2452 ok(aacenc_data_len == 24861, "got length %lu\n", aacenc_data_len);
2454 input_sample = create_sample(aacenc_data + sizeof(DWORD), *(DWORD *)aacenc_data);
2455 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2456 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2457 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2458 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2460 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
2461 * IMFTransform_ProcessOutput needs a sample or returns MF_E_TRANSFORM_NEED_MORE_INPUT */
2463 hr = check_mft_process_output(transform, NULL, &output_status);
2464 ok(hr == E_INVALIDARG, "ProcessOutput returned %#lx\n", hr);
2465 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
2466 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2467 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2469 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
2470 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
2471 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2472 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2474 hr = MFCreateCollection(&output_samples);
2475 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
2477 output_sample = create_sample(NULL, output_info.cbSize);
2478 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
2480 winetest_push_context("%lu", i);
2481 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
2482 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
2483 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
2484 ref = IMFSample_Release(output_sample);
2485 ok(ref == 1, "Release returned %ld\n", ref);
2486 output_sample = create_sample(NULL, output_info.cbSize);
2487 winetest_pop_context();
2489 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2490 ok(output_status == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE, "got output[0].dwStatus %#lx\n", output_status);
2491 ret = IMFSample_Release(output_sample);
2492 ok(ret == 0, "Release returned %lu\n", ret);
2493 ok(i == 1, "got %lu output samples\n", i);
2495 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"aacdecdata.bin");
2496 todo_wine_if(ret <= 5)
2497 ok(ret == 0, "got %lu%% diff\n", ret);
2498 IMFCollection_Release(output_samples);
2500 output_sample = create_sample(NULL, output_info.cbSize);
2501 hr = check_mft_process_output(transform, output_sample, &output_status);
2502 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2503 ok(output_status == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE, "got output[0].dwStatus %#lx\n", output_status);
2504 hr = IMFSample_GetTotalLength(output_sample, &length);
2505 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
2506 ok(length == 0, "got length %lu\n", length);
2507 ret = IMFSample_Release(output_sample);
2508 ok(ret == 0, "Release returned %lu\n", ret);
2510 ret = IMFSample_Release(input_sample);
2511 ok(ret == 0, "Release returned %lu\n", ret);
2512 ret = IMFTransform_Release(transform);
2513 ok(ret == 0, "Release returned %lu\n", ret);
2515 failed:
2516 winetest_pop_context();
2517 CoUninitialize();
2520 static const BYTE wma_codec_data[10] = {0, 0x44, 0, 0, 0x17, 0, 0, 0, 0, 0};
2521 static const ULONG wmaenc_block_size = 1487;
2522 static const ULONG wmadec_block_size = 0x2000;
2524 static void test_wma_encoder(void)
2526 const GUID *const class_id = &CLSID_CWMAEncMediaObject;
2527 const struct transform_info expect_mft_info =
2529 .name = L"WMAudio Encoder MFT",
2530 .major_type = &MFMediaType_Audio,
2531 .inputs =
2533 {.subtype = &MFAudioFormat_PCM},
2534 {.subtype = &MFAudioFormat_Float},
2536 .outputs =
2538 {.subtype = &MFAudioFormat_WMAudioV8},
2539 {.subtype = &MFAudioFormat_WMAudioV9},
2540 {.subtype = &MFAudioFormat_WMAudio_Lossless},
2543 const struct transform_info expect_dmo_info =
2545 .name = L"WMAudio Encoder DMO",
2546 .major_type = &MEDIATYPE_Audio,
2547 .inputs =
2549 {.subtype = &MEDIASUBTYPE_PCM},
2551 .outputs =
2553 {.subtype = &MEDIASUBTYPE_WMAUDIO2},
2554 {.subtype = &MEDIASUBTYPE_WMAUDIO3},
2555 {.subtype = &MEDIASUBTYPE_WMAUDIO_LOSSLESS},
2559 static const struct attribute_desc input_type_desc[] =
2561 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2562 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float, .required = TRUE),
2563 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
2564 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32, .required = TRUE),
2565 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
2566 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2 * (32 / 8), .required = TRUE),
2567 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * (32 / 8) * 22050, .required = TRUE),
2568 {0},
2570 const struct attribute_desc output_type_desc[] =
2572 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2573 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8, .required = TRUE),
2574 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
2575 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
2576 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003, .required = TRUE),
2577 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size, .required = TRUE),
2578 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data), .required = TRUE),
2579 {0},
2581 static const struct attribute_desc expect_input_type_desc[] =
2583 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2584 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
2585 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
2586 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2587 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
2588 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
2589 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 22050 * 8),
2590 ATTR_UINT32(MF_MT_AUDIO_CHANNEL_MASK, 3),
2591 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2592 {0},
2594 const struct attribute_desc expect_output_type_desc[] =
2596 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2597 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
2598 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2599 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
2600 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003),
2601 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size),
2602 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)),
2603 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2604 {0},
2606 const MFT_OUTPUT_STREAM_INFO output_info =
2608 .cbSize = wmaenc_block_size,
2609 .cbAlignment = 1,
2611 const MFT_INPUT_STREAM_INFO input_info =
2613 .hnsMaxLatency = 19969161,
2614 .cbSize = 8,
2615 .cbAlignment = 1,
2618 const struct buffer_desc output_buffer_desc[] =
2620 {.length = wmaenc_block_size},
2622 const struct attribute_desc output_sample_attributes[] =
2624 ATTR_UINT32(mft_output_sample_incomplete, 1),
2625 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
2626 {0},
2628 const struct sample_desc output_sample_desc[] =
2631 .attributes = output_sample_attributes,
2632 .sample_time = 0, .sample_duration = 3250794,
2633 .buffer_count = 1, .buffers = output_buffer_desc,
2636 .attributes = output_sample_attributes,
2637 .sample_time = 3250794, .sample_duration = 3715193,
2638 .buffer_count = 1, .buffers = output_buffer_desc,
2641 .attributes = output_sample_attributes,
2642 .sample_time = 6965986, .sample_duration = 3366893,
2643 .buffer_count = 1, .buffers = output_buffer_desc,
2647 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8};
2648 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_Float};
2649 IMFSample *input_sample, *output_sample;
2650 IMFCollection *output_samples;
2651 DWORD length, output_status;
2652 IMFMediaType *media_type;
2653 IMFTransform *transform;
2654 const BYTE *audio_data;
2655 ULONG audio_data_len;
2656 ULONG i, ret;
2657 HRESULT hr;
2658 LONG ref;
2660 hr = CoInitialize(NULL);
2661 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
2663 winetest_push_context("wmaenc");
2665 if (!check_mft_enum(MFT_CATEGORY_AUDIO_ENCODER, &input_type, &output_type, class_id))
2666 goto failed;
2667 check_mft_get_info(class_id, &expect_mft_info);
2668 check_dmo_get_info(class_id, &expect_dmo_info);
2670 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
2671 &IID_IMFTransform, (void **)&transform)))
2672 goto failed;
2674 check_interface(transform, &IID_IMFTransform, TRUE);
2675 check_interface(transform, &IID_IMediaObject, TRUE);
2676 check_interface(transform, &IID_IPropertyStore, TRUE);
2677 check_interface(transform, &IID_IPropertyBag, TRUE);
2679 check_mft_optional_methods(transform, 1);
2680 check_mft_get_attributes(transform, NULL, FALSE);
2681 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
2682 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
2684 check_mft_set_input_type_required(transform, input_type_desc);
2686 hr = MFCreateMediaType(&media_type);
2687 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
2688 init_media_type(media_type, input_type_desc, -1);
2689 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
2690 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
2691 ret = IMFMediaType_Release(media_type);
2692 ok(ret == 0, "Release returned %lu\n", ret);
2694 check_mft_set_output_type_required(transform, output_type_desc);
2695 check_mft_set_output_type(transform, output_type_desc, S_OK);
2696 check_mft_get_output_current_type(transform, expect_output_type_desc);
2698 check_mft_set_input_type_required(transform, input_type_desc);
2699 check_mft_set_input_type(transform, input_type_desc);
2700 check_mft_get_input_current_type(transform, expect_input_type_desc);
2702 check_mft_get_input_stream_info(transform, S_OK, &input_info);
2703 check_mft_get_output_stream_info(transform, S_OK, &output_info);
2705 load_resource(L"audiodata.bin", &audio_data, &audio_data_len);
2706 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
2708 input_sample = create_sample(audio_data, audio_data_len);
2709 hr = IMFSample_SetSampleTime(input_sample, 0);
2710 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
2711 hr = IMFSample_SetSampleDuration(input_sample, 10000000);
2712 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
2713 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2714 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2715 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
2716 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
2717 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2718 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2719 ref = IMFSample_Release(input_sample);
2720 ok(ref <= 1, "Release returned %ld\n", ref);
2722 hr = MFCreateCollection(&output_samples);
2723 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
2725 output_sample = create_sample(NULL, output_info.cbSize);
2726 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
2728 winetest_push_context("%lu", i);
2729 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
2730 ok(output_status == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE, "got output[0].dwStatus %#lx\n", output_status);
2731 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
2732 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
2733 ref = IMFSample_Release(output_sample);
2734 ok(ref == 1, "Release returned %ld\n", ref);
2735 output_sample = create_sample(NULL, output_info.cbSize);
2736 winetest_pop_context();
2738 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2739 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
2740 ret = IMFSample_Release(output_sample);
2741 ok(ret == 0, "Release returned %lu\n", ret);
2742 ok(i == 3, "got %lu output samples\n", i);
2744 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"wmaencdata.bin");
2745 ok(ret == 0, "got %lu%% diff\n", ret);
2746 IMFCollection_Release(output_samples);
2748 output_sample = create_sample(NULL, output_info.cbSize);
2749 hr = check_mft_process_output(transform, output_sample, &output_status);
2750 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2751 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
2752 hr = IMFSample_GetTotalLength(output_sample, &length);
2753 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
2754 ok(length == 0, "got length %lu\n", length);
2755 ret = IMFSample_Release(output_sample);
2756 ok(ret == 0, "Release returned %lu\n", ret);
2758 ret = IMFTransform_Release(transform);
2759 ok(ret == 0, "Release returned %lu\n", ret);
2761 failed:
2762 winetest_pop_context();
2763 CoUninitialize();
2766 static void test_wma_decoder(void)
2768 const GUID *const class_id = &CLSID_CWMADecMediaObject;
2769 const struct transform_info expect_mft_info =
2771 .name = L"WMAudio Decoder MFT",
2772 .major_type = &MFMediaType_Audio,
2773 .inputs =
2775 {.subtype = &MEDIASUBTYPE_MSAUDIO1},
2776 {.subtype = &MFAudioFormat_WMAudioV8},
2777 {.subtype = &MFAudioFormat_WMAudioV9},
2778 {.subtype = &MFAudioFormat_WMAudio_Lossless},
2780 .outputs =
2782 {.subtype = &MFAudioFormat_PCM},
2783 {.subtype = &MFAudioFormat_Float},
2786 const struct transform_info expect_dmo_info =
2788 .name = L"WMAudio Decoder DMO",
2789 .major_type = &MEDIATYPE_Audio,
2790 .inputs =
2792 {.subtype = &MEDIASUBTYPE_MSAUDIO1},
2793 {.subtype = &MEDIASUBTYPE_WMAUDIO2},
2794 {.subtype = &MEDIASUBTYPE_WMAUDIO3},
2795 {.subtype = &MEDIASUBTYPE_WMAUDIO_LOSSLESS},
2797 .outputs =
2799 {.subtype = &MEDIASUBTYPE_PCM},
2800 {.subtype = &MEDIASUBTYPE_IEEE_FLOAT},
2804 static const media_type_desc expect_available_inputs[] =
2807 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2808 ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_MSAUDIO1),
2809 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2812 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2813 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
2814 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2817 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2818 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV9),
2819 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2822 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2823 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudio_Lossless),
2824 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2827 static const media_type_desc expect_available_outputs[] =
2830 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2831 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
2832 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
2833 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2834 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
2835 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
2836 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
2837 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2838 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2839 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2842 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2843 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2844 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
2845 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2846 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
2847 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
2848 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
2849 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2850 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2851 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2855 const struct attribute_desc input_type_desc[] =
2857 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2858 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8, .required = TRUE),
2859 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data), .required = TRUE),
2860 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size, .required = TRUE),
2861 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
2862 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
2863 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003), /* not required by SetInputType, but needed for the transform to work */
2864 {0},
2866 static const struct attribute_desc output_type_desc[] =
2868 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2869 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM, .required = TRUE),
2870 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
2871 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
2872 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
2873 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2 * (16 / 8), .required = TRUE),
2874 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * (16 / 8) * 22050, .required = TRUE),
2875 {0},
2877 const struct attribute_desc expect_input_type_desc[] =
2879 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2880 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
2881 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)),
2882 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size),
2883 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
2884 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2885 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003),
2886 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2887 {0},
2889 static const struct attribute_desc expect_output_type_desc[] =
2891 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2892 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2893 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 22050 * 4),
2894 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
2895 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2896 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
2897 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
2898 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2899 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2900 {0},
2902 const MFT_INPUT_STREAM_INFO input_info =
2904 .cbSize = wmaenc_block_size,
2905 .cbAlignment = 1,
2907 const MFT_OUTPUT_STREAM_INFO output_info =
2909 .cbSize = wmadec_block_size,
2910 .cbAlignment = 1,
2913 const struct buffer_desc output_buffer_desc[] =
2915 {.length = wmadec_block_size, .compare = compare_pcm16},
2916 {.length = wmadec_block_size / 2, .compare = compare_pcm16, .todo_length = TRUE},
2918 const struct attribute_desc output_sample_attributes[] =
2920 ATTR_UINT32(mft_output_sample_incomplete, 1),
2921 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
2922 {0},
2924 const struct attribute_desc output_sample_attributes_todo[] =
2926 ATTR_UINT32(mft_output_sample_incomplete, 1, .todo = TRUE),
2927 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
2928 {0},
2930 struct sample_desc output_sample_desc[] =
2933 .attributes = output_sample_attributes + 0,
2934 .sample_time = 0, .sample_duration = 928798,
2935 .buffer_count = 1, .buffers = output_buffer_desc + 0, .repeat_count = 1,
2938 .attributes = output_sample_attributes + 0,
2939 .sample_time = 1857596, .sample_duration = 928798,
2940 .buffer_count = 1, .buffers = output_buffer_desc + 0,
2943 .attributes = output_sample_attributes + 1, /* not MFT_OUTPUT_DATA_BUFFER_INCOMPLETE */
2944 .sample_time = 2786394, .sample_duration = 464399,
2945 .buffer_count = 1, .buffers = output_buffer_desc + 1, .todo_length = TRUE,
2949 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8};
2950 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_Float};
2951 IUnknown *unknown, *tmp_unknown, outer = {&test_unk_vtbl};
2952 IMFSample *input_sample, *output_sample;
2953 IMFCollection *output_samples;
2954 DWORD length, output_status;
2955 IMediaObject *media_object;
2956 IPropertyBag *property_bag;
2957 IMFMediaType *media_type;
2958 IMFTransform *transform;
2959 const BYTE *wmaenc_data;
2960 ULONG wmaenc_data_len;
2961 ULONG i, ret, ref;
2962 HRESULT hr;
2964 hr = CoInitialize(NULL);
2965 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
2967 winetest_push_context("wmadec");
2969 if (!check_mft_enum(MFT_CATEGORY_AUDIO_DECODER, &input_type, &output_type, class_id))
2970 goto failed;
2971 check_mft_get_info(class_id, &expect_mft_info);
2972 check_dmo_get_info(class_id, &expect_dmo_info);
2974 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
2975 &IID_IMFTransform, (void **)&transform)))
2976 goto failed;
2978 check_interface(transform, &IID_IMFTransform, TRUE);
2979 check_interface(transform, &IID_IMediaObject, TRUE);
2980 todo_wine
2981 check_interface(transform, &IID_IPropertyStore, TRUE);
2982 check_interface(transform, &IID_IPropertyBag, TRUE);
2984 check_mft_optional_methods(transform, 1);
2985 check_mft_get_attributes(transform, NULL, FALSE);
2986 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
2987 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
2989 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
2990 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
2992 i = -1;
2993 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
2995 winetest_push_context("in %lu", i);
2996 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
2997 check_media_type(media_type, expect_available_inputs[i], -1);
2998 ret = IMFMediaType_Release(media_type);
2999 ok(ret == 0, "Release returned %lu\n", ret);
3000 winetest_pop_context();
3002 todo_wine
3003 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
3004 todo_wine
3005 ok(i == 4, "%lu input media types\n", i);
3007 /* setting output media type first doesn't work */
3008 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
3009 check_mft_get_output_current_type_(transform, NULL, TRUE, FALSE);
3011 check_mft_set_input_type_required(transform, input_type_desc);
3012 check_mft_set_input_type(transform, input_type_desc);
3013 check_mft_get_input_current_type_(transform, expect_input_type_desc, TRUE, FALSE);
3015 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
3016 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
3018 /* check new output media types */
3020 i = -1;
3021 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
3023 winetest_push_context("out %lu", i);
3024 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3025 check_media_type(media_type, expect_available_outputs[i], -1);
3026 ret = IMFMediaType_Release(media_type);
3027 ok(ret == 0, "Release returned %lu\n", ret);
3028 winetest_pop_context();
3030 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3031 ok(i == 2, "%lu output media types\n", i);
3033 check_mft_set_output_type_required(transform, output_type_desc);
3034 check_mft_set_output_type(transform, output_type_desc, S_OK);
3035 check_mft_get_output_current_type_(transform, expect_output_type_desc, TRUE, FALSE);
3037 check_mft_get_input_stream_info(transform, S_OK, &input_info);
3038 check_mft_get_output_stream_info(transform, S_OK, &output_info);
3040 load_resource(L"wmaencdata.bin", &wmaenc_data, &wmaenc_data_len);
3041 ok(wmaenc_data_len % wmaenc_block_size == 0, "got length %lu\n", wmaenc_data_len);
3043 input_sample = create_sample(wmaenc_data, wmaenc_block_size / 2);
3044 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3045 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3046 ret = IMFSample_Release(input_sample);
3047 ok(ret == 0, "Release returned %lu\n", ret);
3048 input_sample = create_sample(wmaenc_data, wmaenc_block_size + 1);
3049 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3050 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3051 ret = IMFSample_Release(input_sample);
3052 ok(ret == 0, "Release returned %lu\n", ret);
3053 input_sample = create_sample(wmaenc_data, wmaenc_block_size);
3054 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3055 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3056 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3057 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
3058 ret = IMFSample_Release(input_sample);
3059 ok(ret == 1, "Release returned %lu\n", ret);
3061 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
3062 * IMFTransform_ProcessOutput needs a sample or returns MF_E_TRANSFORM_NEED_MORE_INPUT */
3064 hr = check_mft_process_output(transform, NULL, &output_status);
3065 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3066 ok(output_status == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE
3067 || broken(output_status == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
3068 "got output[0].dwStatus %#lx\n", output_status);
3070 input_sample = create_sample(wmaenc_data, wmaenc_block_size);
3071 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3072 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
3073 ret = IMFSample_Release(input_sample);
3074 ok(ret == 0, "Release returned %lu\n", ret);
3076 hr = check_mft_process_output(transform, NULL, &output_status);
3077 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3078 ok(output_status == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE
3079 || broken(output_status == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
3080 "got output[0].dwStatus %#lx\n", output_status);
3082 hr = MFCreateCollection(&output_samples);
3083 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
3085 output_sample = create_sample(NULL, output_info.cbSize);
3086 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
3088 winetest_push_context("%lu", i);
3089 ok(!(output_status & ~MFT_OUTPUT_DATA_BUFFER_INCOMPLETE), "got output[0].dwStatus %#lx\n", output_status);
3090 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
3091 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
3092 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
3093 ref = IMFSample_Release(output_sample);
3094 ok(ref == 1, "Release returned %ld\n", ref);
3095 output_sample = create_sample(NULL, output_info.cbSize);
3096 winetest_pop_context();
3098 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3099 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3100 ret = IMFSample_Release(output_sample);
3101 ok(ret == 0, "Release returned %lu\n", ret);
3102 todo_wine_if(i == 3) /* wmadec output depends on ffmpeg version used */
3103 ok(i == 4, "got %lu output samples\n", i);
3105 if (!strcmp(winetest_platform, "wine") && i == 3)
3106 output_sample_desc[1].attributes = output_sample_attributes_todo;
3108 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"wmadecdata.bin");
3109 todo_wine_if(ret > 0 && ret <= 10) /* ffmpeg sometimes offsets the decoded data */
3110 ok(ret == 0, "got %lu%% diff\n", ret);
3111 IMFCollection_Release(output_samples);
3113 output_sample = create_sample(NULL, output_info.cbSize);
3114 hr = check_mft_process_output(transform, output_sample, &output_status);
3115 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3116 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3117 hr = IMFSample_GetTotalLength(output_sample, &length);
3118 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
3119 ok(length == 0, "got length %lu\n", length);
3120 ret = IMFSample_Release(output_sample);
3121 ok(ret == 0, "Release returned %lu\n", ret);
3123 input_sample = create_sample(wmaenc_data, wmaenc_block_size);
3124 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3125 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3127 ret = IMFTransform_Release(transform);
3128 ok(ret == 0, "Release returned %lu\n", ret);
3129 ret = IMFSample_Release(input_sample);
3130 ok(ret == 0, "Release returned %lu\n", ret);
3132 hr = CoCreateInstance( &CLSID_CWMADecMediaObject, &outer, CLSCTX_INPROC_SERVER, &IID_IUnknown,
3133 (void **)&unknown );
3134 ok( hr == S_OK, "CoCreateInstance returned %#lx\n", hr );
3135 hr = IUnknown_QueryInterface( unknown, &IID_IMFTransform, (void **)&transform );
3136 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
3137 hr = IUnknown_QueryInterface( unknown, &IID_IMediaObject, (void **)&media_object );
3138 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
3139 hr = IUnknown_QueryInterface( unknown, &IID_IPropertyBag, (void **)&property_bag );
3140 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
3141 hr = IUnknown_QueryInterface( media_object, &IID_IUnknown, (void **)&tmp_unknown );
3142 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
3144 ok( unknown != &outer, "got outer IUnknown\n" );
3145 ok( transform != (void *)unknown, "got IUnknown == IMFTransform\n" );
3146 ok( media_object != (void *)unknown, "got IUnknown == IMediaObject\n" );
3147 ok( property_bag != (void *)unknown, "got IUnknown == IPropertyBag\n" );
3148 ok( tmp_unknown != unknown, "got inner IUnknown\n" );
3150 check_interface( unknown, &IID_IPersistPropertyBag, FALSE );
3151 check_interface( unknown, &IID_IAMFilterMiscFlags, FALSE );
3152 check_interface( unknown, &IID_IMediaSeeking, FALSE );
3153 check_interface( unknown, &IID_IMediaPosition, FALSE );
3154 check_interface( unknown, &IID_IReferenceClock, FALSE );
3155 check_interface( unknown, &IID_IBasicAudio, FALSE );
3157 ref = IUnknown_Release( tmp_unknown );
3158 ok( ref == 1, "Release returned %lu\n", ref );
3159 ref = IPropertyBag_Release( property_bag );
3160 ok( ref == 1, "Release returned %lu\n", ref );
3161 ref = IMediaObject_Release( media_object );
3162 ok( ref == 1, "Release returned %lu\n", ref );
3163 ref = IMFTransform_Release( transform );
3164 ok( ref == 1, "Release returned %lu\n", ref );
3165 ref = IUnknown_Release( unknown );
3166 ok( ref == 0, "Release returned %lu\n", ref );
3168 failed:
3169 winetest_pop_context();
3170 CoUninitialize();
3173 #define next_h264_sample(a, b) next_h264_sample_(__LINE__, a, b)
3174 static IMFSample *next_h264_sample_(int line, const BYTE **h264_buf, ULONG *h264_len)
3176 const BYTE *sample_data;
3178 ok_(__FILE__, line)(*h264_len > 4, "invalid h264 length\n");
3179 ok_(__FILE__, line)(*(UINT32 *)*h264_buf == 0x01000000, "invalid h264 buffer\n");
3180 sample_data = *h264_buf;
3182 (*h264_len) -= 4;
3183 (*h264_buf) += 4;
3185 while (*h264_len >= 4 && *(UINT32 *)*h264_buf != 0x01000000)
3187 (*h264_len)--;
3188 (*h264_buf)++;
3191 return create_sample(sample_data, *h264_buf - sample_data);
3194 static void test_h264_decoder(void)
3196 const GUID *const class_id = &CLSID_MSH264DecoderMFT;
3197 const struct transform_info expect_mft_info =
3199 .name = L"Microsoft H264 Video Decoder MFT",
3200 .major_type = &MFMediaType_Video,
3201 .inputs =
3203 {.subtype = &MFVideoFormat_H264},
3204 {.subtype = &MFVideoFormat_H264_ES},
3206 .outputs =
3208 {.subtype = &MFVideoFormat_NV12},
3209 {.subtype = &MFVideoFormat_YV12},
3210 {.subtype = &MFVideoFormat_IYUV},
3211 {.subtype = &MFVideoFormat_I420},
3212 {.subtype = &MFVideoFormat_YUY2},
3215 static const media_type_desc default_inputs[] =
3218 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3219 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
3222 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3223 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264_ES),
3226 static const struct attribute_desc expect_transform_attributes[] =
3228 ATTR_UINT32(MF_LOW_LATENCY, 0),
3229 ATTR_UINT32(MF_SA_D3D_AWARE, 1, .todo = TRUE),
3230 ATTR_UINT32(MF_SA_D3D11_AWARE, 1, .todo = TRUE),
3231 ATTR_UINT32(MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER, 0, .todo = TRUE),
3232 /* more H264 decoder specific attributes from CODECAPI */
3233 {0},
3235 static const DWORD input_width = 120, input_height = 248;
3236 const media_type_desc default_outputs[] =
3239 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3240 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
3241 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3242 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
3243 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
3244 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3245 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3246 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3247 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
3248 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
3249 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3252 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3253 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
3254 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3255 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
3256 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
3257 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3258 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3259 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3260 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
3261 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
3262 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3265 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3266 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
3267 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3268 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
3269 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
3270 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3271 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3272 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3273 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
3274 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
3275 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3278 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3279 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
3280 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3281 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
3282 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
3283 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3284 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3285 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3286 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
3287 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
3288 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3291 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3292 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
3293 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3294 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
3295 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width * 2),
3296 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3297 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3298 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3299 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
3300 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 2),
3301 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3304 const struct attribute_desc input_type_desc[] =
3306 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
3307 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264, .required = TRUE),
3308 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
3309 {0},
3311 const struct attribute_desc output_type_desc[] =
3313 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
3314 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE),
3315 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height, .required = TRUE),
3316 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
3317 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 2, 1),
3318 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
3319 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * input_height * 3 / 2),
3320 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
3321 {0},
3323 const struct attribute_desc expect_input_type_desc[] =
3325 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3326 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
3327 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
3328 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 0),
3329 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 0),
3330 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 0),
3331 ATTR_UINT32(MF_MT_AVG_BIT_ERROR_RATE, 0),
3332 ATTR_UINT32(MF_MT_COMPRESSED, 1),
3333 {0},
3335 const struct attribute_desc expect_output_type_desc[] =
3337 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3338 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
3339 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
3340 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
3341 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 2, 1),
3342 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
3343 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * input_height * 3 / 2),
3344 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
3345 ATTR_UINT32(MF_MT_AVG_BIT_ERROR_RATE, 0),
3346 ATTR_UINT32(MF_MT_COMPRESSED, 0),
3347 {0},
3349 static const struct attribute_desc new_output_type_desc[] =
3351 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3352 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
3353 ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96),
3354 ATTR_RATIO(MF_MT_FRAME_RATE, 1, 1),
3355 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 2),
3356 {0},
3358 static const struct attribute_desc expect_new_output_type_desc[] =
3360 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3361 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
3362 ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96),
3363 ATTR_RATIO(MF_MT_FRAME_RATE, 1, 1),
3364 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 2),
3365 ATTR_UINT32(MF_MT_COMPRESSED, 0),
3366 ATTR_UINT32(MF_MT_AVG_BIT_ERROR_RATE, 0),
3367 {0},
3369 static const MFVideoArea actual_aperture = {.Area={82,84}};
3370 static const DWORD actual_width = 96, actual_height = 96;
3371 const media_type_desc actual_outputs[] =
3374 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3375 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
3376 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3377 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
3378 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3379 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
3380 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
3381 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3382 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3383 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3384 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3385 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
3388 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3389 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
3390 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3391 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
3392 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3393 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
3394 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
3395 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3396 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3397 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3398 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3399 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
3402 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3403 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
3404 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3405 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
3406 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3407 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
3408 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
3409 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3410 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3411 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3412 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3413 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
3416 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3417 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
3418 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3419 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
3420 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3421 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
3422 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
3423 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3424 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3425 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3426 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3427 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
3430 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3431 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
3432 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3433 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
3434 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3435 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
3436 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
3437 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3438 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3439 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3440 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3441 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
3444 const MFT_OUTPUT_STREAM_INFO initial_output_info =
3446 .dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
3447 MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE,
3448 .cbSize = 1920 * 1088 * 2,
3450 const MFT_OUTPUT_STREAM_INFO output_info =
3452 .dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
3453 MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE,
3454 .cbSize = input_width * input_height * 2,
3456 const MFT_OUTPUT_STREAM_INFO actual_output_info =
3458 .dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
3459 MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE,
3460 .cbSize = actual_width * actual_height * 2,
3462 const MFT_INPUT_STREAM_INFO input_info =
3464 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
3465 MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE,
3466 .cbSize = 0x1000,
3469 const struct attribute_desc output_sample_attributes[] =
3471 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
3472 {0},
3474 const struct buffer_desc output_buffer_desc_nv12 =
3476 .length = actual_width * actual_height * 3 / 2,
3477 .compare = compare_nv12, .dump = dump_nv12, .rect = {.right = 82, .bottom = 84},
3479 const struct sample_desc output_sample_desc_nv12 =
3481 .attributes = output_sample_attributes,
3482 .sample_time = 0, .sample_duration = 333667,
3483 .buffer_count = 1, .buffers = &output_buffer_desc_nv12,
3485 const struct buffer_desc output_buffer_desc_i420 =
3487 .length = actual_width * actual_height * 3 / 2,
3488 .compare = compare_i420, .dump = dump_i420, .rect = {.right = 82, .bottom = 84},
3490 const struct sample_desc expect_output_sample_i420 =
3492 .attributes = output_sample_attributes,
3493 .sample_time = 333667, .sample_duration = 333667, .todo_time = 1334666 /* with VA-API */,
3494 .buffer_count = 1, .buffers = &output_buffer_desc_i420,
3497 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_H264};
3498 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
3499 IMFSample *input_sample, *output_sample;
3500 const BYTE *h264_encoded_data;
3501 IMFCollection *output_samples;
3502 ULONG h264_encoded_data_len;
3503 DWORD length, output_status;
3504 IMFAttributes *attributes;
3505 IMFMediaType *media_type;
3506 IMFTransform *transform;
3507 ULONG i, ret, ref;
3508 HRESULT hr;
3510 hr = CoInitialize(NULL);
3511 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
3513 winetest_push_context("h264dec");
3515 if (!check_mft_enum(MFT_CATEGORY_VIDEO_DECODER, &input_type, &output_type, class_id))
3516 goto failed;
3517 check_mft_get_info(class_id, &expect_mft_info);
3519 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
3520 &IID_IMFTransform, (void **)&transform)))
3521 goto failed;
3523 check_interface(transform, &IID_IMFTransform, TRUE);
3524 check_interface(transform, &IID_IMediaObject, FALSE);
3525 check_interface(transform, &IID_IPropertyStore, FALSE);
3526 check_interface(transform, &IID_IPropertyBag, FALSE);
3528 check_mft_optional_methods(transform, 1);
3529 check_mft_get_attributes(transform, expect_transform_attributes, TRUE);
3530 check_mft_get_input_stream_info(transform, S_OK, &input_info);
3531 check_mft_get_output_stream_info(transform, S_OK, &initial_output_info);
3533 hr = IMFTransform_GetAttributes(transform, &attributes);
3534 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
3535 hr = IMFAttributes_SetUINT32(attributes, &MF_LOW_LATENCY, 1);
3536 ok(hr == S_OK, "SetUINT32 returned %#lx\n", hr);
3537 IMFAttributes_Release(attributes);
3539 /* no output type is available before an input type is set */
3541 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
3542 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
3544 /* setting output media type first doesn't work */
3545 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
3546 check_mft_get_output_current_type(transform, NULL);
3548 /* check available input types */
3550 i = -1;
3551 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
3553 winetest_push_context("in %lu", i);
3554 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
3555 check_media_type(media_type, default_inputs[i], -1);
3556 ret = IMFMediaType_Release(media_type);
3557 ok(ret == 0, "Release returned %lu\n", ret);
3558 winetest_pop_context();
3560 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
3561 ok(i == 2 || broken(i == 1) /* Win7 */, "%lu input media types\n", i);
3563 check_mft_set_input_type_required(transform, input_type_desc);
3564 check_mft_set_input_type(transform, input_type_desc);
3565 check_mft_get_input_current_type_(transform, expect_input_type_desc, TRUE, FALSE);
3567 check_mft_get_input_stream_info(transform, S_OK, &input_info);
3568 check_mft_get_output_stream_info(transform, S_OK, &output_info);
3570 /* output types can now be enumerated (though they are actually the same for all input types) */
3572 i = -1;
3573 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
3575 winetest_push_context("out %lu", i);
3576 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3577 check_media_type(media_type, default_outputs[i], -1);
3578 ret = IMFMediaType_Release(media_type);
3579 ok(ret == 0, "Release returned %lu\n", ret);
3580 winetest_pop_context();
3582 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3583 ok(i == 5, "%lu output media types\n", i);
3585 check_mft_set_output_type_required(transform, output_type_desc);
3586 check_mft_set_output_type(transform, output_type_desc, S_OK);
3587 check_mft_get_output_current_type_(transform, expect_output_type_desc, FALSE, TRUE);
3589 /* check that the output media type we've selected don't change the enumeration */
3591 i = -1;
3592 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
3594 winetest_push_context("out %lu", i);
3595 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3596 check_media_type(media_type, default_outputs[i], -1);
3597 ret = IMFMediaType_Release(media_type);
3598 ok(ret == 0, "Release returned %lu\n", ret);
3599 winetest_pop_context();
3601 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3602 ok(i == 5, "%lu output media types\n", i);
3604 check_mft_get_input_stream_info(transform, S_OK, &input_info);
3605 check_mft_get_output_stream_info(transform, S_OK, &output_info);
3607 load_resource(L"h264data.bin", &h264_encoded_data, &h264_encoded_data_len);
3609 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
3610 * IMFTransform_ProcessOutput needs a sample or returns an error */
3612 hr = check_mft_process_output(transform, NULL, &output_status);
3613 ok(hr == E_INVALIDARG || hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3614 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3616 i = 0;
3617 input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
3618 while (1)
3620 output_sample = create_sample(NULL, output_info.cbSize);
3621 hr = check_mft_process_output(transform, output_sample, &output_status);
3622 if (hr != MF_E_TRANSFORM_NEED_MORE_INPUT) break;
3624 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3625 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3626 hr = IMFSample_GetTotalLength(output_sample, &length);
3627 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
3628 ok(length == 0, "got length %lu\n", length);
3629 ret = IMFSample_Release(output_sample);
3630 ok(ret == 0, "Release returned %lu\n", ret);
3632 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3633 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3634 ret = IMFSample_Release(input_sample);
3635 ok(ret <= 1, "Release returned %lu\n", ret);
3636 input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
3638 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3639 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3640 ret = IMFSample_Release(input_sample);
3641 ok(ret <= 1, "Release returned %lu\n", ret);
3642 input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
3643 i++;
3645 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
3646 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
3648 todo_wine
3649 ok(i == 2, "got %lu iterations\n", i);
3650 todo_wine
3651 ok(h264_encoded_data_len == 1180, "got h264_encoded_data_len %lu\n", h264_encoded_data_len);
3652 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
3653 ok(output_status == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got output[0].dwStatus %#lx\n", output_status);
3654 hr = IMFSample_GetTotalLength(output_sample, &length);
3655 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
3656 ok(length == 0, "got length %lu\n", length);
3657 ret = IMFSample_Release(output_sample);
3658 ok(ret == 0, "Release returned %lu\n", ret);
3660 check_mft_get_input_stream_info(transform, S_OK, &input_info);
3661 check_mft_get_output_stream_info(transform, S_OK, &actual_output_info);
3663 i = -1;
3664 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
3666 winetest_push_context("out %lu", i);
3667 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3668 check_media_type(media_type, actual_outputs[i], -1);
3669 ret = IMFMediaType_Release(media_type);
3670 ok(ret == 0, "Release returned %lu\n", ret);
3671 winetest_pop_context();
3673 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3674 ok(i == 5, "%lu output media types\n", i);
3676 /* current output type is still the one we selected */
3677 check_mft_get_output_current_type_(transform, expect_output_type_desc, FALSE, TRUE);
3679 hr = MFCreateCollection(&output_samples);
3680 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
3682 output_sample = create_sample(NULL, output_info.cbSize);
3683 hr = check_mft_process_output(transform, output_sample, &output_status);
3684 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
3685 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3686 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
3687 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
3688 ref = IMFSample_Release(output_sample);
3689 ok(ref == 1, "Release returned %ld\n", ref);
3691 ret = check_mf_sample_collection(output_samples, &output_sample_desc_nv12, L"nv12frame.bmp");
3692 ok(ret == 0, "got %lu%% diff\n", ret);
3693 IMFCollection_Release(output_samples);
3695 /* we can change it, but only with the correct frame size */
3696 hr = MFCreateMediaType(&media_type);
3697 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
3698 init_media_type(media_type, output_type_desc, -1);
3699 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3700 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
3701 init_media_type(media_type, new_output_type_desc, -1);
3702 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3703 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
3704 ret = IMFMediaType_Release(media_type);
3705 ok(ret == 1, "Release returned %lu\n", ret);
3707 check_mft_get_output_current_type_(transform, expect_new_output_type_desc, FALSE, TRUE);
3709 output_sample = create_sample(NULL, actual_width * actual_height * 2);
3710 hr = check_mft_process_output(transform, output_sample, &output_status);
3711 todo_wine
3712 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
3713 todo_wine
3714 ok(output_status == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got output[0].dwStatus %#lx\n", output_status);
3716 while (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
3718 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3719 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3720 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3721 ret = IMFSample_Release(input_sample);
3722 ok(ret <= 1, "Release returned %lu\n", ret);
3723 input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
3724 hr = check_mft_process_output(transform, output_sample, &output_status);
3727 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
3728 ok(output_status == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got output[0].dwStatus %#lx\n", output_status);
3730 hr = IMFSample_GetTotalLength(output_sample, &length);
3731 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
3732 ok(length == 0, "got length %lu\n", length);
3733 ret = IMFSample_Release(output_sample);
3734 ok(ret == 0, "Release returned %lu\n", ret);
3736 hr = MFCreateCollection(&output_samples);
3737 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
3739 output_sample = create_sample(NULL, actual_width * actual_height * 2);
3740 hr = check_mft_process_output(transform, output_sample, &output_status);
3741 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
3742 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3743 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
3744 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
3745 ref = IMFSample_Release(output_sample);
3746 ok(ref == 1, "Release returned %ld\n", ref);
3748 ret = check_mf_sample_collection(output_samples, &expect_output_sample_i420, L"i420frame.bmp");
3749 ok(ret == 0, "got %lu%% diff\n", ret);
3750 IMFCollection_Release(output_samples);
3752 output_sample = create_sample(NULL, actual_width * actual_height * 2);
3753 hr = check_mft_process_output(transform, output_sample, &output_status);
3754 todo_wine_if(hr == S_OK) /* when VA-API plugin is used */
3755 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3756 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3757 ret = IMFSample_Release(output_sample);
3758 ok(ret == 0, "Release returned %lu\n", ret);
3760 ret = IMFTransform_Release(transform);
3761 ok(ret == 0, "Release returned %lu\n", ret);
3762 ret = IMFSample_Release(input_sample);
3763 ok(ret == 0, "Release returned %lu\n", ret);
3765 failed:
3766 winetest_pop_context();
3767 CoUninitialize();
3770 static void test_audio_convert(void)
3772 const GUID *const class_id = &CLSID_CResamplerMediaObject;
3773 const struct transform_info expect_mft_info =
3775 .name = L"Resampler MFT",
3776 .major_type = &MFMediaType_Audio,
3777 .inputs =
3779 {.subtype = &MFAudioFormat_PCM},
3780 {.subtype = &MFAudioFormat_Float},
3782 .outputs =
3784 {.subtype = &MFAudioFormat_PCM},
3785 {.subtype = &MFAudioFormat_Float},
3788 const struct transform_info expect_dmo_info =
3790 .name = L"Resampler DMO",
3791 .major_type = &MEDIATYPE_Audio,
3792 .inputs =
3794 {.subtype = &MEDIASUBTYPE_PCM},
3795 {.subtype = &MEDIASUBTYPE_IEEE_FLOAT},
3797 .outputs =
3799 {.subtype = &MEDIASUBTYPE_PCM},
3800 {.subtype = &MEDIASUBTYPE_IEEE_FLOAT},
3804 static const media_type_desc expect_available_inputs[] =
3807 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3808 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
3809 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3812 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3813 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
3814 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3817 static const media_type_desc expect_available_outputs[] =
3820 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3821 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
3822 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3825 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3826 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
3827 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3830 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3831 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
3832 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
3833 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
3834 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
3835 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 384000),
3836 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
3837 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3838 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
3841 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3842 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
3843 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
3844 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
3845 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
3846 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 192000),
3847 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
3848 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3849 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
3853 static const struct attribute_desc input_type_desc[] =
3855 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
3856 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float, .required = TRUE),
3857 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
3858 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32, .required = TRUE),
3859 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
3860 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2 * (32 / 8), .required = TRUE),
3861 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * (32 / 8) * 22050, .required = TRUE),
3862 {0},
3864 const struct attribute_desc output_type_desc[] =
3866 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
3867 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM, .required = TRUE),
3868 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
3869 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
3870 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .required = TRUE),
3871 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2 * (16 / 8), .required = TRUE),
3872 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * (16 / 8) * 44100, .required = TRUE),
3873 {0},
3875 static const struct attribute_desc expect_input_type_desc[] =
3877 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3878 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
3879 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
3880 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
3881 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
3882 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
3883 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 22050 * 8),
3884 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3885 ATTR_UINT32(MF_MT_AUDIO_CHANNEL_MASK, 3),
3886 {0},
3888 const struct attribute_desc expect_output_type_desc[] =
3890 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3891 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
3892 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
3893 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
3894 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
3895 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
3896 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 * 4),
3897 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3898 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
3899 {0},
3901 const MFT_OUTPUT_STREAM_INFO output_info =
3903 .cbSize = 4,
3904 .cbAlignment = 1,
3906 const MFT_INPUT_STREAM_INFO input_info =
3908 .cbSize = 8,
3909 .cbAlignment = 1,
3912 static const ULONG audioconv_block_size = 0x4000;
3913 const struct buffer_desc output_buffer_desc[] =
3915 {.length = audioconv_block_size, .compare = compare_pcm16},
3916 {.length = 0x3dd8, .compare = compare_pcm16, .todo_length = TRUE},
3917 {.length = 0xfc, .compare = compare_pcm16},
3919 const struct attribute_desc output_sample_attributes[] =
3921 ATTR_UINT32(mft_output_sample_incomplete, 1),
3922 ATTR_UINT32(MFSampleExtension_CleanPoint, has_video_processor /* 0 on Win7 */, .todo = TRUE),
3923 {0},
3925 const struct sample_desc output_sample_desc[] =
3928 .attributes = output_sample_attributes + 0,
3929 .sample_time = 0, .sample_duration = 928798,
3930 .buffer_count = 1, .buffers = output_buffer_desc + 0, .repeat_count = 9,
3933 .attributes = output_sample_attributes + 1, /* not MFT_OUTPUT_DATA_BUFFER_INCOMPLETE */
3934 .sample_time = 9287980, .sample_duration = 897506,
3935 .buffer_count = 1, .buffers = output_buffer_desc + 1, .todo_length = TRUE,
3938 .attributes = output_sample_attributes + 0,
3939 .sample_time = 10185486, .sample_duration = 14286,
3940 .buffer_count = 1, .buffers = output_buffer_desc + 2,
3944 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_PCM};
3945 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_Float};
3946 IMFSample *input_sample, *output_sample;
3947 IMFCollection *output_samples;
3948 DWORD length, output_status;
3949 IMFMediaType *media_type;
3950 IMFTransform *transform;
3951 const BYTE *audio_data;
3952 ULONG audio_data_len;
3953 ULONG i, ret, ref;
3954 HRESULT hr;
3956 hr = CoInitialize(NULL);
3957 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
3959 winetest_push_context("resampler");
3961 if (!check_mft_enum(MFT_CATEGORY_AUDIO_EFFECT, &input_type, &output_type, class_id))
3962 goto failed;
3963 check_mft_get_info(class_id, &expect_mft_info);
3964 check_dmo_get_info(class_id, &expect_dmo_info);
3966 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
3967 &IID_IMFTransform, (void **)&transform)))
3968 goto failed;
3970 check_interface(transform, &IID_IMFTransform, TRUE);
3971 check_interface(transform, &IID_IMediaObject, TRUE);
3972 check_interface(transform, &IID_IPropertyStore, TRUE);
3973 check_interface(transform, &IID_IPropertyBag, TRUE);
3974 /* check_interface(transform, &IID_IWMResamplerProps, TRUE); */
3976 check_mft_optional_methods(transform, 1);
3977 check_mft_get_attributes(transform, NULL, FALSE);
3978 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
3979 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
3981 i = -1;
3982 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
3984 winetest_push_context("out %lu", i);
3985 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3986 check_media_type(media_type, expect_available_outputs[i], -1);
3987 ret = IMFMediaType_Release(media_type);
3988 ok(ret == 0, "Release returned %lu\n", ret);
3989 winetest_pop_context();
3991 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3992 ok(i == 4, "%lu output media types\n", i);
3994 i = -1;
3995 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
3997 winetest_push_context("in %lu", i);
3998 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
3999 check_media_type(media_type, expect_available_inputs[i], -1);
4000 ret = IMFMediaType_Release(media_type);
4001 ok(ret == 0, "Release returned %lu\n", ret);
4002 winetest_pop_context();
4004 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
4005 ok(i == 2, "%lu input media types\n", i);
4007 /* setting output media type first doesn't work */
4008 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
4009 check_mft_get_output_current_type(transform, NULL);
4011 check_mft_set_input_type_required(transform, input_type_desc);
4012 check_mft_set_input_type(transform, input_type_desc);
4013 check_mft_get_input_current_type_(transform, expect_input_type_desc, FALSE, TRUE);
4015 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
4016 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
4018 /* check new output media types */
4020 i = -1;
4021 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
4023 winetest_push_context("out %lu", i);
4024 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
4025 check_media_type(media_type, expect_available_outputs[i], -1);
4026 ret = IMFMediaType_Release(media_type);
4027 ok(ret == 0, "Release returned %lu\n", ret);
4028 winetest_pop_context();
4030 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
4031 ok(i == 4, "%lu output media types\n", i);
4033 check_mft_set_output_type_required(transform, output_type_desc);
4034 check_mft_set_output_type(transform, output_type_desc, S_OK);
4035 check_mft_get_output_current_type_(transform, expect_output_type_desc, FALSE, TRUE);
4037 check_mft_get_input_stream_info(transform, S_OK, &input_info);
4038 check_mft_get_output_stream_info(transform, S_OK, &output_info);
4040 load_resource(L"audiodata.bin", &audio_data, &audio_data_len);
4041 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
4043 input_sample = create_sample(audio_data, audio_data_len);
4044 hr = IMFSample_SetSampleTime(input_sample, 0);
4045 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
4046 hr = IMFSample_SetSampleDuration(input_sample, 10000000);
4047 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
4048 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
4049 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
4050 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
4051 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
4052 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
4053 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
4054 ret = IMFSample_Release(input_sample);
4055 ok(ret <= 1, "Release returned %ld\n", ret);
4057 hr = MFCreateCollection(&output_samples);
4058 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
4060 output_sample = create_sample(NULL, audioconv_block_size);
4061 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
4063 winetest_push_context("%lu", i);
4064 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
4065 ok(!(output_status & ~MFT_OUTPUT_DATA_BUFFER_INCOMPLETE), "got output[0].dwStatus %#lx\n", output_status);
4066 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
4067 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
4068 ref = IMFSample_Release(output_sample);
4069 ok(ref == 1, "Release returned %ld\n", ref);
4070 output_sample = create_sample(NULL, audioconv_block_size);
4071 winetest_pop_context();
4073 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
4074 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
4075 ret = IMFSample_Release(output_sample);
4076 ok(ret == 0, "Release returned %lu\n", ret);
4077 todo_wine
4078 ok(i == 12 || broken(i == 11) /* Win7 */, "got %lu output samples\n", i);
4080 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"audioconvdata.bin");
4081 ok(ret == 0, "got %lu%% diff\n", ret);
4082 IMFCollection_Release(output_samples);
4084 output_sample = create_sample(NULL, audioconv_block_size);
4085 hr = check_mft_process_output(transform, output_sample, &output_status);
4086 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
4087 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
4088 hr = IMFSample_GetTotalLength(output_sample, &length);
4089 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
4090 ok(length == 0, "got length %lu\n", length);
4091 ret = IMFSample_Release(output_sample);
4092 ok(ret == 0, "Release returned %lu\n", ret);
4094 ret = IMFTransform_Release(transform);
4095 ok(ret == 0, "Release returned %lu\n", ret);
4097 failed:
4098 winetest_pop_context();
4099 CoUninitialize();
4102 static void test_wmv_encoder(void)
4104 const GUID *const class_id = &CLSID_CWMVXEncMediaObject;
4105 const struct transform_info expect_mft_info =
4107 .name = L"WMVideo8 Encoder MFT",
4108 .major_type = &MFMediaType_Video,
4109 .inputs =
4111 {.subtype = &MFVideoFormat_IYUV},
4112 {.subtype = &MFVideoFormat_I420},
4113 {.subtype = &MFVideoFormat_YV12},
4114 {.subtype = &MFVideoFormat_NV11},
4115 {.subtype = &MFVideoFormat_NV12},
4116 {.subtype = &MFVideoFormat_YUY2},
4117 {.subtype = &MFVideoFormat_UYVY},
4118 {.subtype = &MFVideoFormat_YVYU},
4119 {.subtype = &MFVideoFormat_YVU9},
4120 {.subtype = &DMOVideoFormat_RGB32},
4121 {.subtype = &DMOVideoFormat_RGB24},
4122 {.subtype = &DMOVideoFormat_RGB565},
4123 {.subtype = &DMOVideoFormat_RGB555},
4124 {.subtype = &DMOVideoFormat_RGB8},
4126 .outputs =
4128 {.subtype = &MFVideoFormat_WMV1},
4129 {.subtype = &MFVideoFormat_WMV2},
4132 const struct transform_info expect_dmo_info =
4134 .name = L"WMVideo8 Encoder DMO",
4135 .major_type = &MEDIATYPE_Video,
4136 .inputs =
4138 {.subtype = &MEDIASUBTYPE_IYUV},
4139 {.subtype = &MEDIASUBTYPE_I420},
4140 {.subtype = &MEDIASUBTYPE_YV12},
4141 {.subtype = &MEDIASUBTYPE_NV11},
4142 {.subtype = &MEDIASUBTYPE_NV12},
4143 {.subtype = &MEDIASUBTYPE_YUY2},
4144 {.subtype = &MEDIASUBTYPE_UYVY},
4145 {.subtype = &MEDIASUBTYPE_YVYU},
4146 {.subtype = &MEDIASUBTYPE_YVU9},
4147 {.subtype = &MEDIASUBTYPE_RGB32},
4148 {.subtype = &MEDIASUBTYPE_RGB24},
4149 {.subtype = &MEDIASUBTYPE_RGB565},
4150 {.subtype = &MEDIASUBTYPE_RGB555},
4151 {.subtype = &MEDIASUBTYPE_RGB8},
4153 .outputs =
4155 {.subtype = &MEDIASUBTYPE_WMV1},
4156 {.subtype = &MEDIASUBTYPE_WMV2},
4160 static const media_type_desc expect_available_inputs[] =
4163 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4164 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
4165 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4166 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4167 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4168 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4169 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4170 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4173 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4174 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
4175 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4176 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4177 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4178 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4179 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4180 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4183 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4184 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
4185 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4186 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4187 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4188 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4189 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4190 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4193 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4194 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11),
4195 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4196 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4197 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4198 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4199 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4200 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4203 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4204 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
4205 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4206 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4207 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4208 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4209 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4210 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4213 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4214 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
4215 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4216 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4217 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4218 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4219 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4220 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4223 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4224 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY),
4225 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4226 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4227 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4228 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4229 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4230 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4233 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4234 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU),
4235 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4236 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4237 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4238 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4239 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4240 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4243 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4244 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
4245 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4246 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4247 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4248 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4249 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4250 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4253 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4254 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24),
4255 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4256 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4257 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4258 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4259 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4260 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4263 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4264 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565),
4265 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4266 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4267 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4268 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4269 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4270 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4273 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4274 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555),
4275 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4276 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4277 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4278 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4279 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4280 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4283 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4284 ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_RGB8),
4285 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4286 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4287 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4288 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4289 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4290 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4293 static const media_type_desc expect_available_outputs[] =
4296 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4297 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1),
4298 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4299 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4300 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4301 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4304 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4305 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV2),
4306 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4307 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4308 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4309 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4313 static const DWORD actual_width = 96, actual_height = 96;
4314 const struct attribute_desc input_type_desc[] =
4316 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
4317 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE),
4318 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001, .required = TRUE),
4319 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height), /* required for SetOutputType */
4320 {0},
4322 const struct attribute_desc output_type_desc[] =
4324 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
4325 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1, .required = TRUE),
4326 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
4327 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001, .required = TRUE),
4328 ATTR_UINT32(MF_MT_AVG_BITRATE, 193540, .required = TRUE),
4329 {0},
4332 const struct attribute_desc expect_input_type_desc[] =
4334 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4335 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
4336 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
4337 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4338 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
4339 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
4340 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4341 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4342 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4343 {0},
4345 const struct attribute_desc expect_output_type_desc[] =
4347 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4348 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1),
4349 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4350 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
4351 ATTR_UINT32(MF_MT_AVG_BITRATE, 193540),
4352 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4353 {0},
4355 static const MFT_OUTPUT_STREAM_INFO empty_output_info =
4357 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER,
4359 static const MFT_INPUT_STREAM_INFO empty_input_info =
4361 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER,
4363 static const MFT_OUTPUT_STREAM_INFO expect_output_info =
4365 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER,
4366 .cbSize = 0x8000,
4367 .cbAlignment = 1,
4369 static const MFT_INPUT_STREAM_INFO expect_input_info =
4371 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER,
4372 .cbSize = 0x3600,
4373 .cbAlignment = 1,
4376 const struct buffer_desc output_buffer_desc[] =
4378 {.length = -1 /* variable */},
4380 const struct attribute_desc output_sample_attributes_key[] =
4382 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
4383 {0},
4385 const struct attribute_desc output_sample_attributes[] =
4387 ATTR_UINT32(MFSampleExtension_CleanPoint, 0),
4388 {0},
4390 const struct sample_desc output_sample_desc[] =
4393 .attributes = output_sample_attributes_key,
4394 .sample_time = 0, .sample_duration = 333333,
4395 .buffer_count = 1, .buffers = output_buffer_desc,
4398 .attributes = output_sample_attributes,
4399 .sample_time = 333333, .sample_duration = 333333,
4400 .buffer_count = 1, .buffers = output_buffer_desc, .repeat_count = 4
4404 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_WMV1};
4405 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_NV12};
4406 IMFSample *input_sample, *output_sample;
4407 DWORD status, length, output_status;
4408 MFT_OUTPUT_DATA_BUFFER output;
4409 IMFCollection *output_samples;
4410 const BYTE *nv12frame_data;
4411 IMFMediaType *media_type;
4412 ULONG nv12frame_data_len;
4413 IMFTransform *transform;
4414 ULONG i, ret;
4415 HRESULT hr;
4416 LONG ref;
4418 hr = CoInitialize(NULL);
4419 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
4421 winetest_push_context("wmvenc");
4423 if (!check_mft_enum(MFT_CATEGORY_VIDEO_ENCODER, &input_type, &output_type, class_id))
4424 goto failed;
4425 check_mft_get_info(class_id, &expect_mft_info);
4426 check_dmo_get_info(class_id, &expect_dmo_info);
4428 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
4429 &IID_IMFTransform, (void **)&transform)))
4430 goto failed;
4432 check_interface(transform, &IID_IMFTransform, TRUE);
4433 check_interface(transform, &IID_IMediaObject, TRUE);
4434 check_interface(transform, &IID_IPropertyStore, TRUE);
4435 check_interface(transform, &IID_IPropertyBag, TRUE);
4437 check_mft_optional_methods(transform, 2);
4438 check_mft_get_attributes(transform, NULL, FALSE);
4439 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, &empty_input_info);
4440 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, &empty_output_info);
4442 i = -1;
4443 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
4445 winetest_push_context("in 0 %lu", i);
4446 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
4447 ret = IMFMediaType_Release(media_type);
4448 ok(ret <= 1, "Release returned %lu\n", ret);
4449 winetest_pop_context();
4451 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
4452 ok(i == ARRAY_SIZE(expect_available_inputs), "%lu input media types\n", i);
4454 i = -1;
4455 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
4457 winetest_push_context("out %lu", i);
4458 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
4459 ret = IMFMediaType_Release(media_type);
4460 ok(ret <= 1, "Release returned %lu\n", ret);
4461 winetest_pop_context();
4463 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
4464 ok(i == ARRAY_SIZE(expect_available_outputs), "%lu output media types\n", i);
4466 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
4467 check_mft_get_output_current_type(transform, NULL);
4469 check_mft_set_input_type_required(transform, input_type_desc);
4470 check_mft_set_input_type(transform, input_type_desc);
4471 check_mft_get_input_current_type_(transform, expect_input_type_desc, FALSE, TRUE);
4473 check_mft_set_output_type_required(transform, output_type_desc);
4474 check_mft_set_output_type(transform, output_type_desc, S_OK);
4475 check_mft_get_output_current_type_(transform, expect_output_type_desc, FALSE, TRUE);
4477 check_mft_get_input_stream_info(transform, S_OK, &expect_input_info);
4478 check_mft_get_output_stream_info(transform, S_OK, &expect_output_info);
4480 if (!has_video_processor)
4482 win_skip("Skipping WMV encoder tests on Win7\n");
4483 goto done;
4486 load_resource(L"nv12frame.bmp", &nv12frame_data, &nv12frame_data_len);
4487 /* skip BMP header and RGB data from the dump */
4488 length = *(DWORD *)(nv12frame_data + 2);
4489 nv12frame_data_len = nv12frame_data_len - length;
4490 nv12frame_data = nv12frame_data + length;
4491 ok(nv12frame_data_len == 13824, "got length %lu\n", nv12frame_data_len);
4493 hr = MFCreateCollection(&output_samples);
4494 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
4496 for (i = 0; i < 5; i++)
4498 input_sample = create_sample(nv12frame_data, nv12frame_data_len);
4499 hr = IMFSample_SetSampleTime(input_sample, i * 333333);
4500 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
4501 hr = IMFSample_SetSampleDuration(input_sample, 333333);
4502 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
4503 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
4504 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
4505 ref = IMFSample_Release(input_sample);
4506 ok(ref <= 1, "Release returned %ld\n", ref);
4508 output_sample = create_sample(NULL, expect_output_info.cbSize);
4509 hr = check_mft_process_output(transform, output_sample, &output_status);
4510 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
4511 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
4512 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
4513 ref = IMFSample_Release(output_sample);
4514 ok(ref == 1, "Release returned %ld\n", ref);
4517 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"wmvencdata.bin");
4518 ok(ret == 0, "got %lu%% diff\n", ret);
4519 IMFCollection_Release(output_samples);
4521 output_sample = create_sample(NULL, expect_output_info.cbSize);
4522 status = 0xdeadbeef;
4523 memset(&output, 0, sizeof(output));
4524 output.pSample = output_sample;
4525 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
4526 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
4527 ok(output.pSample == output_sample, "got pSample %p\n", output.pSample);
4528 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
4529 ok(status == 0, "got status %#lx\n", status);
4530 hr = IMFSample_GetTotalLength(output.pSample, &length);
4531 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
4532 ok(length == 0, "got length %lu\n", length);
4533 ret = IMFSample_Release(output_sample);
4534 ok(ret == 0, "Release returned %lu\n", ret);
4536 done:
4537 ret = IMFTransform_Release(transform);
4538 ok(ret == 0, "Release returned %lu\n", ret);
4540 failed:
4541 winetest_pop_context();
4542 CoUninitialize();
4545 static void test_wmv_decoder(void)
4547 const GUID *const class_id = &CLSID_CWMVDecMediaObject;
4548 const struct transform_info expect_mft_info =
4550 .name = L"WMVideo Decoder MFT",
4551 .major_type = &MFMediaType_Video,
4552 .inputs =
4554 {.subtype = &MFVideoFormat_WMV1},
4555 {.subtype = &MFVideoFormat_WMV2},
4556 {.subtype = &MFVideoFormat_WMV3},
4557 {.subtype = &MEDIASUBTYPE_WMVP},
4558 {.subtype = &MEDIASUBTYPE_WVP2},
4559 {.subtype = &MEDIASUBTYPE_WMVR},
4560 {.subtype = &MEDIASUBTYPE_WMVA},
4561 {.subtype = &MFVideoFormat_WVC1},
4562 {.subtype = &MFVideoFormat_VC1S},
4564 .outputs =
4566 {.subtype = &MFVideoFormat_YV12},
4567 {.subtype = &MFVideoFormat_YUY2},
4568 {.subtype = &MFVideoFormat_UYVY},
4569 {.subtype = &MFVideoFormat_YVYU},
4570 {.subtype = &MFVideoFormat_NV11},
4571 {.subtype = &MFVideoFormat_NV12},
4572 {.subtype = &DMOVideoFormat_RGB32},
4573 {.subtype = &DMOVideoFormat_RGB24},
4574 {.subtype = &DMOVideoFormat_RGB565},
4575 {.subtype = &DMOVideoFormat_RGB555},
4576 {.subtype = &DMOVideoFormat_RGB8},
4579 const struct transform_info expect_dmo_info =
4581 .name = L"WMVideo Decoder DMO",
4582 .major_type = &MEDIATYPE_Video,
4583 .inputs =
4585 {.subtype = &MEDIASUBTYPE_WMV1},
4586 {.subtype = &MEDIASUBTYPE_WMV2},
4587 {.subtype = &MEDIASUBTYPE_WMV3},
4588 {.subtype = &MEDIASUBTYPE_WMVA},
4589 {.subtype = &MEDIASUBTYPE_WVC1},
4590 {.subtype = &MEDIASUBTYPE_WMVP},
4591 {.subtype = &MEDIASUBTYPE_WVP2},
4592 {.subtype = &MFVideoFormat_VC1S},
4594 .outputs =
4596 {.subtype = &MEDIASUBTYPE_YV12},
4597 {.subtype = &MEDIASUBTYPE_YUY2},
4598 {.subtype = &MEDIASUBTYPE_UYVY},
4599 {.subtype = &MEDIASUBTYPE_YVYU},
4600 {.subtype = &MEDIASUBTYPE_NV11},
4601 {.subtype = &MEDIASUBTYPE_NV12},
4602 {.subtype = &MEDIASUBTYPE_RGB32},
4603 {.subtype = &MEDIASUBTYPE_RGB24},
4604 {.subtype = &MEDIASUBTYPE_RGB565},
4605 {.subtype = &MEDIASUBTYPE_RGB555},
4606 {.subtype = &MEDIASUBTYPE_RGB8},
4610 static const struct attribute_desc expect_common_attributes[] =
4612 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4613 {0},
4615 static const media_type_desc expect_available_inputs[] =
4617 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1)},
4618 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV2)},
4619 {ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_WMVA)},
4620 {ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_WMVP)},
4621 {ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_WVP2)},
4622 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV_Unknown)},
4623 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WVC1)},
4624 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV3)},
4625 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_VC1S)},
4627 static const MFVideoArea actual_aperture = {.Area={96,96}};
4628 static const DWORD actual_width = 96, actual_height = 96;
4629 const struct attribute_desc expect_output_attributes[] =
4631 ATTR_BLOB(MF_MT_GEOMETRIC_APERTURE, &actual_aperture, sizeof(actual_aperture)),
4632 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, sizeof(actual_aperture)),
4633 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4634 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4635 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4636 ATTR_UINT32(MF_MT_INTERLACE_MODE, 2),
4637 {0},
4639 const media_type_desc expect_available_outputs[] =
4642 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4643 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
4644 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4645 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
4646 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
4649 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4650 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
4651 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4652 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
4653 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
4656 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4657 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
4658 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4659 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
4660 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
4663 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4664 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
4665 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4666 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
4667 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
4670 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4671 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
4672 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4673 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
4674 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
4677 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4678 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY),
4679 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4680 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
4681 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
4684 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4685 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU),
4686 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4687 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
4688 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
4691 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4692 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11),
4693 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4694 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
4695 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
4698 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4699 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
4700 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4701 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 4),
4702 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 4),
4705 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4706 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24),
4707 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4708 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 3),
4709 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3),
4712 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4713 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565),
4714 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4715 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
4716 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
4717 /* ATTR_BLOB(MF_MT_PALETTE, ... with 12 elements), */
4720 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4721 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555),
4722 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4723 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
4724 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
4727 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4728 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB8),
4729 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4730 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
4731 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height),
4732 /* ATTR_BLOB(MF_MT_PALETTE, ... with 904 elements), */
4735 const struct attribute_desc expect_attributes[] =
4737 ATTR_UINT32(MF_LOW_LATENCY, 0),
4738 ATTR_UINT32(MF_SA_D3D11_AWARE, 1),
4739 ATTR_UINT32(MF_SA_D3D_AWARE, 1),
4740 ATTR_UINT32(MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER, 0),
4741 /* more attributes from CODECAPI */
4742 {0},
4744 const struct attribute_desc input_type_desc[] =
4746 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
4747 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1, .required = TRUE),
4748 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
4749 {0},
4751 const struct attribute_desc output_type_desc[] =
4753 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
4754 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE),
4755 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
4756 {0},
4758 const struct attribute_desc expect_input_type_desc[] =
4760 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4761 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1),
4762 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4763 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4764 {0},
4766 const struct attribute_desc expect_output_type_desc[] =
4768 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4769 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
4770 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4771 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
4772 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
4773 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4774 ATTR_UINT32(MF_MT_VIDEO_NOMINAL_RANGE, 2),
4775 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4776 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4777 {0},
4779 const MFT_OUTPUT_STREAM_INFO expect_output_info =
4781 .dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_DISCARDABLE,
4782 .cbSize = 0x3600,
4783 .cbAlignment = 1,
4785 const MFT_OUTPUT_STREAM_INFO empty_output_info =
4787 .dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_DISCARDABLE,
4789 const MFT_INPUT_STREAM_INFO expect_input_info =
4791 .cbSize = 0x3600,
4792 .cbAlignment = 1,
4795 const struct attribute_desc output_sample_attributes[] =
4797 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
4798 {0},
4800 const struct buffer_desc output_buffer_desc_nv12 =
4802 .length = actual_width * actual_height * 3 / 2,
4803 .compare = compare_nv12, .dump = dump_nv12, .rect = {.right = 82, .bottom = 84},
4805 const struct sample_desc output_sample_desc_nv12 =
4807 .attributes = output_sample_attributes,
4808 .sample_time = 0, .sample_duration = 333333,
4809 .buffer_count = 1, .buffers = &output_buffer_desc_nv12,
4812 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
4813 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_WMV1};
4814 IMFSample *input_sample, *output_sample;
4815 IMFCollection *output_samples;
4816 IMFMediaType *media_type;
4817 IMFTransform *transform;
4818 const BYTE *wmvenc_data;
4819 ULONG wmvenc_data_len;
4820 DWORD output_status;
4821 ULONG i, ret, ref;
4822 HRESULT hr;
4824 hr = CoInitialize(NULL);
4825 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
4827 winetest_push_context("wmvdec");
4829 if (!has_video_processor)
4831 win_skip("Skipping inconsistent WMV decoder tests on Win7\n");
4832 goto failed;
4835 if (!check_mft_enum(MFT_CATEGORY_VIDEO_DECODER, &input_type, &output_type, class_id))
4836 goto failed;
4837 check_mft_get_info(class_id, &expect_mft_info);
4838 check_dmo_get_info(class_id, &expect_dmo_info);
4840 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
4841 &IID_IMFTransform, (void **)&transform)))
4842 goto failed;
4844 check_interface(transform, &IID_IMFTransform, TRUE);
4845 check_interface(transform, &IID_IMediaObject, TRUE);
4846 check_interface(transform, &IID_IPropertyStore, TRUE);
4847 check_interface(transform, &IID_IPropertyBag, TRUE);
4849 check_mft_optional_methods(transform, 1);
4850 check_mft_get_attributes(transform, expect_attributes, TRUE);
4851 todo_wine
4852 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
4853 todo_wine
4854 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, &empty_output_info);
4856 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
4857 todo_wine
4858 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
4860 i = -1;
4861 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
4863 winetest_push_context("in %lu", i);
4864 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
4865 check_media_type(media_type, expect_common_attributes, -1);
4866 check_media_type(media_type, expect_available_inputs[i], -1);
4867 ret = IMFMediaType_Release(media_type);
4868 ok(!ret, "Release returned %lu\n", ret);
4869 winetest_pop_context();
4871 todo_wine
4872 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
4873 todo_wine
4874 ok(i == ARRAY_SIZE(expect_available_inputs), "%lu input media types\n", i);
4876 if (hr == E_NOTIMPL)
4877 goto skip_tests;
4879 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
4880 check_mft_get_output_current_type(transform, NULL);
4882 check_mft_set_input_type_required(transform, input_type_desc);
4883 check_mft_set_input_type(transform, input_type_desc);
4884 check_mft_get_input_current_type_(transform, expect_input_type_desc, FALSE, TRUE);
4886 i = -1;
4887 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
4889 winetest_push_context("out %lu", i);
4890 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
4891 check_media_type(media_type, expect_common_attributes, -1);
4892 check_media_type(media_type, expect_output_attributes, -1);
4893 check_media_type(media_type, expect_available_outputs[i], -1);
4894 ret = IMFMediaType_Release(media_type);
4895 ok(!ret, "Release returned %lu\n", ret);
4896 winetest_pop_context();
4898 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
4899 ok(i == ARRAY_SIZE(expect_available_outputs), "%lu input media types\n", i);
4901 check_mft_set_output_type_required(transform, output_type_desc);
4902 check_mft_set_output_type(transform, output_type_desc, S_OK);
4903 check_mft_get_output_current_type_(transform, expect_output_type_desc, FALSE, TRUE);
4905 check_mft_get_input_stream_info(transform, S_OK, &expect_input_info);
4906 check_mft_get_output_stream_info(transform, S_OK, &expect_output_info);
4908 load_resource(L"wmvencdata.bin", &wmvenc_data, &wmvenc_data_len);
4910 input_sample = create_sample(wmvenc_data + sizeof(DWORD), *(DWORD *)wmvenc_data);
4911 wmvenc_data_len -= *(DWORD *)wmvenc_data + sizeof(DWORD);
4912 wmvenc_data += *(DWORD *)wmvenc_data + sizeof(DWORD);
4913 hr = IMFSample_SetSampleTime(input_sample, 0);
4914 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
4915 hr = IMFSample_SetSampleDuration(input_sample, 333333);
4916 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
4917 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
4918 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
4919 ret = IMFSample_Release(input_sample);
4920 ok(ret <= 1, "Release returned %ld\n", ret);
4922 hr = MFCreateCollection(&output_samples);
4923 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
4925 output_sample = create_sample(NULL, expect_output_info.cbSize);
4926 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
4928 winetest_push_context("%lu", i);
4929 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
4930 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
4931 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
4932 ref = IMFSample_Release(output_sample);
4933 ok(ref == 1, "Release returned %ld\n", ref);
4934 output_sample = create_sample(NULL, expect_output_info.cbSize);
4935 winetest_pop_context();
4937 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
4938 ret = IMFSample_Release(output_sample);
4939 ok(ret == 0, "Release returned %lu\n", ret);
4940 ok(i == 1, "got %lu output samples\n", i);
4942 ret = check_mf_sample_collection(output_samples, &output_sample_desc_nv12, L"nv12frame.bmp");
4943 ok(ret == 0, "got %lu%% diff\n", ret);
4944 IMFCollection_Release(output_samples);
4946 skip_tests:
4947 ret = IMFTransform_Release(transform);
4948 ok(ret == 0, "Release returned %lu\n", ret);
4950 failed:
4951 winetest_pop_context();
4952 CoUninitialize();
4955 static void test_wmv_decoder_media_object(void)
4957 const GUID *const class_id = &CLSID_CWMVDecMediaObject;
4958 const DMO_MEDIA_TYPE expected_input_types[] =
4960 {MFMediaType_Video, MEDIASUBTYPE_WMV1, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
4961 {MFMediaType_Video, MEDIASUBTYPE_WMV2, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
4962 {MFMediaType_Video, MEDIASUBTYPE_WMVA, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
4963 {MFMediaType_Video, MEDIASUBTYPE_WMVP, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
4964 {MFMediaType_Video, MEDIASUBTYPE_WVP2, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
4965 {MFMediaType_Video, MFVideoFormat_WMV_Unknown, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
4966 {MFMediaType_Video, MEDIASUBTYPE_WVC1, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
4967 {MFMediaType_Video, MEDIASUBTYPE_WMV3, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
4968 {MFMediaType_Video, MFVideoFormat_VC1S, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
4970 const VIDEOINFOHEADER expected_output_info[] =
4972 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 12, MAKEFOURCC('N', 'V', '1', '2'), 384, 0, 0, 0, 0}},
4973 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 12, MAKEFOURCC('Y', 'V', '1', '2'), 384, 0, 0, 0, 0}},
4974 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 12, MAKEFOURCC('I', 'Y', 'U', 'V'), 384, 0, 0, 0, 0}},
4975 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 12, MAKEFOURCC('I', '4', '2', '0'), 384, 0, 0, 0, 0}},
4976 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 16, MAKEFOURCC('Y', 'U', 'Y', '2'), 512, 0, 0, 0, 0}},
4977 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 16, MAKEFOURCC('U', 'Y', 'V', 'Y'), 512, 0, 0, 0, 0}},
4978 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 16, MAKEFOURCC('Y', 'V', 'Y', 'U'), 512, 0, 0, 0, 0}},
4979 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 12, MAKEFOURCC('N', 'V', '1', '1'), 384, 0, 0, 0, 0}},
4980 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 32, BI_RGB, 1024, 0, 0, 0, 0}},
4981 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 24, BI_RGB, 768, 0, 0, 0, 0}},
4982 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 16, BI_BITFIELDS, 512, 0, 0, 0, 0}},
4983 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 16, BI_RGB, 512, 0, 0, 0, 0}},
4984 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 8, BI_RGB, 256, 0, 0, 226, 226}},
4986 const DMO_MEDIA_TYPE expected_output_types[] =
4988 {MFMediaType_Video, MEDIASUBTYPE_NV12, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[0]},
4989 {MFMediaType_Video, MEDIASUBTYPE_YV12, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[1]},
4990 {MFMediaType_Video, MEDIASUBTYPE_IYUV, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[2]},
4991 {MFMediaType_Video, MEDIASUBTYPE_I420, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[3]},
4992 {MFMediaType_Video, MEDIASUBTYPE_YUY2, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[4]},
4993 {MFMediaType_Video, MEDIASUBTYPE_UYVY, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[5]},
4994 {MFMediaType_Video, MEDIASUBTYPE_YVYU, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[6]},
4995 {MFMediaType_Video, MEDIASUBTYPE_NV11, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[7]},
4996 {MFMediaType_Video, MEDIASUBTYPE_RGB32, TRUE, FALSE, 1024, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[8]},
4997 {MFMediaType_Video, MEDIASUBTYPE_RGB24, TRUE, FALSE, 768, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[9]},
4998 {MFMediaType_Video, MEDIASUBTYPE_RGB565, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 100, (BYTE *)&expected_output_info[10]},
4999 {MFMediaType_Video, MEDIASUBTYPE_RGB555, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[11]},
5000 {MFMediaType_Video, MEDIASUBTYPE_RGB8, TRUE, FALSE, 256, FORMAT_VideoInfo, NULL, 1112, (BYTE *)&expected_output_info[12]},
5002 const POINT test_size[] = {{16, 16}, {96, 96}, {320, 240}};
5003 DWORD in_count, out_count, size, expected_size, alignment;
5004 DMO_MEDIA_TYPE media_type, *type;
5005 IMediaObject *media_object;
5006 char buffer[1024];
5007 ULONG ret, i, j;
5008 HRESULT hr;
5010 winetest_push_context("wmvdec");
5012 if (!has_video_processor)
5014 win_skip("Skipping inconsistent WMV decoder media object tests on Win7.\n");
5015 winetest_pop_context();
5016 return;
5019 type = (DMO_MEDIA_TYPE *)buffer;
5021 hr = CoInitialize(NULL);
5022 ok(hr == S_OK, "CoInitialize failed, hr %#lx.\n", hr);
5024 hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER, &IID_IMediaObject, (void **)&media_object);
5025 ok(hr == S_OK, "CoCreateInstance returned %#lx.\n", hr);
5027 /* Test GetStreamCount. */
5028 in_count = out_count = 0xdeadbeef;
5029 hr = IMediaObject_GetStreamCount(media_object, &in_count, &out_count);
5030 ok(hr == S_OK, "GetStreamCount returned %#lx.\n", hr);
5031 ok(in_count == 1, "Got unexpected in_count %lu.\n", in_count);
5032 ok(out_count == 1, "Got unexpected in_count %lu.\n", out_count);
5034 /* Test GetStreamCount with invalid arguments. */
5035 in_count = out_count = 0xdeadbeef;
5036 hr = IMediaObject_GetStreamCount(media_object, NULL, &out_count);
5037 ok(hr == E_POINTER, "GetStreamCount returned %#lx.\n", hr);
5038 ok(out_count == 0xdeadbeef, "Got unexpected out_count %lu.\n", out_count);
5039 hr = IMediaObject_GetStreamCount(media_object, &in_count, NULL);
5040 ok(hr == E_POINTER, "GetStreamCount returned %#lx.\n", hr);
5041 ok(in_count == 0xdeadbeef, "Got unexpected in_count %lu.\n", in_count);
5043 /* Test GetInputType. */
5044 check_dmo_get_input_type(media_object, expected_input_types, ARRAY_SIZE(expected_input_types));
5046 /* Test SetInputType. */
5047 for (i = 0; i < ARRAY_SIZE(expected_input_types); ++i)
5049 const GUID *subtype = &expected_input_types[i].subtype;
5050 if (IsEqualGUID(subtype, &MEDIASUBTYPE_WMV2)
5051 || IsEqualGUID(subtype, &MEDIASUBTYPE_WMVA)
5052 || IsEqualGUID(subtype, &MEDIASUBTYPE_WVP2)
5053 || IsEqualGUID(subtype, &MEDIASUBTYPE_WVC1)
5054 || IsEqualGUID(subtype, &MFVideoFormat_VC1S))
5056 skip("Skipping SetInputType tests for video subtype %s.\n", debugstr_guid(subtype));
5057 continue;
5060 winetest_push_context("in %lu", i);
5061 check_dmo_set_input_type(media_object, subtype);
5062 winetest_pop_context();
5065 /* Test GetOutputType without setting input type. */
5066 hr = IMediaObject_SetInputType(media_object, 0, NULL, DMO_SET_TYPEF_CLEAR);
5067 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
5068 hr = IMediaObject_GetOutputType(media_object, 0, 0, &media_type);
5069 ok(hr == DMO_E_TYPE_NOT_SET, "GetOutputType returned %#lx.\n", hr);
5071 /* Test GetOutputType after setting input type. */
5072 init_dmo_media_type_video(type, &expected_input_types[0].subtype, 16, 16);
5073 hr = IMediaObject_SetInputType(media_object, 0, type, 0);
5074 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
5075 check_dmo_get_output_type(media_object, expected_output_types, ARRAY_SIZE(expected_output_types));
5077 /* Test SetOutputType without setting input type. */
5078 hr = IMediaObject_SetInputType(media_object, 0, NULL, DMO_SET_TYPEF_CLEAR);
5079 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
5080 hr = IMediaObject_SetOutputType(media_object, 0, &media_type, 0);
5081 ok(hr == DMO_E_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr);
5083 /* Test SetOutputType after setting input type. */
5084 init_dmo_media_type_video(type, &expected_input_types[0].subtype, 16, 16);
5085 hr = IMediaObject_SetInputType(media_object, 0, type, 0);
5086 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
5087 check_dmo_set_output_type(media_object, &MEDIASUBTYPE_RGB24);
5089 /* Test GetOutputSizeInfo. */
5090 hr = IMediaObject_SetOutputType(media_object, 0, NULL, DMO_SET_TYPEF_CLEAR);
5091 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
5092 hr = IMediaObject_GetOutputSizeInfo(media_object, 0, &size, &alignment);
5093 ok(hr == DMO_E_TYPE_NOT_SET, "GetOutputSizeInfo returned %#lx.\n", hr);
5095 for (i = 0; i < ARRAY_SIZE(expected_output_types); ++i)
5097 const GUID *subtype = &expected_output_types[i].subtype;
5098 if (IsEqualGUID(subtype, &MEDIASUBTYPE_RGB565)
5099 || IsEqualGUID(subtype, &MEDIASUBTYPE_RGB8))
5101 skip("Skipping GetOutputSizeInfo tests for video subtype %s.\n", debugstr_guid(subtype));
5102 continue;
5105 winetest_push_context("out %lu", i);
5106 for (j = 0; j < ARRAY_SIZE(test_size); ++j)
5108 init_dmo_media_type_video(type, &expected_output_types[i].subtype, test_size[j].x, test_size[j].y);
5109 hr = IMediaObject_SetOutputType(media_object, 0, type, 0);
5110 todo_wine_if(IsEqualGUID(subtype, &MEDIASUBTYPE_NV11)
5111 || IsEqualGUID(subtype, &MEDIASUBTYPE_IYUV))
5112 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
5113 if (hr != S_OK)
5114 continue;
5116 size = 0xdeadbeef;
5117 alignment = 0xdeadbeef;
5118 hr = MFCalculateImageSize(subtype, test_size[j].x, test_size[j].y, (UINT32 *)&expected_size);
5119 ok(hr == S_OK, "MFCalculateImageSize returned %#lx.\n", hr);
5121 hr = IMediaObject_GetOutputSizeInfo(media_object, 0, &size, &alignment);
5122 ok(hr == S_OK, "GetOutputSizeInfo returned %#lx.\n", hr);
5123 ok(size == expected_size, "Got unexpected size %lu, expected %lu.\n", size, expected_size);
5124 ok(alignment == 1, "Got unexpected alignment %lu.\n", alignment);
5126 winetest_pop_context();
5129 ret = IMediaObject_Release(media_object);
5130 ok(ret == 0, "Release returned %lu\n", ret);
5131 CoUninitialize();
5132 winetest_pop_context();
5135 static void test_color_convert(void)
5137 const GUID *const class_id = &CLSID_CColorConvertDMO;
5138 const struct transform_info expect_mft_info =
5140 .name = L"Color Converter MFT",
5141 .major_type = &MFMediaType_Video,
5142 .inputs =
5144 {.subtype = &MFVideoFormat_YV12},
5145 {.subtype = &MFVideoFormat_YUY2},
5146 {.subtype = &MFVideoFormat_UYVY},
5147 {.subtype = &MFVideoFormat_AYUV},
5148 {.subtype = &MFVideoFormat_NV12},
5149 {.subtype = &DMOVideoFormat_RGB32},
5150 {.subtype = &DMOVideoFormat_RGB565},
5151 {.subtype = &MFVideoFormat_I420},
5152 {.subtype = &MFVideoFormat_IYUV},
5153 {.subtype = &MFVideoFormat_YVYU},
5154 {.subtype = &DMOVideoFormat_RGB24},
5155 {.subtype = &DMOVideoFormat_RGB555},
5156 {.subtype = &DMOVideoFormat_RGB8},
5157 {.subtype = &MEDIASUBTYPE_V216},
5158 {.subtype = &MEDIASUBTYPE_V410},
5159 {.subtype = &MFVideoFormat_NV11},
5160 {.subtype = &MFVideoFormat_Y41P},
5161 {.subtype = &MFVideoFormat_Y41T},
5162 {.subtype = &MFVideoFormat_Y42T},
5163 {.subtype = &MFVideoFormat_YVU9},
5165 .outputs =
5167 {.subtype = &MFVideoFormat_YV12},
5168 {.subtype = &MFVideoFormat_YUY2},
5169 {.subtype = &MFVideoFormat_UYVY},
5170 {.subtype = &MFVideoFormat_AYUV},
5171 {.subtype = &MFVideoFormat_NV12},
5172 {.subtype = &DMOVideoFormat_RGB32},
5173 {.subtype = &DMOVideoFormat_RGB565},
5174 {.subtype = &MFVideoFormat_I420},
5175 {.subtype = &MFVideoFormat_IYUV},
5176 {.subtype = &MFVideoFormat_YVYU},
5177 {.subtype = &DMOVideoFormat_RGB24},
5178 {.subtype = &DMOVideoFormat_RGB555},
5179 {.subtype = &DMOVideoFormat_RGB8},
5180 {.subtype = &MEDIASUBTYPE_V216},
5181 {.subtype = &MEDIASUBTYPE_V410},
5182 {.subtype = &MFVideoFormat_NV11},
5185 const struct transform_info expect_dmo_info =
5187 .name = L"Color Converter DMO",
5188 .major_type = &MEDIATYPE_Video,
5189 .inputs =
5191 {.subtype = &MEDIASUBTYPE_YV12},
5192 {.subtype = &MEDIASUBTYPE_YUY2},
5193 {.subtype = &MEDIASUBTYPE_UYVY},
5194 {.subtype = &MEDIASUBTYPE_AYUV},
5195 {.subtype = &MEDIASUBTYPE_NV12},
5196 {.subtype = &MEDIASUBTYPE_RGB32},
5197 {.subtype = &MEDIASUBTYPE_RGB565},
5198 {.subtype = &MEDIASUBTYPE_I420},
5199 {.subtype = &MEDIASUBTYPE_IYUV},
5200 {.subtype = &MEDIASUBTYPE_YVYU},
5201 {.subtype = &MEDIASUBTYPE_RGB24},
5202 {.subtype = &MEDIASUBTYPE_RGB555},
5203 {.subtype = &MEDIASUBTYPE_RGB8},
5204 {.subtype = &MEDIASUBTYPE_V216},
5205 {.subtype = &MEDIASUBTYPE_V410},
5206 {.subtype = &MEDIASUBTYPE_NV11},
5207 {.subtype = &MEDIASUBTYPE_Y41P},
5208 {.subtype = &MEDIASUBTYPE_Y41T},
5209 {.subtype = &MEDIASUBTYPE_Y42T},
5210 {.subtype = &MEDIASUBTYPE_YVU9},
5212 .outputs =
5214 {.subtype = &MEDIASUBTYPE_YV12},
5215 {.subtype = &MEDIASUBTYPE_YUY2},
5216 {.subtype = &MEDIASUBTYPE_UYVY},
5217 {.subtype = &MEDIASUBTYPE_AYUV},
5218 {.subtype = &MEDIASUBTYPE_NV12},
5219 {.subtype = &MEDIASUBTYPE_RGB32},
5220 {.subtype = &MEDIASUBTYPE_RGB565},
5221 {.subtype = &MEDIASUBTYPE_I420},
5222 {.subtype = &MEDIASUBTYPE_IYUV},
5223 {.subtype = &MEDIASUBTYPE_YVYU},
5224 {.subtype = &MEDIASUBTYPE_RGB24},
5225 {.subtype = &MEDIASUBTYPE_RGB555},
5226 {.subtype = &MEDIASUBTYPE_RGB8},
5227 {.subtype = &MEDIASUBTYPE_V216},
5228 {.subtype = &MEDIASUBTYPE_V410},
5229 {.subtype = &MEDIASUBTYPE_NV11},
5233 static const media_type_desc expect_available_inputs[20] =
5235 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12), },
5236 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), },
5237 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY), },
5238 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_AYUV), },
5239 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), },
5240 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), },
5241 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565), },
5242 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420), },
5243 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV), },
5244 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU), },
5245 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24), },
5246 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555), },
5247 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_RGB8), },
5248 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V216), },
5249 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V410), },
5250 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11), },
5251 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y41P), },
5252 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y41T), },
5253 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y42T), },
5254 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVU9), },
5256 static const media_type_desc expect_available_outputs[16] =
5258 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12), },
5259 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), },
5260 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY), },
5261 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_AYUV), },
5262 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), },
5263 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), },
5264 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565), },
5265 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420), },
5266 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV), },
5267 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU), },
5268 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24), },
5269 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555), },
5270 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_RGB8), },
5271 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V216), },
5272 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V410), },
5273 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11), },
5275 static const media_type_desc expect_available_common =
5277 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5278 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
5279 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
5282 static const MFVideoArea actual_aperture = {.Area={82,84}};
5283 static const DWORD actual_width = 96, actual_height = 96;
5284 const struct attribute_desc input_type_desc[] =
5286 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
5287 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE),
5288 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
5289 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
5290 {0},
5292 const struct attribute_desc output_type_desc[] =
5294 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
5295 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32, .required = TRUE),
5296 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
5297 {0},
5299 const struct attribute_desc expect_input_type_desc[] =
5301 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5302 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
5303 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
5304 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
5305 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
5306 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
5307 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
5308 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
5309 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
5310 {0},
5312 const struct attribute_desc expect_output_type_desc[] =
5314 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5315 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
5316 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
5317 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 4),
5318 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 4),
5319 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
5320 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
5321 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
5322 {0},
5324 const MFT_OUTPUT_STREAM_INFO output_info =
5326 .cbSize = actual_width * actual_height * 4,
5327 .cbAlignment = 1,
5329 const MFT_INPUT_STREAM_INFO input_info =
5331 .cbSize = actual_width * actual_height * 3 / 2,
5332 .cbAlignment = 1,
5335 const struct buffer_desc output_buffer_desc =
5337 .length = actual_width * actual_height * 4,
5338 .compare = compare_rgb32, .dump = dump_rgb32, .rect = {.right = 82, .bottom = 84},
5340 const struct attribute_desc output_sample_attributes[] =
5342 ATTR_UINT32(MFSampleExtension_CleanPoint, 0, .todo = TRUE),
5343 {0},
5345 const struct sample_desc output_sample_desc =
5347 .attributes = output_sample_attributes,
5348 .sample_time = 0, .sample_duration = 10000000,
5349 .buffer_count = 1, .buffers = &output_buffer_desc,
5352 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
5353 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_I420};
5354 IMFSample *input_sample, *output_sample;
5355 IMFCollection *output_samples;
5356 DWORD length, output_status;
5357 const BYTE *nv12frame_data;
5358 ULONG nv12frame_data_len;
5359 IMFMediaType *media_type;
5360 IMFTransform *transform;
5361 ULONG i, ret, ref;
5362 HRESULT hr;
5364 hr = CoInitialize(NULL);
5365 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
5367 winetest_push_context("colorconv");
5369 if (!check_mft_enum(MFT_CATEGORY_VIDEO_EFFECT, &input_type, &output_type, class_id))
5370 goto failed;
5371 check_mft_get_info(class_id, &expect_mft_info);
5372 check_dmo_get_info(class_id, &expect_dmo_info);
5374 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
5375 &IID_IMFTransform, (void **)&transform)))
5376 goto failed;
5378 check_interface(transform, &IID_IMFTransform, TRUE);
5379 check_interface(transform, &IID_IMediaObject, TRUE);
5380 check_interface(transform, &IID_IPropertyStore, TRUE);
5381 todo_wine
5382 check_interface(transform, &IID_IPropertyBag, FALSE);
5383 todo_wine
5384 check_interface(transform, &IID_IMFRealTimeClient, TRUE);
5385 /* check_interface(transform, &IID_IWMColorConvProps, TRUE); */
5387 check_mft_optional_methods(transform, 1);
5388 check_mft_get_attributes(transform, NULL, FALSE);
5389 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
5390 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
5392 i = -1;
5393 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
5395 winetest_push_context("out %lu", i);
5396 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
5397 check_media_type(media_type, expect_available_common, -1);
5398 check_media_type(media_type, expect_available_outputs[i], -1);
5399 ret = IMFMediaType_Release(media_type);
5400 ok(ret == 0, "Release returned %lu\n", ret);
5401 winetest_pop_context();
5403 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
5404 ok(i == 16, "%lu output media types\n", i);
5406 i = -1;
5407 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
5409 winetest_push_context("in %lu", i);
5410 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
5411 check_media_type(media_type, expect_available_common, -1);
5412 check_media_type(media_type, expect_available_inputs[i], -1);
5413 ret = IMFMediaType_Release(media_type);
5414 ok(ret == 0, "Release returned %lu\n", ret);
5415 winetest_pop_context();
5417 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
5418 ok(i == 20, "%lu input media types\n", i);
5420 check_mft_set_output_type_required(transform, output_type_desc);
5421 check_mft_set_output_type(transform, output_type_desc, S_OK);
5422 check_mft_get_output_current_type_(transform, expect_output_type_desc, FALSE, TRUE);
5424 check_mft_set_input_type_required(transform, input_type_desc);
5425 check_mft_set_input_type(transform, input_type_desc);
5426 check_mft_get_input_current_type_(transform, expect_input_type_desc, FALSE, TRUE);
5428 check_mft_get_input_stream_info(transform, S_OK, &input_info);
5429 check_mft_get_output_stream_info(transform, S_OK, &output_info);
5431 load_resource(L"nv12frame.bmp", &nv12frame_data, &nv12frame_data_len);
5432 /* skip BMP header and RGB data from the dump */
5433 length = *(DWORD *)(nv12frame_data + 2);
5434 nv12frame_data_len = nv12frame_data_len - length;
5435 nv12frame_data = nv12frame_data + length;
5436 ok(nv12frame_data_len == 13824, "got length %lu\n", nv12frame_data_len);
5438 input_sample = create_sample(nv12frame_data, nv12frame_data_len);
5439 hr = IMFSample_SetSampleTime(input_sample, 0);
5440 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
5441 hr = IMFSample_SetSampleDuration(input_sample, 10000000);
5442 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
5443 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
5444 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
5445 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
5446 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
5447 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
5448 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
5449 ret = IMFSample_Release(input_sample);
5450 ok(ret <= 1, "Release returned %ld\n", ret);
5452 hr = MFCreateCollection(&output_samples);
5453 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
5455 output_sample = create_sample(NULL, output_info.cbSize);
5456 hr = check_mft_process_output(transform, output_sample, &output_status);
5457 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
5458 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
5459 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
5460 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
5461 ref = IMFSample_Release(output_sample);
5462 ok(ref == 1, "Release returned %ld\n", ref);
5464 ret = check_mf_sample_collection(output_samples, &output_sample_desc, L"rgb32frame.bmp");
5465 ok(ret <= 4 /* small and harmless diff in Wine vs Windows */, "got %lu%% diff\n", ret);
5466 IMFCollection_Release(output_samples);
5468 output_sample = create_sample(NULL, output_info.cbSize);
5469 hr = check_mft_process_output(transform, output_sample, &output_status);
5470 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
5471 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
5472 hr = IMFSample_GetTotalLength(output_sample, &length);
5473 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
5474 ok(length == 0, "got length %lu\n", length);
5475 ret = IMFSample_Release(output_sample);
5476 ok(ret == 0, "Release returned %lu\n", ret);
5478 ret = IMFTransform_Release(transform);
5479 ok(ret == 0, "Release returned %ld\n", ret);
5481 failed:
5482 winetest_pop_context();
5483 CoUninitialize();
5486 static void test_video_processor(void)
5488 const GUID *const class_id = &CLSID_VideoProcessorMFT;
5489 const struct transform_info expect_mft_info =
5491 .name = L"Microsoft Video Processor MFT",
5492 .major_type = &MFMediaType_Video,
5493 .inputs =
5495 {.subtype = &MFVideoFormat_IYUV},
5496 {.subtype = &MFVideoFormat_YV12},
5497 {.subtype = &MFVideoFormat_NV12},
5498 {.subtype = &MFVideoFormat_YUY2},
5499 {.subtype = &MFVideoFormat_ARGB32},
5500 {.subtype = &MFVideoFormat_RGB32},
5501 {.subtype = &MFVideoFormat_NV11},
5502 {.subtype = &MFVideoFormat_AYUV},
5503 {.subtype = &MFVideoFormat_UYVY},
5504 {.subtype = &MEDIASUBTYPE_P208},
5505 {.subtype = &MFVideoFormat_RGB24},
5506 {.subtype = &MFVideoFormat_RGB555},
5507 {.subtype = &MFVideoFormat_RGB565},
5508 {.subtype = &MFVideoFormat_RGB8},
5509 {.subtype = &MFVideoFormat_I420},
5510 {.subtype = &MFVideoFormat_Y216},
5511 {.subtype = &MFVideoFormat_v410},
5512 {.subtype = &MFVideoFormat_Y41P},
5513 {.subtype = &MFVideoFormat_Y41T},
5514 {.subtype = &MFVideoFormat_Y42T},
5515 {.subtype = &MFVideoFormat_YVYU},
5516 {.subtype = &MFVideoFormat_420O},
5518 .outputs =
5520 {.subtype = &MFVideoFormat_IYUV},
5521 {.subtype = &MFVideoFormat_YV12},
5522 {.subtype = &MFVideoFormat_NV12},
5523 {.subtype = &MFVideoFormat_YUY2},
5524 {.subtype = &MFVideoFormat_ARGB32},
5525 {.subtype = &MFVideoFormat_RGB32},
5526 {.subtype = &MFVideoFormat_NV11},
5527 {.subtype = &MFVideoFormat_AYUV},
5528 {.subtype = &MFVideoFormat_UYVY},
5529 {.subtype = &MEDIASUBTYPE_P208},
5530 {.subtype = &MFVideoFormat_RGB24},
5531 {.subtype = &MFVideoFormat_RGB555},
5532 {.subtype = &MFVideoFormat_RGB565},
5533 {.subtype = &MFVideoFormat_RGB8},
5534 {.subtype = &MFVideoFormat_I420},
5535 {.subtype = &MFVideoFormat_Y216},
5536 {.subtype = &MFVideoFormat_v410},
5537 {.subtype = &MFVideoFormat_Y41P},
5538 {.subtype = &MFVideoFormat_Y41T},
5539 {.subtype = &MFVideoFormat_Y42T},
5540 {.subtype = &MFVideoFormat_YVYU},
5543 const GUID expect_available_inputs_w8[] =
5545 MFVideoFormat_IYUV,
5546 MFVideoFormat_YV12,
5547 MFVideoFormat_NV12,
5548 MFVideoFormat_420O,
5549 MFVideoFormat_UYVY,
5550 MFVideoFormat_YUY2,
5551 MFVideoFormat_P208,
5552 MFVideoFormat_NV11,
5553 MFVideoFormat_AYUV,
5554 MFVideoFormat_ARGB32,
5555 MFVideoFormat_RGB32,
5556 MFVideoFormat_RGB24,
5557 MFVideoFormat_I420,
5558 MFVideoFormat_YVYU,
5559 MFVideoFormat_RGB555,
5560 MFVideoFormat_RGB565,
5561 MFVideoFormat_RGB8,
5562 MFVideoFormat_Y216,
5563 MFVideoFormat_v410,
5564 MFVideoFormat_Y41P,
5565 MFVideoFormat_Y41T,
5566 MFVideoFormat_Y42T,
5568 const GUID expect_available_inputs_w10[] =
5570 MFVideoFormat_L8,
5571 MFVideoFormat_L16,
5572 MFAudioFormat_MPEG,
5573 MFVideoFormat_IYUV,
5574 MFVideoFormat_YV12,
5575 MFVideoFormat_NV12,
5576 MFVideoFormat_420O,
5577 MFVideoFormat_P010,
5578 MFVideoFormat_P016,
5579 MFVideoFormat_UYVY,
5580 MFVideoFormat_YUY2,
5581 MFVideoFormat_P208,
5582 MFVideoFormat_NV11,
5583 MFVideoFormat_AYUV,
5584 MFVideoFormat_ARGB32,
5585 MFVideoFormat_ABGR32,
5586 MFVideoFormat_RGB32,
5587 MFVideoFormat_A2R10G10B10,
5588 MFVideoFormat_A16B16G16R16F,
5589 MFVideoFormat_RGB24,
5590 MFVideoFormat_I420,
5591 MFVideoFormat_YVYU,
5592 MFVideoFormat_RGB555,
5593 MFVideoFormat_RGB565,
5594 MFVideoFormat_RGB8,
5595 MFVideoFormat_Y216,
5596 MFVideoFormat_v410,
5597 MFVideoFormat_Y41P,
5598 MFVideoFormat_Y41T,
5599 MFVideoFormat_Y42T,
5601 const GUID expect_available_outputs[] =
5603 MFVideoFormat_A2R10G10B10, /* enumerated with MFVideoFormat_P010 input */
5604 MFVideoFormat_P010, /* enumerated with MFVideoFormat_A2R10G10B10 input */
5605 MFVideoFormat_YUY2,
5606 MFVideoFormat_IYUV,
5607 MFVideoFormat_I420,
5608 MFVideoFormat_NV12,
5609 MFVideoFormat_RGB24,
5610 MFVideoFormat_ARGB32,
5611 MFVideoFormat_RGB32,
5612 MFVideoFormat_YV12,
5613 MFVideoFormat_Y216, /* enumerated with some input formats */
5614 MFVideoFormat_UYVY, /* enumerated with some input formats */
5615 MFVideoFormat_YVYU, /* enumerated with some input formats */
5616 MFVideoFormat_AYUV,
5617 MFVideoFormat_RGB555,
5618 MFVideoFormat_RGB565,
5619 MFVideoFormat_AYUV, /* some inputs enumerate MFVideoFormat_AYUV after RGB565 */
5620 MFVideoFormat_NV12, /* P010 enumerates NV12 after (A)RGB32 formats */
5621 MFVideoFormat_A16B16G16R16F, /* enumerated with MFVideoFormat_P010 input */
5623 static const media_type_desc expect_available_common =
5625 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5627 static const struct attribute_desc expect_transform_attributes[] =
5629 ATTR_UINT32(MFT_SUPPORT_3DVIDEO, 1, .todo = TRUE),
5630 /* ATTR_UINT32(MF_SA_D3D_AWARE, 1), only on W7 */
5631 {0},
5634 static const MFVideoArea actual_aperture = {.Area={82,84}};
5635 static const DWORD actual_width = 96, actual_height = 96;
5636 const struct attribute_desc input_type_desc[] =
5638 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
5639 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE),
5640 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
5641 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
5642 {0},
5644 const struct attribute_desc output_type_desc[] =
5646 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
5647 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32, .required = TRUE),
5648 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
5649 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
5650 {0},
5652 const MFT_OUTPUT_STREAM_INFO initial_output_info = {0};
5653 const MFT_INPUT_STREAM_INFO initial_input_info = {0};
5654 MFT_OUTPUT_STREAM_INFO output_info = {0};
5655 MFT_INPUT_STREAM_INFO input_info = {0};
5657 const struct buffer_desc output_buffer_desc =
5659 .length = actual_width * actual_height * 4,
5660 .compare = compare_rgb32, .dump = dump_rgb32, .rect = {.top = 12, .right = 82, .bottom = 96},
5662 const struct attribute_desc output_sample_attributes[] =
5664 ATTR_UINT32(MFSampleExtension_CleanPoint, 1, .todo = TRUE),
5665 {0},
5667 const struct sample_desc output_sample_desc =
5669 .attributes = output_sample_attributes,
5670 .sample_time = 0, .sample_duration = 10000000,
5671 .buffer_count = 1, .buffers = &output_buffer_desc,
5674 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
5675 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_I420};
5676 DWORD i, j, k, flags, length, output_status;
5677 IMFSample *input_sample, *output_sample;
5678 IMFMediaType *media_type, *media_type2;
5679 const GUID *expect_available_inputs;
5680 IMFCollection *output_samples;
5681 const BYTE *nv12frame_data;
5682 ULONG nv12frame_data_len;
5683 IMFTransform *transform;
5684 IMFMediaBuffer *buffer;
5685 UINT32 count;
5686 HRESULT hr;
5687 ULONG ret;
5688 GUID guid;
5689 LONG ref;
5691 hr = CoInitialize(NULL);
5692 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
5694 winetest_push_context("videoproc");
5696 if (!check_mft_enum(MFT_CATEGORY_VIDEO_PROCESSOR, &input_type, &output_type, class_id))
5697 goto failed;
5698 check_mft_get_info(class_id, &expect_mft_info);
5700 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
5701 &IID_IMFTransform, (void **)&transform)))
5702 goto failed;
5704 todo_wine
5705 check_interface(transform, &IID_IMFVideoProcessorControl, TRUE);
5706 todo_wine
5707 check_interface(transform, &IID_IMFRealTimeClientEx, TRUE);
5708 check_interface(transform, &IID_IMFMediaEventGenerator, FALSE);
5709 check_interface(transform, &IID_IMFShutdown, FALSE);
5711 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
5712 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5714 hr = IMFTransform_GetOutputStatus(transform, &flags);
5715 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5717 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
5718 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5720 check_mft_get_input_current_type(transform, NULL);
5721 check_mft_get_output_current_type(transform, NULL);
5723 check_mft_get_input_stream_info(transform, S_OK, &initial_input_info);
5724 check_mft_get_output_stream_info(transform, S_OK, &initial_output_info);
5726 /* Configure stream types. */
5727 for (i = 0;;++i)
5729 if (FAILED(hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type)))
5731 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
5732 break;
5735 hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type2);
5736 ok(hr == S_OK, "Failed to get available type, hr %#lx.\n", hr);
5737 ok(media_type != media_type2, "Unexpected instance.\n");
5738 ref = IMFMediaType_Release(media_type2);
5739 ok(ref == 0, "Release returned %ld\n", ref);
5741 hr = IMFMediaType_GetMajorType(media_type, &guid);
5742 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
5743 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type.\n");
5745 hr = IMFMediaType_GetCount(media_type, &count);
5746 ok(hr == S_OK, "Failed to get attributes count, hr %#lx.\n", hr);
5747 ok(count == 2, "Unexpected count %u.\n", count);
5749 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
5750 ok(hr == S_OK, "Failed to get subtype, hr %#lx.\n", hr);
5751 ok(is_supported_video_type(&guid), "Unexpected media type %s.\n", wine_dbgstr_guid(&guid));
5753 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
5754 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
5756 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
5757 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
5759 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type2);
5760 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
5762 /* FIXME: figure out if those require additional attributes or simply advertised but not supported */
5763 if (IsEqualGUID(&guid, &MFVideoFormat_L8) || IsEqualGUID(&guid, &MFVideoFormat_L16)
5764 || IsEqualGUID(&guid, &MFVideoFormat_D16) || IsEqualGUID(&guid, &MFVideoFormat_420O)
5765 || IsEqualGUID(&guid, &MFVideoFormat_A16B16G16R16F))
5767 ref = IMFMediaType_Release(media_type);
5768 ok(ref == 0, "Release returned %ld\n", ref);
5769 continue;
5772 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
5773 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5775 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
5776 ok(hr == S_OK, "Failed to test input type %s, hr %#lx.\n", wine_dbgstr_guid(&guid), hr);
5778 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
5779 ok(hr == S_OK, "Failed to test input type, hr %#lx.\n", hr);
5781 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type2);
5782 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
5783 ok(media_type != media_type2, "Unexpected instance.\n");
5784 IMFMediaType_Release(media_type2);
5786 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
5787 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
5788 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected input status %#lx.\n", flags);
5790 input_info.cbSize = 0;
5791 if (!IsEqualGUID(&guid, &MFVideoFormat_P208) && !IsEqualGUID(&guid, &MEDIASUBTYPE_Y41T)
5792 && !IsEqualGUID(&guid, &MEDIASUBTYPE_Y42T))
5794 hr = MFCalculateImageSize(&guid, 16, 16, (UINT32 *)&input_info.cbSize);
5795 todo_wine_if(IsEqualGUID(&guid, &MFVideoFormat_Y216)
5796 || IsEqualGUID(&guid, &MFVideoFormat_v410)
5797 || IsEqualGUID(&guid, &MFVideoFormat_Y41P))
5798 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5800 check_mft_get_input_stream_info(transform, S_OK, &input_info);
5801 check_mft_get_output_stream_info(transform, S_OK, &initial_output_info);
5803 IMFMediaType_Release(media_type);
5806 /* IYUV -> RGB32 */
5807 hr = MFCreateMediaType(&media_type);
5808 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
5810 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
5811 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5813 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_IYUV);
5814 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5816 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
5817 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5819 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
5820 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
5822 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
5823 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
5825 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
5826 ok(hr == S_OK, "Failed to set output type, hr %#lx.\n", hr);
5828 hr = MFCalculateImageSize(&MFVideoFormat_IYUV, 16, 16, (UINT32 *)&input_info.cbSize);
5829 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5830 hr = MFCalculateImageSize(&MFVideoFormat_RGB32, 16, 16, (UINT32 *)&output_info.cbSize);
5831 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5832 check_mft_get_input_stream_info(transform, S_OK, &input_info);
5833 check_mft_get_output_stream_info(transform, S_OK, &output_info);
5835 hr = MFCreateSample(&input_sample);
5836 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5838 hr = MFCreateSample(&output_sample);
5839 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
5841 hr = check_mft_process_output(transform, output_sample, &output_status);
5842 todo_wine
5843 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#lx.\n", hr);
5845 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
5846 todo_wine
5847 ok(hr == S_OK, "Failed to push a sample, hr %#lx.\n", hr);
5849 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
5850 todo_wine
5851 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#lx.\n", hr);
5853 hr = check_mft_process_output(transform, output_sample, &output_status);
5854 todo_wine
5855 ok(hr == MF_E_NO_SAMPLE_TIMESTAMP, "Unexpected hr %#lx.\n", hr);
5857 hr = IMFSample_SetSampleTime(input_sample, 0);
5858 ok(hr == S_OK, "Failed to set sample time, hr %#lx.\n", hr);
5859 hr = check_mft_process_output(transform, output_sample, &output_status);
5860 todo_wine
5861 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5863 hr = MFCreateMemoryBuffer(1024 * 1024, &buffer);
5864 ok(hr == S_OK, "Failed to create a buffer, hr %#lx.\n", hr);
5866 hr = IMFSample_AddBuffer(input_sample, buffer);
5867 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
5869 hr = IMFSample_AddBuffer(output_sample, buffer);
5870 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
5872 hr = check_mft_process_output(transform, output_sample, &output_status);
5873 todo_wine
5874 ok(hr == S_OK || broken(FAILED(hr)) /* Win8 */, "Failed to get output buffer, hr %#lx.\n", hr);
5876 if (SUCCEEDED(hr))
5878 hr = check_mft_process_output(transform, output_sample, &output_status);
5879 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#lx.\n", hr);
5882 ref = IMFTransform_Release(transform);
5883 ok(ref == 0, "Release returned %ld\n", ref);
5885 ref = IMFMediaType_Release(media_type);
5886 ok(ref == 0, "Release returned %ld\n", ref);
5887 ref = IMFSample_Release(input_sample);
5888 ok(ref == 0, "Release returned %ld\n", ref);
5889 ref = IMFSample_Release(output_sample);
5890 ok(ref == 0, "Release returned %ld\n", ref);
5891 ref = IMFMediaBuffer_Release(buffer);
5892 ok(ref == 0, "Release returned %ld\n", ref);
5895 hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)&transform);
5896 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5898 check_interface(transform, &IID_IMFTransform, TRUE);
5899 check_interface(transform, &IID_IMediaObject, FALSE);
5900 check_interface(transform, &IID_IPropertyStore, FALSE);
5901 check_interface(transform, &IID_IPropertyBag, FALSE);
5903 check_mft_optional_methods(transform, 1);
5904 check_mft_get_attributes(transform, expect_transform_attributes, TRUE);
5905 check_mft_get_input_stream_info(transform, S_OK, &initial_input_info);
5906 check_mft_get_output_stream_info(transform, S_OK, &initial_output_info);
5908 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
5909 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
5911 hr = IMFTransform_GetInputAvailableType(transform, 0, 23, &media_type);
5912 ok(hr == S_OK || hr == MF_E_NO_MORE_TYPES /* w8 */, "GetOutputAvailableType returned %#lx\n", hr);
5913 if (hr == MF_E_NO_MORE_TYPES)
5914 expect_available_inputs = expect_available_inputs_w8;
5915 else
5917 hr = IMFTransform_GetInputAvailableType(transform, 0, 27, &media_type);
5918 ok(hr == S_OK || broken(hr == MF_E_NO_MORE_TYPES) /* w1064v1507 */, "GetOutputAvailableType returned %#lx\n", hr);
5919 if (hr == MF_E_NO_MORE_TYPES)
5920 expect_available_inputs = expect_available_inputs_w10 + 3;
5921 else
5922 expect_available_inputs = expect_available_inputs_w10;
5925 i = -1;
5926 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
5928 /* FIXME: Skip exotic input types which aren't directly accepted */
5929 if (IsEqualGUID(&expect_available_inputs[i], &MFVideoFormat_L8)
5930 || IsEqualGUID(&expect_available_inputs[i], &MFVideoFormat_L16)
5931 || IsEqualGUID(&expect_available_inputs[i], &MFAudioFormat_MPEG)
5932 || IsEqualGUID(&expect_available_inputs[i], &MFVideoFormat_420O)
5933 || IsEqualGUID(&expect_available_inputs[i], &MFVideoFormat_A16B16G16R16F) /* w1064v1507 */)
5934 continue;
5936 winetest_push_context("in %lu", i);
5937 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
5938 check_media_type(media_type, expect_available_common, -1);
5940 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
5941 ok(hr == S_OK, "GetGUID returned %#lx\n", hr);
5943 /* w1064v1507 doesn't expose MFVideoFormat_ABGR32 input */
5944 if (broken(IsEqualGUID(&expect_available_inputs[i], &MFVideoFormat_ABGR32)
5945 && IsEqualGUID(&guid, &MFVideoFormat_RGB32)))
5946 expect_available_inputs++;
5948 ok(IsEqualGUID(&expect_available_inputs[i], &guid), "got subtype %s\n", debugstr_guid(&guid));
5950 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
5951 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
5953 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)actual_width << 32 | actual_height);
5954 ok(hr == S_OK, "SetUINT64 returned %#lx.\n", hr);
5955 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
5956 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
5958 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type2);
5959 ok(hr == S_OK, "GetOutputAvailableType returned %#lx.\n", hr);
5960 hr = IMFMediaType_IsEqual(media_type, media_type2, &flags);
5961 ok(hr == S_OK, "IsEqual returned %#lx.\n", hr);
5962 IMFMediaType_Release(media_type2);
5964 ret = IMFMediaType_Release(media_type);
5965 ok(ret == 1, "Release returned %lu\n", ret);
5967 j = k = 0;
5968 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++j, &media_type)))
5970 winetest_push_context("out %lu", j);
5971 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
5972 check_media_type(media_type, expect_available_common, -1);
5974 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
5975 ok(hr == S_OK, "GetGUID returned %#lx\n", hr);
5977 for (; k < ARRAY_SIZE(expect_available_outputs); k++)
5978 if (IsEqualGUID(&expect_available_outputs[k], &guid))
5979 break;
5980 ok(k < ARRAY_SIZE(expect_available_outputs), "got subtype %s\n", debugstr_guid(&guid));
5982 ret = IMFMediaType_Release(media_type);
5983 ok(ret == 0, "Release returned %lu\n", ret);
5984 winetest_pop_context();
5986 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
5988 winetest_pop_context();
5990 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
5991 ok(i == 22 || i == 30 || broken(i == 26) /* w1064v1507 */, "%lu input media types\n", i);
5993 check_mft_set_input_type_required(transform, input_type_desc);
5994 check_mft_set_input_type(transform, input_type_desc);
5995 check_mft_get_input_current_type(transform, input_type_desc);
5997 check_mft_set_output_type_required(transform, output_type_desc);
5998 check_mft_set_output_type(transform, output_type_desc, S_OK);
5999 check_mft_get_output_current_type(transform, output_type_desc);
6001 input_info.cbSize = actual_width * actual_height * 3 / 2;
6002 output_info.cbSize = actual_width * actual_height * 4;
6003 check_mft_get_input_stream_info(transform, S_OK, &input_info);
6004 check_mft_get_output_stream_info(transform, S_OK, &output_info);
6006 load_resource(L"nv12frame.bmp", &nv12frame_data, &nv12frame_data_len);
6007 /* skip BMP header and RGB data from the dump */
6008 length = *(DWORD *)(nv12frame_data + 2);
6009 nv12frame_data_len = nv12frame_data_len - length;
6010 nv12frame_data = nv12frame_data + length;
6011 ok(nv12frame_data_len == 13824, "got length %lu\n", nv12frame_data_len);
6013 input_sample = create_sample(nv12frame_data, nv12frame_data_len);
6014 hr = IMFSample_SetSampleTime(input_sample, 0);
6015 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
6016 hr = IMFSample_SetSampleDuration(input_sample, 10000000);
6017 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
6018 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
6019 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6020 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
6021 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
6022 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
6023 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
6024 ret = IMFSample_Release(input_sample);
6025 ok(ret <= 1, "Release returned %ld\n", ret);
6027 hr = MFCreateCollection(&output_samples);
6028 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
6030 output_sample = create_sample(NULL, output_info.cbSize);
6031 hr = check_mft_process_output(transform, output_sample, &output_status);
6032 ok(hr == S_OK || broken(hr == MF_E_SHUTDOWN) /* w8 */, "ProcessOutput returned %#lx\n", hr);
6033 if (hr != S_OK)
6035 win_skip("ProcessOutput returned MF_E_SHUTDOWN, skipping tests.\n");
6036 goto skip_output;
6038 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
6040 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
6041 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
6042 ref = IMFSample_Release(output_sample);
6043 ok(ref == 1, "Release returned %ld\n", ref);
6045 ret = check_mf_sample_collection(output_samples, &output_sample_desc, L"rgb32frame-vp.bmp");
6046 todo_wine
6047 ok(ret == 0 || broken(ret == 25) /* w1064v1507 / w1064v1809 incorrectly rescale */, "got %lu%% diff\n", ret);
6048 IMFCollection_Release(output_samples);
6050 output_sample = create_sample(NULL, output_info.cbSize);
6051 hr = check_mft_process_output(transform, output_sample, &output_status);
6052 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6053 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
6054 hr = IMFSample_GetTotalLength(output_sample, &length);
6055 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
6056 ok(length == 0, "got length %lu\n", length);
6058 skip_output:
6059 ret = IMFSample_Release(output_sample);
6060 ok(ret == 0, "Release returned %lu\n", ret);
6062 ret = IMFTransform_Release(transform);
6063 ok(ret == 0, "Release returned %ld\n", ret);
6065 failed:
6066 winetest_pop_context();
6067 CoUninitialize();
6070 static void test_mp3_decoder(void)
6072 const GUID *const class_id = &CLSID_CMP3DecMediaObject;
6073 const struct transform_info expect_mft_info =
6075 .name = L"MP3 Decoder MFT",
6076 .major_type = &MFMediaType_Audio,
6077 .inputs =
6079 {.subtype = &MFAudioFormat_MP3},
6081 .outputs =
6083 {.subtype = &MFAudioFormat_PCM},
6086 const struct transform_info expect_dmo_info =
6088 .name = L"MP3 Decoder DMO",
6089 .major_type = &MEDIATYPE_Audio,
6090 .inputs =
6092 {.subtype = &MFAudioFormat_MP3},
6094 .outputs =
6096 {.subtype = &MEDIASUBTYPE_PCM},
6100 static const ULONG mp3dec_block_size = 0x1200;
6101 static const media_type_desc expect_available_inputs[] =
6104 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6105 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3),
6106 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6109 static const media_type_desc expect_available_outputs[] =
6112 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6113 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
6114 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
6115 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6116 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6117 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
6118 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
6119 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6122 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6123 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
6124 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
6125 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6126 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6127 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
6128 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
6129 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6132 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6133 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
6134 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
6135 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6136 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6137 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
6138 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2),
6139 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6142 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6143 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
6144 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
6145 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
6146 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6147 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
6148 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
6149 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6152 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6153 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
6154 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
6155 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
6156 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6157 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
6158 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2),
6159 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6162 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6163 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
6164 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
6165 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
6166 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6167 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 22050),
6168 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
6169 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6173 const struct attribute_desc input_type_desc[] =
6175 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
6176 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3, .required = TRUE),
6177 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
6178 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6179 {0},
6181 static const struct attribute_desc output_type_desc[] =
6183 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
6184 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM, .required = TRUE),
6185 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
6186 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
6187 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
6188 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2 * (16 / 8), .required = TRUE),
6189 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * (16 / 8) * 22050, .required = TRUE),
6190 {0},
6192 const struct attribute_desc expect_input_type_desc[] =
6194 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6195 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3),
6196 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6197 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6198 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
6199 {0},
6201 static const struct attribute_desc expect_output_type_desc[] =
6203 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
6204 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
6205 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
6206 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
6207 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
6208 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
6209 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 22050 * 4),
6210 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6211 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
6212 {0},
6214 const MFT_OUTPUT_STREAM_INFO output_info =
6216 .cbSize = mp3dec_block_size,
6217 .cbAlignment = 1,
6219 const MFT_INPUT_STREAM_INFO input_info =
6221 .cbAlignment = 1,
6224 const struct buffer_desc output_buffer_desc[] =
6226 {.length = 0x9c0, .compare = compare_pcm16},
6227 {.length = mp3dec_block_size, .compare = compare_pcm16},
6229 const struct attribute_desc output_sample_attributes[] =
6231 ATTR_UINT32(mft_output_sample_incomplete, 1),
6232 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
6233 {0},
6235 const struct sample_desc output_sample_desc[] =
6238 .attributes = output_sample_attributes + 0,
6239 .sample_time = 0, .sample_duration = 282993,
6240 .buffer_count = 1, .buffers = output_buffer_desc + 0,
6243 .attributes = output_sample_attributes + 0,
6244 .sample_time = 282993, .sample_duration = 522449,
6245 .buffer_count = 1, .buffers = output_buffer_desc + 1, .repeat_count = 18,
6248 .attributes = output_sample_attributes + 1, /* not MFT_OUTPUT_DATA_BUFFER_INCOMPLETE */
6249 .sample_time = 10209524, .sample_duration = 522449,
6250 .buffer_count = 1, .buffers = output_buffer_desc + 1,
6254 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_PCM};
6255 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_MP3};
6256 IMFSample *input_sample, *output_sample;
6257 IMFCollection *output_samples;
6258 DWORD length, output_status;
6259 IMFMediaType *media_type;
6260 IMFTransform *transform;
6261 const BYTE *mp3enc_data;
6262 ULONG mp3enc_data_len;
6263 ULONG i, ret, ref;
6264 HRESULT hr;
6266 hr = CoInitialize(NULL);
6267 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
6269 winetest_push_context("mp3dec");
6271 if (!check_mft_enum(MFT_CATEGORY_AUDIO_DECODER, &input_type, &output_type, class_id))
6272 goto failed;
6273 check_mft_get_info(class_id, &expect_mft_info);
6274 check_dmo_get_info(class_id, &expect_dmo_info);
6276 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
6277 &IID_IMFTransform, (void **)&transform)))
6278 goto failed;
6280 check_interface(transform, &IID_IMFTransform, TRUE);
6281 check_interface(transform, &IID_IMediaObject, TRUE);
6282 todo_wine
6283 check_interface(transform, &IID_IPropertyStore, TRUE);
6284 check_interface(transform, &IID_IPropertyBag, FALSE);
6286 check_mft_optional_methods(transform, 1);
6287 check_mft_get_attributes(transform, NULL, FALSE);
6288 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
6289 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
6291 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
6292 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
6294 i = -1;
6295 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
6297 winetest_push_context("in %lu", i);
6298 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
6299 check_media_type(media_type, expect_available_inputs[i], -1);
6300 ret = IMFMediaType_Release(media_type);
6301 ok(ret == 0, "Release returned %lu\n", ret);
6302 winetest_pop_context();
6304 todo_wine
6305 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
6306 todo_wine
6307 ok(i == ARRAY_SIZE(expect_available_inputs), "%lu input media types\n", i);
6309 /* setting output media type first doesn't work */
6310 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
6311 check_mft_get_output_current_type(transform, NULL);
6313 check_mft_set_input_type_required(transform, input_type_desc);
6314 check_mft_set_input_type(transform, input_type_desc);
6315 check_mft_get_input_current_type(transform, expect_input_type_desc);
6317 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
6318 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
6320 /* check new output media types */
6322 i = -1;
6323 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
6325 winetest_push_context("out %lu", i);
6326 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
6327 check_media_type(media_type, expect_available_outputs[i], -1);
6328 ret = IMFMediaType_Release(media_type);
6329 ok(ret == 0, "Release returned %lu\n", ret);
6330 winetest_pop_context();
6332 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
6333 ok(i == ARRAY_SIZE(expect_available_outputs), "%lu output media types\n", i);
6335 check_mft_set_output_type_required(transform, output_type_desc);
6336 check_mft_set_output_type(transform, output_type_desc, S_OK);
6337 check_mft_get_output_current_type(transform, expect_output_type_desc);
6339 check_mft_get_input_stream_info(transform, S_OK, &input_info);
6340 check_mft_get_output_stream_info(transform, S_OK, &output_info);
6342 load_resource(L"mp3encdata.bin", &mp3enc_data, &mp3enc_data_len);
6343 ok(mp3enc_data_len == 6295, "got length %lu\n", mp3enc_data_len);
6345 input_sample = create_sample(mp3enc_data, mp3enc_data_len);
6346 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
6347 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6348 ret = IMFSample_Release(input_sample);
6349 ok(ret == 1, "Release returned %lu\n", ret);
6351 input_sample = create_sample(mp3enc_data, mp3enc_data_len);
6352 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
6353 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
6354 ret = IMFSample_Release(input_sample);
6355 ok(ret == 0, "Release returned %lu\n", ret);
6357 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
6358 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
6360 hr = MFCreateCollection(&output_samples);
6361 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
6363 /* first sample is broken */
6364 output_sample = create_sample(NULL, output_info.cbSize);
6365 hr = check_mft_process_output(transform, output_sample, &output_status);
6366 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
6367 ok(output_status == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE, "got output[0].dwStatus %#lx\n", output_status);
6368 hr = IMFSample_GetTotalLength(output_sample, &length);
6369 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
6370 ok(length == mp3dec_block_size /* Win8 */ || length == 0x9c0 /* Win10 */ || length == 0x900 /* Win7 */,
6371 "got length %lu\n", length);
6372 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
6373 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
6374 ref = IMFSample_Release(output_sample);
6375 ok(ref == 1, "Release returned %ld\n", ref);
6377 output_sample = create_sample(NULL, output_info.cbSize);
6378 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
6380 winetest_push_context("%lu", i);
6381 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
6382 ok(!(output_status & ~MFT_OUTPUT_DATA_BUFFER_INCOMPLETE), "got output[0].dwStatus %#lx\n", output_status);
6383 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
6384 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
6385 ref = IMFSample_Release(output_sample);
6386 ok(ref == 1, "Release returned %ld\n", ref);
6387 output_sample = create_sample(NULL, output_info.cbSize);
6388 winetest_pop_context();
6390 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6391 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
6392 ret = IMFSample_Release(output_sample);
6393 ok(ret == 0, "Release returned %lu\n", ret);
6394 ok(i == 20 || broken(i == 41) /* Win7 */, "got %lu output samples\n", i);
6396 if (broken(length != 0x9c0))
6397 win_skip("Skipping MP3 decoder output sample checks on Win7 / Win8\n");
6398 else
6400 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"mp3decdata.bin");
6401 ok(ret == 0, "got %lu%% diff\n", ret);
6403 IMFCollection_Release(output_samples);
6405 output_sample = create_sample(NULL, mp3dec_block_size);
6406 hr = check_mft_process_output(transform, output_sample, &output_status);
6407 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6408 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
6409 hr = IMFSample_GetTotalLength(output_sample, &length);
6410 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
6411 ok(length == 0, "got length %lu\n", length);
6412 ret = IMFSample_Release(output_sample);
6413 ok(ret == 0, "Release returned %lu\n", ret);
6415 ret = IMFTransform_Release(transform);
6416 ok(ret == 0, "Release returned %lu\n", ret);
6418 failed:
6419 winetest_pop_context();
6420 CoUninitialize();
6423 START_TEST(transform)
6425 init_functions();
6427 test_sample_copier();
6428 test_sample_copier_output_processing();
6429 test_aac_encoder();
6430 test_aac_decoder();
6431 test_wma_encoder();
6432 test_wma_decoder();
6433 test_h264_decoder();
6434 test_wmv_encoder();
6435 test_wmv_decoder();
6436 test_wmv_decoder_media_object();
6437 test_audio_convert();
6438 test_color_convert();
6439 test_video_processor();
6440 test_mp3_decoder();