winegstreamer: Implement MFT_MESSAGE_COMMAND_DRAIN for the H264 decoder.
[wine.git] / dlls / mf / tests / transform.c
blob27dd4ad17c2e462eb5f8a23e1587483ce0cf20eb
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"
38 #include "vfw.h"
40 #include "mf_test.h"
42 #include "wine/test.h"
44 #include "initguid.h"
46 #include "d3d11_4.h"
48 DEFINE_GUID(DMOVideoFormat_RGB24,D3DFMT_R8G8B8,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
49 DEFINE_GUID(DMOVideoFormat_RGB32,D3DFMT_X8R8G8B8,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
50 DEFINE_GUID(DMOVideoFormat_RGB555,D3DFMT_X1R5G5B5,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
51 DEFINE_GUID(DMOVideoFormat_RGB565,D3DFMT_R5G6B5,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
52 DEFINE_GUID(DMOVideoFormat_RGB8,D3DFMT_P8,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf,0x0b,0xa7,0x70);
53 DEFINE_GUID(MFAudioFormat_RAW_AAC1,WAVE_FORMAT_RAW_AAC1,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
54 DEFINE_GUID(MFVideoFormat_ABGR32,0x00000020,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
55 DEFINE_GUID(MFVideoFormat_P208,0x38303250,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
56 DEFINE_GUID(MFVideoFormat_VC1S,0x53314356,0x0000,0x0010,0x80,0x00,0x00,0xaa,0x00,0x38,0x9b,0x71);
57 DEFINE_GUID(MFVideoFormat_WMV_Unknown,0x7ce12ca9,0xbfbf,0x43d9,0x9d,0x00,0x82,0xb8,0xed,0x54,0x31,0x6b);
58 DEFINE_MEDIATYPE_GUID(MEDIASUBTYPE_IV50,MAKEFOURCC('I','V','5','0'));
60 DEFINE_GUID(mft_output_sample_incomplete,0xffffff,0xffff,0xffff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
62 struct media_buffer
64 IMediaBuffer IMediaBuffer_iface;
65 LONG refcount;
66 DWORD length;
67 DWORD max_length;
68 BYTE data[];
71 static inline struct media_buffer *impl_from_IMediaBuffer(IMediaBuffer *iface)
73 return CONTAINING_RECORD(iface, struct media_buffer, IMediaBuffer_iface);
76 static HRESULT WINAPI media_buffer_QueryInterface(IMediaBuffer *iface, REFIID iid, void **obj)
78 if (IsEqualIID(iid, &IID_IMediaBuffer)
79 || IsEqualIID(iid, &IID_IUnknown))
81 *obj = iface;
82 return S_OK;
84 return E_NOINTERFACE;
87 static ULONG WINAPI media_buffer_AddRef(IMediaBuffer *iface)
89 struct media_buffer *buffer = impl_from_IMediaBuffer(iface);
90 return InterlockedIncrement(&buffer->refcount);
93 static ULONG WINAPI media_buffer_Release(IMediaBuffer *iface)
95 struct media_buffer *buffer = impl_from_IMediaBuffer(iface);
96 ULONG ref = InterlockedDecrement(&buffer->refcount);
97 if (!ref)
98 free(buffer);
99 return ref;
102 static HRESULT WINAPI media_buffer_SetLength(IMediaBuffer *iface, DWORD length)
104 struct media_buffer *buffer = impl_from_IMediaBuffer(iface);
105 if (length > buffer->max_length)
106 return E_INVALIDARG;
107 buffer->length = length;
108 return S_OK;
111 static HRESULT WINAPI media_buffer_GetMaxLength(IMediaBuffer *iface, DWORD *max_length)
113 struct media_buffer *buffer = impl_from_IMediaBuffer(iface);
114 if (!max_length)
115 return E_POINTER;
116 *max_length = buffer->max_length;
117 return S_OK;
120 static HRESULT WINAPI media_buffer_GetBufferAndLength(IMediaBuffer *iface, BYTE **data, DWORD *length)
122 struct media_buffer *buffer = impl_from_IMediaBuffer(iface);
123 if (!data || ! length)
124 return E_POINTER;
125 *data = buffer->data;
126 *length = buffer->length;
127 return S_OK;
130 static IMediaBufferVtbl media_buffer_vtbl = {
131 media_buffer_QueryInterface,
132 media_buffer_AddRef,
133 media_buffer_Release,
134 media_buffer_SetLength,
135 media_buffer_GetMaxLength,
136 media_buffer_GetBufferAndLength,
139 HRESULT media_buffer_create(DWORD max_length, struct media_buffer **ret)
141 struct media_buffer *buffer;
143 if (!(buffer = calloc(1, offsetof(struct media_buffer, data[max_length]))))
144 return E_OUTOFMEMORY;
145 buffer->IMediaBuffer_iface.lpVtbl = &media_buffer_vtbl;
146 buffer->refcount = 1;
147 buffer->length = 0;
148 buffer->max_length = max_length;
149 *ret = buffer;
150 return S_OK;
153 static BOOL is_compressed_subtype(const GUID *subtype)
155 if (IsEqualGUID(subtype, &MEDIASUBTYPE_WMV1)
156 || IsEqualGUID(subtype, &MEDIASUBTYPE_WMV2)
157 || IsEqualGUID(subtype, &MEDIASUBTYPE_WMVA)
158 || IsEqualGUID(subtype, &MEDIASUBTYPE_WMVP)
159 || IsEqualGUID(subtype, &MEDIASUBTYPE_WVP2)
160 || IsEqualGUID(subtype, &MFVideoFormat_WMV_Unknown)
161 || IsEqualGUID(subtype, &MEDIASUBTYPE_WVC1)
162 || IsEqualGUID(subtype, &MEDIASUBTYPE_WMV3)
163 || IsEqualGUID(subtype, &MFVideoFormat_VC1S))
164 return TRUE;
165 return FALSE;
168 static DWORD subtype_to_compression(const GUID *subtype)
170 if (IsEqualGUID(subtype, &MEDIASUBTYPE_RGB32)
171 || IsEqualGUID(subtype, &MEDIASUBTYPE_RGB24)
172 || IsEqualGUID(subtype, &MEDIASUBTYPE_RGB555)
173 || IsEqualGUID(subtype, &MEDIASUBTYPE_RGB8))
174 return BI_RGB;
175 else if (IsEqualGUID(subtype, &MEDIASUBTYPE_RGB565))
176 return BI_BITFIELDS;
177 else
178 return subtype->Data1;
181 static DWORD subtype_to_bpp(const GUID *subtype)
183 if (IsEqualGUID(subtype, &MEDIASUBTYPE_RGB8))
184 return 8;
185 else if (IsEqualGUID(subtype, &MEDIASUBTYPE_NV12)
186 || IsEqualGUID(subtype, &MEDIASUBTYPE_YV12)
187 || IsEqualGUID(subtype, &MEDIASUBTYPE_IYUV)
188 || IsEqualGUID(subtype, &MEDIASUBTYPE_I420)
189 || IsEqualGUID(subtype, &MEDIASUBTYPE_NV11))
190 return 12;
191 else if (IsEqualGUID(subtype, &MEDIASUBTYPE_YUY2)
192 || IsEqualGUID(subtype, &MEDIASUBTYPE_UYVY)
193 || IsEqualGUID(subtype, &MEDIASUBTYPE_YVYU)
194 || IsEqualGUID(subtype, &MEDIASUBTYPE_RGB565)
195 || IsEqualGUID(subtype, &MEDIASUBTYPE_RGB555))
196 return 16;
197 else if (IsEqualGUID(subtype, &MEDIASUBTYPE_RGB24))
198 return 24;
199 else if (IsEqualGUID(subtype, &MEDIASUBTYPE_RGB32))
200 return 32;
201 else
202 return 0;
205 static void load_resource(const WCHAR *filename, const BYTE **data, DWORD *length)
207 HRSRC resource = FindResourceW(NULL, filename, (const WCHAR *)RT_RCDATA);
208 ok(resource != 0, "FindResourceW failed, error %lu\n", GetLastError());
209 *data = LockResource(LoadResource(GetModuleHandleW(NULL), resource));
210 *length = SizeofResource(GetModuleHandleW(NULL), resource);
213 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
214 static void _expect_ref(IUnknown* obj, ULONG expected_refcount, int line)
216 ULONG refcount;
217 IUnknown_AddRef(obj);
218 refcount = IUnknown_Release(obj);
219 ok_(__FILE__, line)(refcount == expected_refcount, "Unexpected refcount %ld, expected %ld.\n", refcount,
220 expected_refcount);
223 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
224 static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported)
226 IUnknown *iface = iface_ptr;
227 HRESULT hr, expected_hr;
228 IUnknown *unk;
230 expected_hr = supported ? S_OK : E_NOINTERFACE;
232 hr = IUnknown_QueryInterface(iface, iid, (void **)&unk);
233 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#lx, expected %#lx.\n", hr, expected_hr);
234 if (SUCCEEDED(hr))
235 IUnknown_Release(unk);
238 #define check_member_(file, line, val, exp, fmt, member) \
239 ok_ (file, line)((val).member == (exp).member, "got " #member " " fmt "\n", (val).member)
240 #define check_member(val, exp, fmt, member) check_member_(__FILE__, __LINE__, val, exp, fmt, member)
242 void check_attributes_(const char *file, int line, IMFAttributes *attributes,
243 const struct attribute_desc *desc, ULONG limit)
245 char buffer[256], *buf = buffer;
246 PROPVARIANT value;
247 int i, j, ret;
248 HRESULT hr;
250 for (i = 0; i < limit && desc[i].key; ++i)
252 hr = IMFAttributes_GetItem(attributes, desc[i].key, &value);
253 todo_wine_if(desc[i].todo)
254 ok_(file, line)(hr == S_OK, "%s missing, hr %#lx\n", debugstr_a(desc[i].name), hr);
255 if (hr != S_OK) continue;
257 switch (value.vt)
259 default: sprintf(buffer, "??"); break;
260 case VT_CLSID: sprintf(buffer, "%s", debugstr_guid(value.puuid)); break;
261 case VT_UI4: sprintf(buffer, "%lu", value.ulVal); break;
262 case VT_UI8:
263 if (desc[i].ratio)
264 sprintf(buffer, "%lu:%lu", value.uhVal.HighPart, value.uhVal.LowPart);
265 else
266 sprintf(buffer, "%I64u", value.uhVal.QuadPart);
267 break;
268 case VT_VECTOR | VT_UI1:
269 buf += sprintf(buf, "size %lu, data {", value.caub.cElems);
270 for (j = 0; j < 16 && j < value.caub.cElems; ++j)
271 buf += sprintf(buf, "0x%02x,", value.caub.pElems[j]);
272 if (value.caub.cElems > 16)
273 buf += sprintf(buf, "...}");
274 else
275 buf += sprintf(buf - (j ? 1 : 0), "}");
276 break;
279 ret = PropVariantCompareEx(&value, &desc[i].value, 0, 0);
280 todo_wine_if(desc[i].todo_value)
281 ok_(file, line)(ret == 0, "%s mismatch, type %u, value %s\n",
282 debugstr_a(desc[i].name), value.vt, buffer);
283 PropVariantClear(&value);
287 struct transform_info
289 const WCHAR *name;
290 const GUID *major_type;
291 struct
293 const GUID *subtype;
294 BOOL broken;
295 } inputs[32], input_end, outputs[32], output_end;
298 static BOOL check_mft_enum(GUID category, MFT_REGISTER_TYPE_INFO *input_type,
299 MFT_REGISTER_TYPE_INFO *output_type, const GUID *expect_class_id)
301 GUID *class_ids = NULL;
302 UINT32 count = 0, i;
303 HRESULT hr;
305 hr = MFTEnum(category, 0, input_type, output_type, NULL, &class_ids, &count);
306 if (FAILED(hr) || count == 0)
308 todo_wine
309 win_skip("MFTEnum returned %#lx, count %u, skipping tests.\n", hr, count);
310 return FALSE;
313 ok(hr == S_OK, "MFTEnum returned %#lx\n", hr);
314 for (i = 0; i < count; ++i)
315 if (IsEqualGUID(expect_class_id, class_ids + i))
316 break;
317 ok(i < count, "Failed to find transform.\n");
318 CoTaskMemFree(class_ids);
320 return i < count;
323 static void check_mft_get_info(const GUID *class_id, const struct transform_info *expect)
325 MFT_REGISTER_TYPE_INFO *input_types = NULL, *output_types = NULL;
326 UINT32 input_count = 0, output_count = 0, i;
327 WCHAR *name;
328 HRESULT hr;
330 hr = MFTGetInfo(*class_id, &name, &input_types, &input_count, &output_types, &output_count, NULL);
331 ok(hr == S_OK, "MFTEnum returned %#lx\n", hr);
332 ok(!wcscmp(name, expect->name), "got name %s\n", debugstr_w(name));
334 for (i = 0; i < input_count && expect->inputs[i].subtype; ++i)
336 ok(IsEqualGUID(&input_types[i].guidMajorType, expect->major_type),
337 "got input[%u] major %s\n", i, debugstr_guid(&input_types[i].guidMajorType));
338 ok(IsEqualGUID(&input_types[i].guidSubtype, expect->inputs[i].subtype),
339 "got input[%u] subtype %s\n", i, debugstr_guid(&input_types[i].guidSubtype));
341 for (; expect->inputs[i].subtype; ++i)
342 ok(broken(expect->inputs[i].broken), "missing input[%u] subtype %s\n",
343 i, debugstr_guid(expect->inputs[i].subtype));
344 for (; i < input_count; ++i)
345 ok(0, "extra input[%u] subtype %s\n", i, debugstr_guid(&input_types[i].guidSubtype));
347 for (i = 0; expect->outputs[i].subtype; ++i)
349 ok(IsEqualGUID(&output_types[i].guidMajorType, expect->major_type),
350 "got output[%u] major %s\n", i, debugstr_guid(&output_types[i].guidMajorType));
351 ok(IsEqualGUID(&output_types[i].guidSubtype, expect->outputs[i].subtype),
352 "got output[%u] subtype %s\n", i, debugstr_guid(&output_types[i].guidSubtype));
354 for (; expect->outputs[i].subtype; ++i)
355 ok(0, "missing output[%u] subtype %s\n", i, debugstr_guid(expect->outputs[i].subtype));
356 for (; i < output_count; ++i)
357 ok(0, "extra output[%u] subtype %s\n", i, debugstr_guid(&output_types[i].guidSubtype));
359 CoTaskMemFree(output_types);
360 CoTaskMemFree(input_types);
361 CoTaskMemFree(name);
364 static void check_dmo_get_info(const GUID *class_id, const struct transform_info *expect)
366 DWORD input_count = 0, output_count = 0;
367 DMO_PARTIAL_MEDIATYPE output[32] = {{{0}}};
368 DMO_PARTIAL_MEDIATYPE input[32] = {{{0}}};
369 WCHAR name[80];
370 HRESULT hr;
371 int i;
373 hr = DMOGetName(class_id, name);
374 ok(hr == S_OK, "DMOGetName returned %#lx\n", hr);
375 ok(!wcscmp(name, expect->name), "got name %s\n", debugstr_w(name));
377 hr = DMOGetTypes(class_id, ARRAY_SIZE(input), &input_count, input,
378 ARRAY_SIZE(output), &output_count, output);
379 ok(hr == S_OK, "DMOGetTypes returned %#lx\n", hr);
381 for (i = 0; i < input_count && expect->inputs[i].subtype; ++i)
383 ok(IsEqualGUID(&input[i].type, expect->major_type),
384 "got input[%u] major %s\n", i, debugstr_guid(&input[i].type));
385 ok(IsEqualGUID(&input[i].subtype, expect->inputs[i].subtype),
386 "got input[%u] subtype %s\n", i, debugstr_guid(&input[i].subtype));
388 for (; expect->inputs[i].subtype; ++i)
389 ok(0, "missing input[%u] subtype %s\n", i, debugstr_guid(expect->inputs[i].subtype));
390 for (; i < input_count; ++i)
391 ok(0, "extra input[%u] subtype %s\n", i, debugstr_guid(&input[i].subtype));
393 for (i = 0; expect->outputs[i].subtype; ++i)
395 ok(IsEqualGUID(&output[i].type, expect->major_type),
396 "got output[%u] major %s\n", i, debugstr_guid(&output[i].type));
397 ok(IsEqualGUID(&output[i].subtype, expect->outputs[i].subtype),
398 "got output[%u] subtype %s\n", i, debugstr_guid(&output[i].subtype));
400 for (; expect->outputs[i].subtype; ++i)
401 ok(0, "missing output[%u] subtype %s\n", i, debugstr_guid(expect->outputs[i].subtype));
402 for (; i < output_count; ++i)
403 ok(0, "extra output[%u] subtype %s\n", i, debugstr_guid(&output[i].subtype));
406 void init_media_type(IMFMediaType *mediatype, const struct attribute_desc *desc, ULONG limit)
408 HRESULT hr;
409 ULONG i;
411 hr = IMFMediaType_DeleteAllItems(mediatype);
412 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
414 for (i = 0; i < limit && desc[i].key; ++i)
416 hr = IMFMediaType_SetItem(mediatype, desc[i].key, &desc[i].value);
417 ok(hr == S_OK, "SetItem %s returned %#lx\n", debugstr_a(desc[i].name), hr);
421 static void init_dmo_media_type_video(DMO_MEDIA_TYPE *media_type,
422 const GUID *subtype, const LONG width, const LONG height)
424 VIDEOINFOHEADER *header = (VIDEOINFOHEADER *)(media_type + 1);
425 BOOL compressed = is_compressed_subtype(subtype);
426 ULONG codec_data_size = compressed ? 4 : 0;
428 memset(media_type, 0, sizeof(*media_type) + sizeof(*header) + codec_data_size);
430 header->bmiHeader.biSize = sizeof(header->bmiHeader);
431 header->bmiHeader.biWidth = width;
432 header->bmiHeader.biHeight = height;
433 header->bmiHeader.biPlanes = 1;
434 header->bmiHeader.biBitCount = subtype_to_bpp(subtype);
435 header->bmiHeader.biCompression = subtype_to_compression(subtype);
437 media_type->majortype = MEDIATYPE_Video;
438 media_type->subtype = *subtype;
439 media_type->bFixedSizeSamples = !compressed;
440 media_type->bTemporalCompression = compressed;
441 media_type->lSampleSize = 0;
442 media_type->formattype = FORMAT_VideoInfo;
443 media_type->pUnk = NULL;
444 media_type->cbFormat = sizeof(*header) + codec_data_size;
445 media_type->pbFormat = (BYTE *)header;
448 static void check_mft_optional_methods(IMFTransform *transform, DWORD output_count)
450 DWORD in_id, out_id, in_count, out_count, in_min, in_max, out_min, out_max;
451 PROPVARIANT propvar = {.vt = VT_EMPTY};
452 IMFMediaEvent *event;
453 HRESULT hr;
455 in_min = in_max = out_min = out_max = 0xdeadbeef;
456 hr = IMFTransform_GetStreamLimits(transform, &in_min, &in_max, &out_min, &out_max);
457 ok(hr == S_OK, "GetStreamLimits returned %#lx\n", hr);
458 ok(in_min == 1, "got input_min %lu\n", in_min);
459 ok(in_max == 1, "got input_max %lu\n", in_max);
460 ok(out_min == output_count, "got output_min %lu\n", out_min);
461 ok(out_max == output_count, "got output_max %lu\n", out_max);
463 in_count = out_count = 0xdeadbeef;
464 hr = IMFTransform_GetStreamCount(transform, &in_count, &out_count);
465 ok(hr == S_OK, "GetStreamCount returned %#lx\n", hr);
466 ok(in_count == 1, "got input_count %lu\n", in_count);
467 ok(out_count == output_count, "got output_count %lu\n", out_count);
469 in_count = out_count = 1;
470 in_id = out_id = 0xdeadbeef;
471 hr = IMFTransform_GetStreamIDs(transform, in_count, &in_id, out_count, &out_id);
472 ok(hr == E_NOTIMPL, "GetStreamIDs returned %#lx\n", hr);
474 hr = IMFTransform_DeleteInputStream(transform, 0);
475 ok(hr == E_NOTIMPL, "DeleteInputStream returned %#lx\n", hr);
476 hr = IMFTransform_DeleteInputStream(transform, 1);
477 ok(hr == E_NOTIMPL, "DeleteInputStream returned %#lx\n", hr);
479 hr = IMFTransform_AddInputStreams(transform, 0, NULL);
480 ok(hr == E_NOTIMPL, "AddInputStreams returned %#lx\n", hr);
481 in_id = 0xdeadbeef;
482 hr = IMFTransform_AddInputStreams(transform, 1, &in_id);
483 ok(hr == E_NOTIMPL, "AddInputStreams returned %#lx\n", hr);
485 hr = IMFTransform_SetOutputBounds(transform, 0, 0);
486 ok(hr == E_NOTIMPL || hr == S_OK, "SetOutputBounds returned %#lx\n", hr);
488 hr = MFCreateMediaEvent(MEEndOfStream, &GUID_NULL, S_OK, &propvar, &event);
489 ok(hr == S_OK, "MFCreateMediaEvent returned %#lx\n", hr);
490 hr = IMFTransform_ProcessEvent(transform, 0, NULL);
491 ok(hr == E_NOTIMPL || hr == E_POINTER || hr == E_INVALIDARG, "ProcessEvent returned %#lx\n", hr);
492 hr = IMFTransform_ProcessEvent(transform, 1, event);
493 ok(hr == E_NOTIMPL, "ProcessEvent returned %#lx\n", hr);
494 hr = IMFTransform_ProcessEvent(transform, 0, event);
495 ok(hr == E_NOTIMPL, "ProcessEvent returned %#lx\n", hr);
496 IMFMediaEvent_Release(event);
499 static void check_mft_get_attributes(IMFTransform *transform, const struct attribute_desc *expect_transform_attributes,
500 BOOL expect_output_attributes)
502 IMFAttributes *attributes, *tmp_attributes;
503 UINT32 count;
504 HRESULT hr;
505 ULONG ref;
507 hr = IMFTransform_GetAttributes(transform, &attributes);
508 todo_wine_if(expect_transform_attributes && hr == E_NOTIMPL)
509 ok(hr == (expect_transform_attributes ? S_OK : E_NOTIMPL), "GetAttributes returned %#lx\n", hr);
510 if (hr == S_OK)
512 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
513 check_attributes(attributes, expect_transform_attributes, -1);
515 hr = IMFTransform_GetAttributes(transform, &tmp_attributes);
516 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
517 ok(attributes == tmp_attributes, "got attributes %p\n", tmp_attributes);
518 IMFAttributes_Release(tmp_attributes);
520 ref = IMFAttributes_Release(attributes);
521 ok(ref == 1, "Release returned %lu\n", ref);
524 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &attributes);
525 todo_wine_if(expect_output_attributes && hr == E_NOTIMPL)
526 ok(hr == (expect_output_attributes ? S_OK : E_NOTIMPL)
527 || broken(hr == MF_E_UNSUPPORTED_REPRESENTATION) /* Win7 */,
528 "GetOutputStreamAttributes returned %#lx\n", hr);
529 if (hr == S_OK)
531 ok(hr == S_OK, "GetOutputStreamAttributes returned %#lx\n", hr);
533 count = 0xdeadbeef;
534 hr = IMFAttributes_GetCount(attributes, &count);
535 ok(hr == S_OK, "GetCount returned %#lx\n", hr);
536 ok(!count, "got %u attributes\n", count);
538 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, &tmp_attributes);
539 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
540 ok(attributes == tmp_attributes, "got attributes %p\n", tmp_attributes);
541 IMFAttributes_Release(tmp_attributes);
543 ref = IMFAttributes_Release(attributes);
544 ok(ref == 1, "Release returned %lu\n", ref);
546 hr = IMFTransform_GetOutputStreamAttributes(transform, 0, NULL);
547 ok(hr == E_NOTIMPL || hr == E_POINTER, "GetOutputStreamAttributes returned %#lx\n", hr);
548 hr = IMFTransform_GetOutputStreamAttributes(transform, 1, &attributes);
549 ok(hr == MF_E_INVALIDSTREAMNUMBER, "GetOutputStreamAttributes returned %#lx\n", hr);
552 hr = IMFTransform_GetInputStreamAttributes(transform, 0, &attributes);
553 ok(hr == E_NOTIMPL || broken(hr == MF_E_UNSUPPORTED_REPRESENTATION) /* Win7 */,
554 "GetInputStreamAttributes returned %#lx\n", hr);
557 #define check_mft_input_stream_info(a, b) check_mft_input_stream_info_(__LINE__, a, b)
558 static void check_mft_input_stream_info_(int line, MFT_INPUT_STREAM_INFO *value, const MFT_INPUT_STREAM_INFO *expect)
560 check_member_(__FILE__, line, *value, *expect, "%I64d", hnsMaxLatency);
561 check_member_(__FILE__, line, *value, *expect, "%#lx", dwFlags);
562 check_member_(__FILE__, line, *value, *expect, "%#lx", cbSize);
563 check_member_(__FILE__, line, *value, *expect, "%#lx", cbMaxLookahead);
564 check_member_(__FILE__, line, *value, *expect, "%#lx", cbAlignment);
567 #define check_mft_get_input_stream_info(a, b, c) check_mft_get_input_stream_info_(__LINE__, a, b, c)
568 static void check_mft_get_input_stream_info_(int line, IMFTransform *transform, HRESULT expect_hr, const MFT_INPUT_STREAM_INFO *expect)
570 MFT_INPUT_STREAM_INFO info, empty = {0};
571 HRESULT hr;
573 memset(&info, 0xcd, sizeof(info));
574 hr = IMFTransform_GetInputStreamInfo(transform, 0, &info);
575 ok_(__FILE__, line)(hr == expect_hr, "GetInputStreamInfo returned %#lx\n", hr);
576 check_mft_input_stream_info_(line, &info, expect ? expect : &empty);
579 #define check_mft_output_stream_info(a, b) check_mft_output_stream_info_(__LINE__, a, b)
580 static void check_mft_output_stream_info_(int line, MFT_OUTPUT_STREAM_INFO *value, const MFT_OUTPUT_STREAM_INFO *expect)
582 check_member_(__FILE__, line, *value, *expect, "%#lx", dwFlags);
583 check_member_(__FILE__, line, *value, *expect, "%#lx", cbSize);
584 check_member_(__FILE__, line, *value, *expect, "%#lx", cbAlignment);
587 #define check_mft_get_output_stream_info(a, b, c) check_mft_get_output_stream_info_(__LINE__, a, b, c)
588 static void check_mft_get_output_stream_info_(int line, IMFTransform *transform, HRESULT expect_hr, const MFT_OUTPUT_STREAM_INFO *expect)
590 MFT_OUTPUT_STREAM_INFO info, empty = {0};
591 HRESULT hr;
593 memset(&info, 0xcd, sizeof(info));
594 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &info);
595 ok_(__FILE__, line)(hr == expect_hr, "GetOutputStreamInfo returned %#lx\n", hr);
596 check_mft_output_stream_info_(line, &info, expect ? expect : &empty);
599 #define check_mft_set_input_type_required(a, b) check_mft_set_input_type_required_(__LINE__, a, b)
600 static void check_mft_set_input_type_required_(int line, IMFTransform *transform, const struct attribute_desc *attributes)
602 const struct attribute_desc *attr;
603 IMFMediaType *media_type;
604 HRESULT hr;
605 ULONG ref;
607 hr = MFCreateMediaType(&media_type);
608 ok_(__FILE__, line)(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
609 init_media_type(media_type, attributes, -1);
611 for (attr = attributes; attr && attr->key; attr++)
613 winetest_push_context("%s", debugstr_a(attr->name));
614 hr = IMFMediaType_DeleteItem(media_type, attr->key);
615 ok_(__FILE__, line)(hr == S_OK, "DeleteItem returned %#lx\n", hr);
616 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
617 ok_(__FILE__, line)(FAILED(hr) == attr->required, "SetInputType returned %#lx.\n", hr);
618 hr = IMFMediaType_SetItem(media_type, attr->key, &attr->value);
619 ok_(__FILE__, line)(hr == S_OK, "SetItem returned %#lx\n", hr);
620 winetest_pop_context();
623 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
624 ok_(__FILE__, line)(hr == S_OK, "SetInputType returned %#lx.\n", hr);
625 ref = IMFMediaType_Release(media_type);
626 ok_(__FILE__, line)(!ref, "Release returned %lu\n", ref);
629 static void check_mft_set_input_type(IMFTransform *transform, const struct attribute_desc *attributes)
631 IMFMediaType *media_type;
632 HRESULT hr;
634 hr = MFCreateMediaType(&media_type);
635 ok(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
636 init_media_type(media_type, attributes, -1);
638 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
639 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
640 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
641 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
643 IMFMediaType_Release(media_type);
646 #define check_mft_get_input_current_type(a, b) check_mft_get_input_current_type_(a, b, FALSE, FALSE)
647 static void check_mft_get_input_current_type_(IMFTransform *transform, const struct attribute_desc *attributes,
648 BOOL todo_current, BOOL todo_compare)
650 HRESULT hr, expect_hr = attributes ? S_OK : MF_E_TRANSFORM_TYPE_NOT_SET;
651 IMFMediaType *media_type, *current_type;
652 BOOL result;
654 hr = IMFTransform_GetInputCurrentType(transform, 0, &current_type);
655 todo_wine_if(todo_current)
656 ok(hr == expect_hr, "GetInputCurrentType returned hr %#lx.\n", hr);
657 if (FAILED(hr))
658 return;
660 hr = MFCreateMediaType(&media_type);
661 ok(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
662 init_media_type(media_type, attributes, -1);
664 hr = IMFMediaType_Compare(current_type, (IMFAttributes *)media_type,
665 MF_ATTRIBUTES_MATCH_ALL_ITEMS, &result);
666 ok(hr == S_OK, "Compare returned hr %#lx.\n", hr);
667 todo_wine_if(todo_compare)
668 ok(result, "got result %u.\n", !!result);
670 IMFMediaType_Release(media_type);
671 IMFMediaType_Release(current_type);
674 #define check_mft_set_output_type_required(a, b) check_mft_set_output_type_required_(__LINE__, a, b)
675 static void check_mft_set_output_type_required_(int line, IMFTransform *transform, const struct attribute_desc *attributes)
677 const struct attribute_desc *attr;
678 IMFMediaType *media_type;
679 HRESULT hr;
680 ULONG ref;
682 hr = MFCreateMediaType(&media_type);
683 ok_(__FILE__, line)(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
684 init_media_type(media_type, attributes, -1);
686 for (attr = attributes; attr && attr->key; attr++)
688 winetest_push_context("%s", debugstr_a(attr->name));
689 hr = IMFMediaType_DeleteItem(media_type, attr->key);
690 ok_(__FILE__, line)(hr == S_OK, "DeleteItem returned %#lx\n", hr);
691 hr = IMFTransform_SetOutputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
692 ok_(__FILE__, line)(FAILED(hr) == attr->required, "SetOutputType returned %#lx.\n", hr);
693 hr = IMFMediaType_SetItem(media_type, attr->key, &attr->value);
694 ok_(__FILE__, line)(hr == S_OK, "SetItem returned %#lx\n", hr);
695 winetest_pop_context();
698 hr = IMFTransform_SetOutputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
699 ok_(__FILE__, line)(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
700 ref = IMFMediaType_Release(media_type);
701 ok_(__FILE__, line)(!ref, "Release returned %lu\n", ref);
704 static void check_mft_set_output_type(IMFTransform *transform, const struct attribute_desc *attributes,
705 HRESULT expect_hr)
707 IMFMediaType *media_type;
708 HRESULT hr;
710 hr = MFCreateMediaType(&media_type);
711 ok(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
712 init_media_type(media_type, attributes, -1);
714 hr = IMFTransform_SetOutputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
715 ok(hr == expect_hr, "SetOutputType returned %#lx.\n", hr);
716 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
717 ok(hr == expect_hr, "SetOutputType returned %#lx.\n", hr);
719 IMFMediaType_Release(media_type);
722 #define check_mft_get_output_current_type(a, b) check_mft_get_output_current_type_(a, b, FALSE, FALSE)
723 static void check_mft_get_output_current_type_(IMFTransform *transform, const struct attribute_desc *attributes,
724 BOOL todo_current, BOOL todo_compare)
726 HRESULT hr, expect_hr = attributes ? S_OK : MF_E_TRANSFORM_TYPE_NOT_SET;
727 IMFMediaType *media_type, *current_type;
728 BOOL result;
730 hr = IMFTransform_GetOutputCurrentType(transform, 0, &current_type);
731 todo_wine_if(todo_current)
732 ok(hr == expect_hr, "GetOutputCurrentType returned hr %#lx.\n", hr);
733 if (FAILED(hr))
734 return;
736 hr = MFCreateMediaType(&media_type);
737 ok(hr == S_OK, "MFCreateMediaType returned hr %#lx.\n", hr);
738 init_media_type(media_type, attributes, -1);
740 hr = IMFMediaType_Compare(current_type, (IMFAttributes *)media_type,
741 MF_ATTRIBUTES_MATCH_ALL_ITEMS, &result);
742 ok(hr == S_OK, "Compare returned hr %#lx.\n", hr);
743 todo_wine_if(todo_compare)
744 ok(result, "got result %u.\n", !!result);
746 IMFMediaType_Release(media_type);
747 IMFMediaType_Release(current_type);
750 #define check_mft_process_output(a, b, c) check_mft_process_output_(__LINE__, a, b, c)
751 static HRESULT check_mft_process_output_(int line, IMFTransform *transform, IMFSample *output_sample, DWORD *output_status)
753 static const DWORD expect_flags = MFT_OUTPUT_DATA_BUFFER_INCOMPLETE | MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE
754 | MFT_OUTPUT_DATA_BUFFER_STREAM_END | MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE;
755 MFT_OUTPUT_DATA_BUFFER output[3];
756 HRESULT hr, ret;
757 DWORD status;
759 status = 0;
760 memset(&output, 0, sizeof(output));
761 output[0].pSample = output_sample;
762 output[0].dwStreamID = 0;
763 ret = IMFTransform_ProcessOutput(transform, 0, 1, output, &status);
764 ok_(__FILE__, line)(output[0].dwStreamID == 0, "got dwStreamID %#lx\n", output[0].dwStreamID);
765 ok_(__FILE__, line)(output[0].pEvents == NULL, "got pEvents %p\n", output[0].pEvents);
766 ok_(__FILE__, line)(output[0].pSample == output_sample, "got pSample %p\n", output[0].pSample);
767 ok_(__FILE__, line)((output[0].dwStatus & ~expect_flags) == 0
768 || broken((output[0].dwStatus & ~expect_flags) == 6) /* Win7 */
769 || broken((output[0].dwStatus & ~expect_flags) == 7) /* Win7 */,
770 "got dwStatus %#lx\n", output[0].dwStatus);
771 *output_status = output[0].dwStatus & expect_flags;
773 if (!output_sample)
774 ok_(__FILE__, line)(status == 0, "got status %#lx\n", status);
775 else if (ret == MF_E_TRANSFORM_STREAM_CHANGE)
776 ok_(__FILE__, line)(status == MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS,
777 "got status %#lx\n", status);
778 else
780 if (*output_status & MFT_OUTPUT_DATA_BUFFER_INCOMPLETE)
782 hr = IMFSample_SetUINT32(output_sample, &mft_output_sample_incomplete, 1);
783 ok_(__FILE__, line)(hr == S_OK, "SetUINT32 returned %#lx\n", hr);
785 else
787 hr = IMFSample_DeleteItem(output_sample, &mft_output_sample_incomplete);
788 ok_(__FILE__, line)(hr == S_OK, "DeleteItem returned %#lx\n", hr);
790 ok_(__FILE__, line)(status == 0, "got status %#lx\n", status);
793 return ret;
796 DWORD compare_nv12(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
798 DWORD x, y, size, diff = 0, width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
800 /* skip BMP header and RGB data from the dump */
801 size = *(DWORD *)(expect + 2);
802 *length = *length + size;
803 expect = expect + size;
805 for (y = 0; y < height; y++, data += width, expect += width)
807 if (y < rect->top || y >= rect->bottom) continue;
808 for (x = 0; x < width; x++)
810 if (x < rect->left || x >= rect->right) continue;
811 diff += abs((int)expect[x] - (int)data[x]);
815 for (y = 0; y < height; y += 2, data += width, expect += width)
817 if (y < rect->top || y >= rect->bottom) continue;
818 for (x = 0; x < width; x += 2)
820 if (x < rect->left || x >= rect->right) continue;
821 diff += abs((int)expect[x + 0] - (int)data[x + 0]);
822 diff += abs((int)expect[x + 1] - (int)data[x + 1]);
826 size = (rect->right - rect->left) * (rect->bottom - rect->top) * 3 / 2;
827 return diff * 100 / 256 / size;
830 DWORD compare_i420(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
832 DWORD i, x, y, size, diff = 0, width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
834 /* skip BMP header and RGB data from the dump */
835 size = *(DWORD *)(expect + 2);
836 *length = *length + size;
837 expect = expect + size;
839 for (y = 0; y < height; y++, data += width, expect += width)
841 if (y < rect->top || y >= rect->bottom) continue;
842 for (x = 0; x < width; x++)
844 if (x < rect->left || x >= rect->right) continue;
845 diff += abs((int)expect[x] - (int)data[x]);
849 for (i = 0; i < 2; ++i) for (y = 0; y < height; y += 2, data += width / 2, expect += width / 2)
851 if (y < rect->top || y >= rect->bottom) continue;
852 for (x = 0; x < width; x += 2)
854 if (x < rect->left || x >= rect->right) continue;
855 diff += abs((int)expect[x / 2] - (int)data[x / 2]);
859 size = (rect->right - rect->left) * (rect->bottom - rect->top) * 3 / 2;
860 return diff * 100 / 256 / size;
863 static DWORD compare_rgb(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect, UINT bits)
865 DWORD x, y, step = bits / 8, size, diff = 0, width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
867 /* skip BMP header from the dump */
868 size = *(DWORD *)(expect + 2 + 2 * sizeof(DWORD));
869 *length = *length + size;
870 expect = expect + size;
872 for (y = 0; y < height; y++, data += width * step, expect += width * step)
874 if (y < rect->top || y >= rect->bottom) continue;
875 for (x = 0; x < width; x++)
877 if (x < rect->left || x >= rect->right) continue;
878 diff += abs((int)expect[step * x + 0] - (int)data[step * x + 0]);
879 diff += abs((int)expect[step * x + 1] - (int)data[step * x + 1]);
880 if (step >= 3) diff += abs((int)expect[step * x + 2] - (int)data[step * x + 2]);
884 size = (rect->right - rect->left) * (rect->bottom - rect->top) * min(step, 3);
885 return diff * 100 / 256 / size;
888 DWORD compare_rgb32(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
890 return compare_rgb(data, length, rect, expect, 32);
893 DWORD compare_rgb24(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
895 return compare_rgb(data, length, rect, expect, 24);
898 DWORD compare_rgb16(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
900 return compare_rgb(data, length, rect, expect, 16);
903 DWORD compare_pcm16(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
905 const INT16 *data_pcm = (INT16 *)data, *expect_pcm = (INT16 *)expect;
906 DWORD i, size = *length / 2, diff = 0;
908 for (i = 0; i < size; i++)
909 diff += abs((int)*expect_pcm++ - (int)*data_pcm++);
911 return diff * 100 / 65536 / size;
914 static DWORD compare_bytes(const BYTE *data, DWORD *length, const RECT *rect, const BYTE *expect)
916 DWORD i, size = *length, diff = 0;
918 for (i = 0; i < size; i++)
919 diff += abs((int)*expect++ - (int)*data++);
921 return diff * 100 / 256 / size;
924 static void dump_rgb(const BYTE *data, DWORD length, const RECT *rect, HANDLE output, UINT bits)
926 DWORD width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
927 static const char magic[2] = "BM";
928 struct
930 DWORD length;
931 DWORD reserved;
932 DWORD offset;
933 BITMAPINFOHEADER biHeader;
934 } header =
936 .length = length + sizeof(header) + 2, .offset = sizeof(header) + 2,
937 .biHeader =
939 .biSize = sizeof(BITMAPINFOHEADER), .biWidth = width, .biHeight = height, .biPlanes = 1,
940 .biBitCount = bits, .biCompression = BI_RGB, .biSizeImage = width * height * (bits / 8),
943 DWORD written;
944 BOOL ret;
946 ret = WriteFile(output, magic, sizeof(magic), &written, NULL);
947 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
948 ok(written == sizeof(magic), "written %lu bytes\n", written);
949 ret = WriteFile(output, &header, sizeof(header), &written, NULL);
950 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
951 ok(written == sizeof(header), "written %lu bytes\n", written);
952 ret = WriteFile(output, data, length, &written, NULL);
953 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
954 ok(written == length, "written %lu bytes\n", written);
957 void dump_rgb32(const BYTE *data, DWORD length, const RECT *rect, HANDLE output)
959 return dump_rgb(data, length, rect, output, 32);
962 void dump_rgb24(const BYTE *data, DWORD length, const RECT *rect, HANDLE output)
964 return dump_rgb(data, length, rect, output, 24);
967 void dump_rgb16(const BYTE *data, DWORD length, const RECT *rect, HANDLE output)
969 return dump_rgb(data, length, rect, output, 16);
972 void dump_nv12(const BYTE *data, DWORD length, const RECT *rect, HANDLE output)
974 DWORD written, x, y, width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
975 BYTE *rgb32_data = malloc(width * height * 4), *rgb32 = rgb32_data;
976 BOOL ret;
978 for (y = 0; y < height; y++) for (x = 0; x < width; x++)
980 *rgb32++ = data[width * y + x];
981 *rgb32++ = data[width * height + width * (y / 2) + (x & ~1) + 0];
982 *rgb32++ = data[width * height + width * (y / 2) + (x & ~1) + 1];
983 *rgb32++ = 0xff;
986 dump_rgb32(rgb32_data, width * height * 4, rect, output);
987 free(rgb32_data);
989 ret = WriteFile(output, data, length, &written, NULL);
990 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
991 ok(written == length, "written %lu bytes\n", written);
994 void dump_i420(const BYTE *data, DWORD length, const RECT *rect, HANDLE output)
996 DWORD written, x, y, width = (rect->right + 0xf) & ~0xf, height = (rect->bottom + 0xf) & ~0xf;
997 BYTE *rgb32_data = malloc(width * height * 4), *rgb32 = rgb32_data;
998 BOOL ret;
1000 for (y = 0; y < height; y++) for (x = 0; x < width; x++)
1002 *rgb32++ = data[width * y + x];
1003 *rgb32++ = data[width * height + (width / 2) * (y / 2) + x / 2];
1004 *rgb32++ = data[width * height + (width / 2) * (y / 2) + (width / 2) * (height / 2) + x / 2];
1005 *rgb32++ = 0xff;
1008 dump_rgb32(rgb32_data, width * height * 4, rect, output);
1009 free(rgb32_data);
1011 ret = WriteFile(output, data, length, &written, NULL);
1012 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
1013 ok(written == length, "written %lu bytes\n", written);
1016 typedef void (*enum_mf_media_buffers_cb)(IMFMediaBuffer *buffer, const struct buffer_desc *desc, void *context);
1017 static void enum_mf_media_buffers(IMFSample *sample, const struct sample_desc *sample_desc,
1018 enum_mf_media_buffers_cb callback, void *context)
1020 IMFMediaBuffer *buffer;
1021 HRESULT hr;
1022 DWORD i;
1024 for (i = 0; SUCCEEDED(hr = IMFSample_GetBufferByIndex(sample, i, &buffer)); i++)
1026 winetest_push_context("buffer %lu", i);
1027 ok(hr == S_OK, "GetBufferByIndex returned %#lx\n", hr);
1028 ok(i < sample_desc->buffer_count, "got unexpected buffer\n");
1030 callback(buffer, sample_desc->buffers + i, context);
1032 IMFMediaBuffer_Release(buffer);
1033 winetest_pop_context();
1035 ok(hr == E_INVALIDARG, "GetBufferByIndex returned %#lx\n", hr);
1038 struct enum_mf_sample_state
1040 const struct sample_desc *next_sample;
1041 struct sample_desc sample;
1044 typedef void (*enum_mf_sample_cb)(IMFSample *sample, const struct sample_desc *sample_desc, void *context);
1045 static void enum_mf_samples(IMFCollection *samples, const struct sample_desc *collection_desc,
1046 enum_mf_sample_cb callback, void *context)
1048 struct enum_mf_sample_state state = {.next_sample = collection_desc};
1049 IMFSample *sample;
1050 HRESULT hr;
1051 DWORD i;
1053 for (i = 0; SUCCEEDED(hr = IMFCollection_GetElement(samples, i, (IUnknown **)&sample)); i++)
1055 winetest_push_context("sample %lu", i);
1056 ok(hr == S_OK, "GetElement returned %#lx\n", hr);
1058 state.sample.sample_time += state.sample.sample_duration;
1059 if (!state.sample.repeat_count--)
1060 state.sample = *state.next_sample++;
1062 callback(sample, &state.sample, context);
1064 IMFSample_Release(sample);
1065 winetest_pop_context();
1067 ok(hr == E_INVALIDARG, "GetElement returned %#lx\n", hr);
1070 static void dump_mf_media_buffer(IMFMediaBuffer *buffer, const struct buffer_desc *buffer_desc, HANDLE output)
1072 DWORD length, written;
1073 HRESULT hr;
1074 BYTE *data;
1075 BOOL ret;
1077 hr = IMFMediaBuffer_Lock(buffer, &data, NULL, &length);
1078 ok(hr == S_OK, "Lock returned %#lx\n", hr);
1080 if (buffer_desc->dump)
1081 buffer_desc->dump(data, length, &buffer_desc->rect, output);
1082 else
1084 if (buffer_desc->length == -1)
1086 ret = WriteFile(output, &length, sizeof(length), &written, NULL);
1087 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
1088 ok(written == sizeof(length), "written %lu bytes\n", written);
1091 ret = WriteFile(output, data, length, &written, NULL);
1092 ok(ret, "WriteFile failed, error %lu\n", GetLastError());
1093 ok(written == length, "written %lu bytes\n", written);
1096 hr = IMFMediaBuffer_Unlock(buffer);
1097 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
1100 static void dump_mf_sample(IMFSample *sample, const struct sample_desc *sample_desc, HANDLE output)
1102 enum_mf_media_buffers(sample, sample_desc, dump_mf_media_buffer, output);
1105 static void dump_mf_sample_collection(IMFCollection *samples, const struct sample_desc *collection_desc,
1106 const WCHAR *output_filename)
1108 WCHAR path[MAX_PATH];
1109 HANDLE output;
1111 GetTempPathW(ARRAY_SIZE(path), path);
1112 lstrcatW(path, output_filename);
1114 output = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
1115 ok(output != INVALID_HANDLE_VALUE, "CreateFileW failed, error %lu\n", GetLastError());
1117 enum_mf_samples(samples, collection_desc, dump_mf_sample, output);
1119 trace("created %s\n", debugstr_w(path));
1120 CloseHandle(output);
1123 #define check_mf_media_buffer(a, b, c) check_mf_media_buffer_(__FILE__, __LINE__, a, b, c)
1124 static DWORD check_mf_media_buffer_(const char *file, int line, IMFMediaBuffer *buffer, const struct buffer_desc *expect,
1125 const BYTE **expect_data, DWORD *expect_data_len)
1127 DWORD length, diff = 0, expect_length = expect->length;
1128 HRESULT hr;
1129 BYTE *data;
1131 if (expect_length == -1)
1133 expect_length = *(DWORD *)*expect_data;
1134 *expect_data = *expect_data + sizeof(DWORD);
1135 *expect_data_len = *expect_data_len - sizeof(DWORD);
1138 hr = IMFMediaBuffer_Lock(buffer, &data, NULL, &length);
1139 ok_(file, line)(hr == S_OK, "Lock returned %#lx\n", hr);
1140 todo_wine_if(expect->todo_length)
1141 ok_(file, line)(length == expect_length, "got length %#lx\n", length);
1143 if (*expect_data)
1145 if (*expect_data_len < length)
1146 todo_wine_if(expect->todo_length)
1147 ok_(file, line)(0, "missing %#lx bytes\n", length - *expect_data_len);
1148 else if (!expect->compare)
1149 diff = compare_bytes(data, &length, NULL, *expect_data);
1150 else
1151 diff = expect->compare(data, &length, &expect->rect, *expect_data);
1154 hr = IMFMediaBuffer_Unlock(buffer);
1155 ok_(file, line)(hr == S_OK, "Unlock returned %#lx\n", hr);
1157 *expect_data = *expect_data + min(length, *expect_data_len);
1158 *expect_data_len = *expect_data_len - min(length, *expect_data_len);
1160 return diff;
1163 struct check_mf_sample_context
1165 DWORD total_length;
1166 const BYTE *data;
1167 DWORD data_len;
1168 DWORD diff;
1169 const char *file;
1170 int line;
1173 static void check_mf_sample_buffer(IMFMediaBuffer *buffer, const struct buffer_desc *expect, void *context)
1175 struct check_mf_sample_context *ctx = context;
1176 DWORD expect_length = expect->length == -1 ? *(DWORD *)ctx->data : expect->length;
1177 ctx->diff += check_mf_media_buffer_(ctx->file, ctx->line, buffer, expect, &ctx->data, &ctx->data_len);
1178 ctx->total_length += expect_length;
1181 #define check_mf_sample(a, b, c, d) check_mf_sample_(__FILE__, __LINE__, a, b, c, d)
1182 static DWORD check_mf_sample_(const char *file, int line, IMFSample *sample, const struct sample_desc *expect,
1183 const BYTE **expect_data, DWORD *expect_data_len)
1185 struct check_mf_sample_context ctx = {.data = *expect_data, .data_len = *expect_data_len, .file = file, .line = line};
1186 DWORD buffer_count, total_length, sample_flags;
1187 LONGLONG timestamp;
1188 HRESULT hr;
1190 if (expect->attributes)
1191 check_attributes_(file, line, (IMFAttributes *)sample, expect->attributes, -1);
1193 buffer_count = 0xdeadbeef;
1194 hr = IMFSample_GetBufferCount(sample, &buffer_count);
1195 ok_(file, line)(hr == S_OK, "GetBufferCount returned %#lx\n", hr);
1196 ok_(file, line)(buffer_count == expect->buffer_count,
1197 "got %lu buffers\n", buffer_count);
1199 sample_flags = 0xdeadbeef;
1200 hr = IMFSample_GetSampleFlags(sample, &sample_flags);
1201 ok_(file, line)(hr == S_OK, "GetSampleFlags returned %#lx\n", hr);
1202 ok_(file, line)(sample_flags == 0,
1203 "got sample flags %#lx\n", sample_flags);
1205 timestamp = 0xdeadbeef;
1206 hr = IMFSample_GetSampleTime(sample, &timestamp);
1207 ok_(file, line)(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
1208 todo_wine_if(expect->todo_time)
1209 ok_(file, line)(llabs(timestamp - expect->sample_time) <= 50,
1210 "got sample time %I64d\n", timestamp);
1212 timestamp = 0xdeadbeef;
1213 hr = IMFSample_GetSampleDuration(sample, &timestamp);
1214 ok_(file, line)(hr == S_OK, "GetSampleDuration returned %#lx\n", hr);
1215 todo_wine_if(expect->todo_duration && expect->todo_duration == timestamp)
1216 ok_(file, line)(llabs(timestamp - expect->sample_duration) <= 1,
1217 "got sample duration %I64d\n", timestamp);
1219 enum_mf_media_buffers(sample, expect, check_mf_sample_buffer, &ctx);
1221 total_length = 0xdeadbeef;
1222 hr = IMFSample_GetTotalLength(sample, &total_length);
1223 ok_(file, line)(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
1224 todo_wine_if(expect->todo_length)
1225 ok_(file, line)(total_length == ctx.total_length,
1226 "got total length %#lx\n", total_length);
1227 ok_(file, line)(!*expect_data || *expect_data_len >= ctx.total_length,
1228 "missing %#lx data\n", ctx.total_length - *expect_data_len);
1230 *expect_data = ctx.data;
1231 *expect_data_len = ctx.data_len;
1233 return ctx.diff / buffer_count;
1236 static void check_mf_sample_collection_enum(IMFSample *sample, const struct sample_desc *expect, void *context)
1238 struct check_mf_sample_context *ctx = context;
1239 ctx->diff += check_mf_sample_(ctx->file, ctx->line, sample, expect, &ctx->data, &ctx->data_len);
1242 DWORD check_mf_sample_collection_(const char *file, int line, IMFCollection *samples,
1243 const struct sample_desc *expect_samples, const WCHAR *expect_data_filename)
1245 struct check_mf_sample_context ctx = {.file = file, .line = line};
1246 DWORD count;
1247 HRESULT hr;
1249 if (expect_data_filename) load_resource(expect_data_filename, &ctx.data, &ctx.data_len);
1250 enum_mf_samples(samples, expect_samples, check_mf_sample_collection_enum, &ctx);
1252 if (expect_data_filename) dump_mf_sample_collection(samples, expect_samples, expect_data_filename);
1254 hr = IMFCollection_GetElementCount(samples, &count);
1255 ok_(file, line)(hr == S_OK, "GetElementCount returned %#lx\n", hr);
1257 return ctx.diff / count;
1260 #define check_video_info_header(a, b) check_video_info_header_(__LINE__, a, b)
1261 static void check_video_info_header_(int line, VIDEOINFOHEADER *info, const VIDEOINFOHEADER *expected)
1263 ok_(__FILE__, line)(info->rcSource.left == expected->rcSource.left
1264 && info->rcSource.top == expected->rcSource.top
1265 && info->rcSource.right == expected->rcSource.right
1266 && info->rcSource.bottom == expected->rcSource.bottom,
1267 "Got unexpected rcSource {%ld, %ld, %ld, %ld}, expected {%ld, %ld, %ld, %ld}.\n",
1268 info->rcSource.left, info->rcSource.top, info->rcSource.right, info->rcSource.bottom,
1269 expected->rcSource.left, expected->rcSource.top, expected->rcSource.right, expected->rcSource.bottom);
1270 ok_(__FILE__, line)(info->rcTarget.left == expected->rcTarget.left
1271 && info->rcTarget.top == expected->rcTarget.top
1272 && info->rcTarget.right == expected->rcTarget.right
1273 && info->rcTarget.bottom == expected->rcTarget.bottom,
1274 "Got unexpected rcTarget {%ld, %ld, %ld, %ld}, expected {%ld, %ld, %ld, %ld}.\n",
1275 info->rcTarget.left, info->rcTarget.top, info->rcTarget.right, info->rcTarget.bottom,
1276 expected->rcTarget.left, expected->rcTarget.top, expected->rcTarget.right, expected->rcTarget.bottom);
1277 ok_(__FILE__, line)(info->dwBitRate == expected->dwBitRate,
1278 "Got unexpected dwBitRate %lu, expected %lu.\n",
1279 info->dwBitRate, expected->dwBitRate);
1280 ok_(__FILE__, line)(info->dwBitErrorRate == expected->dwBitErrorRate,
1281 "Got unexpected dwBitErrorRate %lu, expected %lu.\n",
1282 info->dwBitErrorRate, expected->dwBitErrorRate);
1283 ok_(__FILE__, line)(info->AvgTimePerFrame == expected->AvgTimePerFrame,
1284 "Got unexpected AvgTimePerFrame %I64d, expected %I64d.\n",
1285 info->AvgTimePerFrame, expected->AvgTimePerFrame);
1286 ok_(__FILE__, line)(info->bmiHeader.biSize == expected->bmiHeader.biSize,
1287 "Got unexpected bmiHeader.biSize %lu, expected %lu.\n",
1288 info->bmiHeader.biSize, expected->bmiHeader.biSize);
1289 ok_(__FILE__, line)(info->bmiHeader.biWidth == expected->bmiHeader.biWidth,
1290 "Got unexpected bmiHeader.biWidth %ld, expected %ld.\n",
1291 info->bmiHeader.biWidth, expected->bmiHeader.biWidth);
1292 ok_(__FILE__, line)(info->bmiHeader.biHeight == expected->bmiHeader.biHeight,
1293 "Got unexpected bmiHeader.biHeight %ld, expected %ld.\n",
1294 info->bmiHeader.biHeight, expected->bmiHeader.biHeight);
1295 ok_(__FILE__, line)(info->bmiHeader.biPlanes == expected->bmiHeader.biPlanes,
1296 "Got unexpected bmiHeader.biPlanes %u, expected %u.\n",
1297 info->bmiHeader.biPlanes, expected->bmiHeader.biPlanes);
1298 ok_(__FILE__, line)(info->bmiHeader.biBitCount == expected->bmiHeader.biBitCount,
1299 "Got unexpected bmiHeader.biBitCount %u, expected %u.\n",
1300 info->bmiHeader.biBitCount, expected->bmiHeader.biBitCount);
1301 ok_(__FILE__, line)(info->bmiHeader.biCompression == expected->bmiHeader.biCompression,
1302 "Got unexpected bmiHeader.biCompression %#lx, expected %#lx.\n",
1303 info->bmiHeader.biCompression, expected->bmiHeader.biCompression);
1304 ok_(__FILE__, line)(info->bmiHeader.biSizeImage == expected->bmiHeader.biSizeImage,
1305 "Got unexpected bmiHeader.biSizeImage %lu, expected %lu.\n",
1306 info->bmiHeader.biSizeImage, expected->bmiHeader.biSizeImage);
1307 ok_(__FILE__, line)(info->bmiHeader.biXPelsPerMeter == expected->bmiHeader.biXPelsPerMeter,
1308 "Got unexpected bmiHeader.biXPelsPerMeter %ld, expected %ld.\n",
1309 info->bmiHeader.biXPelsPerMeter, expected->bmiHeader.biXPelsPerMeter);
1310 ok_(__FILE__, line)(info->bmiHeader.biYPelsPerMeter == expected->bmiHeader.biYPelsPerMeter,
1311 "Got unexpected bmiHeader.xxxxxx %ld, expected %ld.\n",
1312 info->bmiHeader.biYPelsPerMeter, expected->bmiHeader.biYPelsPerMeter);
1313 todo_wine_if(expected->bmiHeader.biClrUsed != 0)
1314 ok_(__FILE__, line)(info->bmiHeader.biClrUsed == expected->bmiHeader.biClrUsed,
1315 "Got unexpected bmiHeader.biClrUsed %lu, expected %lu.\n",
1316 info->bmiHeader.biClrUsed, expected->bmiHeader.biClrUsed);
1317 todo_wine_if(expected->bmiHeader.biClrImportant != 0)
1318 ok_(__FILE__, line)(info->bmiHeader.biClrImportant == expected->bmiHeader.biClrImportant,
1319 "Got unexpected bmiHeader.biClrImportant %lu, expected %lu.\n",
1320 info->bmiHeader.biClrImportant, expected->bmiHeader.biClrImportant);
1323 #define check_dmo_media_type(a, b) check_dmo_media_type_(__LINE__, a, b)
1324 static void check_dmo_media_type_(int line, DMO_MEDIA_TYPE *media_type, const DMO_MEDIA_TYPE *expected)
1326 ok_(__FILE__, line)(IsEqualGUID(&media_type->majortype, &expected->majortype),
1327 "Got unexpected majortype %s, expected %s.\n",
1328 debugstr_guid(&media_type->majortype), debugstr_guid(&expected->majortype));
1329 ok_(__FILE__, line)(IsEqualGUID(&media_type->subtype, &expected->subtype),
1330 "Got unexpected subtype %s, expected %s.\n",
1331 debugstr_guid(&media_type->subtype), debugstr_guid(&expected->subtype));
1332 ok_(__FILE__, line)(media_type->bFixedSizeSamples == expected->bFixedSizeSamples,
1333 "Got unexpected bFixedSizeSamples %d, expected %d.\n",
1334 media_type->bFixedSizeSamples, expected->bFixedSizeSamples);
1335 ok_(__FILE__, line)(media_type->bTemporalCompression == expected->bTemporalCompression,
1336 "Got unexpected bTemporalCompression %d, expected %d.\n",
1337 media_type->bTemporalCompression, expected->bTemporalCompression);
1338 ok_(__FILE__, line)(media_type->lSampleSize == expected->lSampleSize,
1339 "Got unexpected lSampleSize %lu, expected %lu.\n",
1340 media_type->lSampleSize, expected->lSampleSize);
1341 ok_(__FILE__, line)(IsEqualGUID(&media_type->formattype, &expected->formattype),
1342 "Got unexpected formattype %s.\n",
1343 debugstr_guid(&media_type->formattype));
1344 ok_(__FILE__, line)(media_type->pUnk == NULL, "Got unexpected pUnk %p.\n", media_type->pUnk);
1345 todo_wine_if(expected->cbFormat && expected->cbFormat != sizeof(VIDEOINFOHEADER))
1346 ok_(__FILE__, line)(media_type->cbFormat == expected->cbFormat,
1347 "Got unexpected cbFormat %lu, expected %lu.\n",
1348 media_type->cbFormat, expected->cbFormat);
1350 if (expected->pbFormat)
1352 ok_(__FILE__, line)(!!media_type->pbFormat, "Got NULL pbFormat.\n");
1353 if (!media_type->pbFormat)
1354 return;
1356 if (IsEqualGUID(&media_type->formattype, &FORMAT_VideoInfo)
1357 && IsEqualGUID(&expected->formattype, &FORMAT_VideoInfo))
1358 check_video_info_header((VIDEOINFOHEADER *)media_type->pbFormat, (VIDEOINFOHEADER *)expected->pbFormat);
1362 static void check_dmo_get_input_type(IMediaObject *media_object, const DMO_MEDIA_TYPE *expected_type, ULONG count)
1364 DMO_MEDIA_TYPE media_type;
1365 HRESULT hr;
1366 DWORD i;
1368 hr = IMediaObject_GetInputType(media_object, 1, 0, NULL);
1369 ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetInputType returned %#lx.\n", hr);
1370 hr = IMediaObject_GetInputType(media_object, 1, 0, &media_type);
1371 ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetInputType returned %#lx.\n", hr);
1372 hr = IMediaObject_GetInputType(media_object, 1, count, &media_type);
1373 ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetInputType returned %#lx.\n", hr);
1374 hr = IMediaObject_GetInputType(media_object, 0, count, &media_type);
1375 ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned %#lx.\n", hr);
1376 hr = IMediaObject_GetInputType(media_object, 0, count, NULL);
1377 ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned %#lx.\n", hr);
1378 hr = IMediaObject_GetInputType(media_object, 0, 0xdeadbeef, NULL);
1379 ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned %#lx.\n", hr);
1380 hr = IMediaObject_GetInputType(media_object, 0, count - 1, NULL);
1381 ok(hr == S_OK, "GetInputType returned %#lx.\n", hr);
1382 hr = IMediaObject_GetInputType(media_object, 0, count - 1, &media_type);
1383 ok(hr == S_OK, "GetInputType returned %#lx.\n", hr);
1384 if (hr == S_OK)
1385 MoFreeMediaType(&media_type);
1387 i = -1;
1388 while (SUCCEEDED(hr = IMediaObject_GetInputType(media_object, 0, ++i, &media_type)))
1390 winetest_push_context("in %lu", i);
1391 check_dmo_media_type(&media_type, &expected_type[i]);
1392 MoFreeMediaType(&media_type);
1393 winetest_pop_context();
1396 ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned %#lx.\n", hr);
1397 ok(i == count, "%lu types.\n", i);
1400 static void check_dmo_get_output_type(IMediaObject *media_object, const DMO_MEDIA_TYPE *expected_type, ULONG count)
1402 DMO_MEDIA_TYPE media_type;
1403 HRESULT hr;
1404 DWORD i;
1406 hr = IMediaObject_GetOutputType(media_object, 1, 0, NULL);
1407 ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetOutputType returned %#lx.\n", hr);
1408 hr = IMediaObject_GetOutputType(media_object, 1, 0, &media_type);
1409 ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetOutputType returned %#lx.\n", hr);
1410 hr = IMediaObject_GetOutputType(media_object, 1, count, &media_type);
1411 ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetOutputType returned %#lx.\n", hr);
1412 hr = IMediaObject_GetOutputType(media_object, 0, count, &media_type);
1413 ok(hr == DMO_E_NO_MORE_ITEMS, "GetOutputType returned %#lx.\n", hr);
1414 hr = IMediaObject_GetOutputType(media_object, 0, count, NULL);
1415 ok(hr == DMO_E_NO_MORE_ITEMS || broken(hr == S_OK), "GetOutputType returned %#lx.\n", hr);
1416 hr = IMediaObject_GetOutputType(media_object, 0, 0xdeadbeef, NULL);
1417 ok(hr == DMO_E_NO_MORE_ITEMS || broken(hr == S_OK), "GetOutputType returned %#lx.\n", hr);
1418 hr = IMediaObject_GetOutputType(media_object, 0, count - 1, NULL);
1419 ok(hr == S_OK, "GetOutputType returned %#lx.\n", hr);
1420 hr = IMediaObject_GetOutputType(media_object, 0, count - 1, &media_type);
1421 ok(hr == S_OK, "GetOutputType returned %#lx.\n", hr);
1422 if (hr == S_OK)
1423 MoFreeMediaType(&media_type);
1425 i = -1;
1426 while (SUCCEEDED(hr = IMediaObject_GetOutputType(media_object, 0, ++i, &media_type)))
1428 winetest_push_context("out %lu", i);
1429 check_dmo_media_type(&media_type, &expected_type[i]);
1430 MoFreeMediaType(&media_type);
1431 winetest_pop_context();
1434 ok(hr == DMO_E_NO_MORE_ITEMS, "GetOutputType returned %#lx.\n", hr);
1435 ok(i == count, "%lu types.\n", i);
1438 static void check_dmo_set_input_type(IMediaObject *media_object, const GUID *subtype)
1440 DMO_MEDIA_TYPE bad_media_type, *good_media_type;
1441 VIDEOINFOHEADER *header;
1442 char buffer[1024];
1443 DWORD i, flag;
1444 HRESULT hr;
1446 const DWORD flags[] = {0, 0x4, DMO_SET_TYPEF_CLEAR, DMO_SET_TYPEF_TEST_ONLY, DMO_SET_TYPEF_TEST_ONLY | 0x4};
1448 memset(&bad_media_type, 0, sizeof(bad_media_type));
1449 good_media_type = (DMO_MEDIA_TYPE *)buffer;
1450 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1451 header = (VIDEOINFOHEADER *)(good_media_type + 1);
1453 /* Test invalid stream index. */
1454 for (i = 0; i < ARRAY_SIZE(flags); ++i)
1456 flag = flags[i];
1457 hr = IMediaObject_SetInputType(media_object, 1, NULL, flag);
1458 ok(hr == DMO_E_INVALIDSTREAMINDEX, "SetInputType returned %#lx for flag %#lx.\n", hr, flag);
1459 hr = IMediaObject_SetInputType(media_object, 1, &bad_media_type, flag);
1460 ok(hr == DMO_E_INVALIDSTREAMINDEX, "SetInputType returned %#lx for flag %#lx.\n", hr, flag);
1461 hr = IMediaObject_SetInputType(media_object, 1, good_media_type, flag);
1462 ok(hr == DMO_E_INVALIDSTREAMINDEX, "SetInputType returned %#lx for flag %#lx.\n", hr, flag);
1465 /* Test unaccepted type. */
1466 for (i = 0; i < ARRAY_SIZE(flags); ++i)
1468 flag = flags[i];
1469 if (!(flag & DMO_SET_TYPEF_CLEAR))
1471 hr = IMediaObject_SetInputType(media_object, 0, NULL, flag);
1472 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx for flag %#lx.\n", hr, flag);
1474 hr = IMediaObject_SetInputType(media_object, 0, &bad_media_type, flag);
1475 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx for flag %#lx.\n", hr, flag);
1478 /* Test clearing the type. */
1479 for (i = 0; i < ARRAY_SIZE(flags); ++i)
1481 flag = DMO_SET_TYPEF_CLEAR | flags[i];
1482 hr = IMediaObject_SetInputType(media_object, 0, NULL, flag);
1483 ok(hr == S_OK, "SetInputType returned %#lx for flag %#lx.\n", hr, flag);
1486 /* Test accepted type. */
1487 for (i = 0; i < ARRAY_SIZE(flags); ++i)
1489 flag = flags[i];
1490 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, flag);
1491 ok(hr == S_OK, "SetInputType returned %#lx for flag %#lx.\n", hr, flag);
1494 /* Test unconsidered header member.*/
1495 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1496 header->dwBitRate = 0xdeadbeef;
1497 header->dwBitErrorRate = 0xdeadbeef;
1498 header->AvgTimePerFrame = 0xdeadbeef;
1499 header->bmiHeader.biPlanes = 0xdead;
1500 header->bmiHeader.biBitCount = 0xdead;
1501 header->bmiHeader.biSizeImage = 0xdeadbeef;
1502 header->bmiHeader.biXPelsPerMeter = 0xdead;
1503 header->bmiHeader.biYPelsPerMeter = 0xdead;
1504 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, 0);
1505 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
1507 /* Test invalid major type. */
1508 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1509 good_media_type->majortype = MFMediaType_Default;
1510 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1511 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1513 /* Test invalid subtype. */
1514 init_dmo_media_type_video(good_media_type, &MEDIASUBTYPE_None, 16, 16);
1515 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1516 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1518 /* Test invalid format type. */
1519 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1520 good_media_type->formattype = FORMAT_None;
1521 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1522 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1524 /* Test invalid format size. */
1525 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1526 good_media_type->cbFormat = 1;
1527 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1528 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1530 /* Test NULL format pointer. */
1531 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1532 good_media_type->pbFormat = NULL;
1533 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1534 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1536 /* Test video header struct size. */
1537 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1538 header->bmiHeader.biSize = 0;
1539 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1540 todo_wine
1541 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1542 header->bmiHeader.biSize = 1;
1543 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1544 todo_wine
1545 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1546 header->bmiHeader.biSize = 0xdeadbeef;
1547 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1548 todo_wine
1549 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1551 /* Test width. */
1552 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1553 header->bmiHeader.biWidth = 0;
1554 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1555 todo_wine
1556 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1557 header->bmiHeader.biWidth = -1;
1558 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1559 todo_wine
1560 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1561 header->bmiHeader.biWidth = 4096 + 1;
1562 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1563 todo_wine
1564 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1565 header->bmiHeader.biWidth = 4096;
1566 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1567 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
1569 /* Test height. */
1570 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1571 header->bmiHeader.biHeight = 0;
1572 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1573 todo_wine
1574 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1575 header->bmiHeader.biHeight = 4096 + 1;
1576 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1577 todo_wine
1578 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1579 header->bmiHeader.biHeight = 4096;
1580 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1581 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
1582 header->bmiHeader.biHeight = -4096;
1583 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1584 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
1586 /* Test compression. */
1587 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1588 header->bmiHeader.biCompression = 0;
1589 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1590 todo_wine
1591 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetInputType returned %#lx.\n", hr);
1592 header->bmiHeader.biCompression = 1;
1593 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1594 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
1595 header->bmiHeader.biCompression = 2;
1596 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1597 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
1598 header->bmiHeader.biCompression = 0xdeadbeef;
1599 hr = IMediaObject_SetInputType(media_object, 0, good_media_type, DMO_SET_TYPEF_TEST_ONLY);
1600 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
1603 static void check_dmo_set_output_type(IMediaObject *media_object, const GUID *subtype)
1605 DMO_MEDIA_TYPE bad_media_type, *good_media_type;
1606 char buffer[1024];
1607 DWORD i, flag;
1608 HRESULT hr;
1610 const DWORD flags[] = {0, 0x4, DMO_SET_TYPEF_CLEAR, DMO_SET_TYPEF_TEST_ONLY, DMO_SET_TYPEF_TEST_ONLY | 0x4};
1612 memset(&bad_media_type, 0, sizeof(bad_media_type));
1613 good_media_type = (DMO_MEDIA_TYPE *)buffer;
1614 init_dmo_media_type_video(good_media_type, subtype, 16, 16);
1616 /* Test invalid stream index. */
1617 for (i = 0; i < ARRAY_SIZE(flags); ++i)
1619 flag = flags[i];
1620 hr = IMediaObject_SetOutputType(media_object, 1, NULL, flag);
1621 ok(hr == DMO_E_INVALIDSTREAMINDEX, "SetOutputType returned %#lx for flag %#lx.\n", hr, flag);
1622 hr = IMediaObject_SetOutputType(media_object, 1, &bad_media_type, flag);
1623 ok(hr == DMO_E_INVALIDSTREAMINDEX, "SetOutputType returned %#lx for flag %#lx.\n", hr, flag);
1624 hr = IMediaObject_SetOutputType(media_object, 1, good_media_type, flag);
1625 ok(hr == DMO_E_INVALIDSTREAMINDEX, "SetOutputType returned %#lx for flag %#lx.\n", hr, flag);
1628 /* Test unaccepted type. */
1629 for (i = 0; i < ARRAY_SIZE(flags); ++i)
1631 flag = flags[i];
1632 if (!(flag & DMO_SET_TYPEF_CLEAR))
1634 hr = IMediaObject_SetOutputType(media_object, 0, NULL, flag);
1635 ok(hr == E_POINTER, "SetOutputType returned %#lx for flag %#lx.\n", hr, flag);
1637 hr = IMediaObject_SetOutputType(media_object, 0, &bad_media_type, flag);
1638 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "SetOutputType returned %#lx for flag %#lx.\n", hr, flag);
1641 /* Test clearing the type. */
1642 for (i = 0; i < ARRAY_SIZE(flags); ++i)
1644 flag = DMO_SET_TYPEF_CLEAR | flags[i];
1645 hr = IMediaObject_SetOutputType(media_object, 0, NULL, flag);
1646 ok(hr == S_OK, "SetOutputType returned %#lx for flag %#lx.\n", hr, flag);
1649 /* Test accepted type. */
1650 for (i = 0; i < ARRAY_SIZE(flags); ++i)
1652 flag = flags[i];
1653 hr = IMediaObject_SetOutputType(media_object, 0, good_media_type, flag);
1654 ok(hr == S_OK, "SetOutputType returned %#lx for flag %#lx.\n", hr, flag);
1658 #define check_dmo_output_data_buffer(a, b, c, d, e) check_dmo_output_data_buffer_(__LINE__, a, b, c, d, e)
1659 static DWORD check_dmo_output_data_buffer_(int line, DMO_OUTPUT_DATA_BUFFER *output_data_buffer,
1660 const struct buffer_desc *buffer_desc, const WCHAR *expect_data_filename,
1661 REFERENCE_TIME time_stamp, REFERENCE_TIME time_length)
1663 DWORD diff, data_length, buffer_length, expect_length;
1664 BYTE *data, *buffer;
1665 HRESULT hr;
1667 if (output_data_buffer->dwStatus & DMO_OUTPUT_DATA_BUFFERF_TIME)
1668 ok_(__FILE__, line)(output_data_buffer->rtTimestamp == time_stamp,
1669 "Unexpected time stamp %I64d, expected %I64d.\n",
1670 output_data_buffer->rtTimestamp, time_stamp);
1671 if (output_data_buffer->dwStatus & DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH)
1672 todo_wine
1673 ok_(__FILE__, line)(output_data_buffer->rtTimelength == time_length,
1674 "Unexpected time length %I64d, expected %I64d.\n",
1675 output_data_buffer->rtTimelength, time_length);
1677 load_resource(expect_data_filename, (const BYTE **)&data, &data_length);
1679 expect_length = buffer_desc->length;
1680 if (expect_length == -1)
1682 expect_length = *(DWORD *)data;
1683 data += sizeof(DWORD);
1684 data_length = data_length - sizeof(DWORD);
1687 hr = IMediaBuffer_GetBufferAndLength(output_data_buffer->pBuffer, &buffer, &buffer_length);
1688 ok(hr == S_OK, "GetBufferAndLength returned %#lx.\n", hr);
1689 ok_(__FILE__, line)(buffer_length == expect_length, "Unexpected length %#lx, expected %#lx\n", buffer_length, expect_length);
1691 diff = 0;
1692 if (data_length < buffer_length)
1693 ok_(__FILE__, line)(0, "Missing %#lx bytes\n", buffer_length - data_length);
1694 else if (!buffer_desc->compare)
1695 diff = compare_bytes(buffer, &buffer_length, NULL, data);
1696 else
1697 diff = buffer_desc->compare(buffer, &buffer_length, &buffer_desc->rect, data);
1699 return diff;
1703 static HRESULT WINAPI test_unk_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
1705 if (IsEqualIID(riid, &IID_IUnknown))
1707 *obj = iface;
1708 IUnknown_AddRef(iface);
1709 return S_OK;
1712 *obj = NULL;
1713 return E_NOINTERFACE;
1716 static ULONG WINAPI test_unk_AddRef(IUnknown *iface)
1718 return 2;
1721 static ULONG WINAPI test_unk_Release(IUnknown *iface)
1723 return 1;
1726 static const IUnknownVtbl test_unk_vtbl =
1728 test_unk_QueryInterface,
1729 test_unk_AddRef,
1730 test_unk_Release,
1733 static BOOL is_supported_video_type(const GUID *guid)
1735 return IsEqualGUID(guid, &MFVideoFormat_L8)
1736 || IsEqualGUID(guid, &MFVideoFormat_L16)
1737 || IsEqualGUID(guid, &MFVideoFormat_D16)
1738 || IsEqualGUID(guid, &MFVideoFormat_IYUV)
1739 || IsEqualGUID(guid, &MFVideoFormat_YV12)
1740 || IsEqualGUID(guid, &MFVideoFormat_NV12)
1741 || IsEqualGUID(guid, &MFVideoFormat_NV21)
1742 || IsEqualGUID(guid, &MFVideoFormat_420O)
1743 || IsEqualGUID(guid, &MFVideoFormat_P010)
1744 || IsEqualGUID(guid, &MFVideoFormat_P016)
1745 || IsEqualGUID(guid, &MFVideoFormat_UYVY)
1746 || IsEqualGUID(guid, &MFVideoFormat_YUY2)
1747 || IsEqualGUID(guid, &MFVideoFormat_P208)
1748 || IsEqualGUID(guid, &MFVideoFormat_NV11)
1749 || IsEqualGUID(guid, &MFVideoFormat_AYUV)
1750 || IsEqualGUID(guid, &MFVideoFormat_ARGB32)
1751 || IsEqualGUID(guid, &MFVideoFormat_RGB32)
1752 || IsEqualGUID(guid, &MFVideoFormat_A2R10G10B10)
1753 || IsEqualGUID(guid, &MFVideoFormat_A16B16G16R16F)
1754 || IsEqualGUID(guid, &MFVideoFormat_RGB24)
1755 || IsEqualGUID(guid, &MFVideoFormat_I420)
1756 || IsEqualGUID(guid, &MFVideoFormat_YVYU)
1757 || IsEqualGUID(guid, &MFVideoFormat_RGB555)
1758 || IsEqualGUID(guid, &MFVideoFormat_RGB565)
1759 || IsEqualGUID(guid, &MFVideoFormat_RGB8)
1760 || IsEqualGUID(guid, &MFVideoFormat_Y216)
1761 || IsEqualGUID(guid, &MFVideoFormat_v410)
1762 || IsEqualGUID(guid, &MFVideoFormat_Y41P)
1763 || IsEqualGUID(guid, &MFVideoFormat_Y41T)
1764 || IsEqualGUID(guid, &MFVideoFormat_Y42T)
1765 || IsEqualGUID(guid, &MFVideoFormat_ABGR32);
1768 static BOOL is_sample_copier_available_type(IMFMediaType *type)
1770 GUID major = { 0 };
1771 UINT32 count;
1772 HRESULT hr;
1774 hr = IMFMediaType_GetMajorType(type, &major);
1775 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
1777 hr = IMFMediaType_GetCount(type, &count);
1778 ok(hr == S_OK, "Failed to get attribute count, hr %#lx.\n", hr);
1779 ok(count == 1, "Unexpected attribute count %u.\n", count);
1781 return IsEqualGUID(&major, &MFMediaType_Video) || IsEqualGUID(&major, &MFMediaType_Audio);
1784 static void test_sample_copier(void)
1786 static const struct attribute_desc expect_transform_attributes[] =
1788 ATTR_UINT32(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, 1),
1789 {0},
1791 const MFT_OUTPUT_STREAM_INFO initial_output_info = {0}, output_info = {.cbSize = 16 * 16};
1792 const MFT_INPUT_STREAM_INFO initial_input_info = {0}, input_info = {.cbSize = 16 * 16};
1793 IMFMediaType *mediatype, *mediatype2;
1794 IMFSample *sample, *client_sample;
1795 IMFMediaBuffer *media_buffer;
1796 MFT_INPUT_STREAM_INFO info;
1797 DWORD flags, output_status;
1798 IMFTransform *copier;
1799 HRESULT hr;
1800 LONG ref;
1802 if (!pMFCreateSampleCopierMFT)
1804 win_skip("MFCreateSampleCopierMFT() is not available.\n");
1805 return;
1808 winetest_push_context("copier");
1810 hr = pMFCreateSampleCopierMFT(&copier);
1811 ok(hr == S_OK, "Failed to create sample copier, hr %#lx.\n", hr);
1813 check_interface(copier, &IID_IMFTransform, TRUE);
1814 check_interface(copier, &IID_IMediaObject, FALSE);
1815 check_interface(copier, &IID_IPropertyStore, FALSE);
1816 check_interface(copier, &IID_IPropertyBag, FALSE);
1818 check_mft_optional_methods(copier, 1);
1819 check_mft_get_attributes(copier, expect_transform_attributes, FALSE);
1821 /* Available types. */
1822 hr = IMFTransform_GetInputAvailableType(copier, 0, 0, &mediatype);
1823 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1824 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
1825 IMFMediaType_Release(mediatype);
1827 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype);
1828 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1829 ok(is_sample_copier_available_type(mediatype), "Unexpected type.\n");
1830 IMFMediaType_Release(mediatype);
1832 hr = IMFTransform_GetInputAvailableType(copier, 0, 2, &mediatype);
1833 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
1835 hr = IMFTransform_GetInputAvailableType(copier, 1, 0, &mediatype);
1836 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
1838 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype);
1839 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
1841 hr = IMFTransform_GetOutputAvailableType(copier, 1, 0, &mediatype);
1842 ok(hr == MF_E_INVALIDSTREAMNUMBER, "Unexpected hr %#lx.\n", hr);
1844 check_mft_get_input_current_type(copier, NULL);
1845 check_mft_get_output_current_type(copier, NULL);
1847 hr = MFCreateSample(&sample);
1848 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
1850 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
1851 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
1853 hr = MFCreateMediaType(&mediatype);
1854 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
1856 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
1857 ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr);
1859 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
1860 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1862 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB8);
1863 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1865 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
1866 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
1868 check_mft_get_input_stream_info(copier, S_OK, &initial_input_info);
1869 check_mft_get_output_stream_info(copier, S_OK, &initial_output_info);
1871 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
1872 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
1874 memset(&info, 0xcd, sizeof(info));
1875 hr = IMFTransform_GetInputStreamInfo(copier, 0, &info);
1876 ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr);
1877 check_member(info, initial_input_info, "%I64d", hnsMaxLatency);
1878 check_member(info, initial_input_info, "%#lx", dwFlags);
1879 todo_wine
1880 check_member(info, initial_input_info, "%#lx", cbSize);
1881 check_member(info, initial_input_info, "%#lx", cbMaxLookahead);
1882 check_member(info, initial_input_info, "%#lx", cbAlignment);
1883 check_mft_get_output_stream_info(copier, S_OK, &output_info);
1885 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
1886 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
1887 IMFMediaType_Release(mediatype2);
1889 check_mft_get_input_current_type(copier, NULL);
1891 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
1892 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
1894 /* Setting input type resets output type. */
1895 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
1896 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1897 IMFMediaType_Release(mediatype2);
1899 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
1900 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
1902 hr = IMFTransform_GetOutputCurrentType(copier, 0, &mediatype2);
1903 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
1905 hr = IMFTransform_GetInputAvailableType(copier, 0, 1, &mediatype2);
1906 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1907 ok(is_sample_copier_available_type(mediatype2), "Unexpected type.\n");
1908 IMFMediaType_Release(mediatype2);
1910 check_mft_get_input_stream_info(copier, S_OK, &input_info);
1911 check_mft_get_output_stream_info(copier, S_OK, &output_info);
1913 hr = IMFTransform_GetOutputAvailableType(copier, 0, 0, &mediatype2);
1914 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1915 hr = IMFMediaType_IsEqual(mediatype2, mediatype, &flags);
1916 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1917 IMFMediaType_Release(mediatype2);
1919 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
1920 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
1921 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected flags %#lx.\n", flags);
1923 hr = IMFTransform_GetInputCurrentType(copier, 0, &mediatype2);
1924 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
1925 IMFMediaType_Release(mediatype2);
1927 hr = IMFTransform_GetOutputStatus(copier, &flags);
1928 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
1930 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
1931 ok(hr == S_OK, "Failed to set output type, hr %#lx.\n", hr);
1933 hr = IMFTransform_GetOutputStatus(copier, &flags);
1934 ok(hr == S_OK, "Failed to get output status, hr %#lx.\n", hr);
1935 ok(!flags, "Unexpected flags %#lx.\n", flags);
1937 /* Pushing samples. */
1938 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
1939 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
1941 hr = IMFSample_AddBuffer(sample, media_buffer);
1942 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
1943 IMFMediaBuffer_Release(media_buffer);
1945 EXPECT_REF(sample, 1);
1946 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
1947 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
1948 EXPECT_REF(sample, 2);
1950 hr = IMFTransform_GetInputStatus(copier, 0, &flags);
1951 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
1952 ok(!flags, "Unexpected flags %#lx.\n", flags);
1954 hr = IMFTransform_GetOutputStatus(copier, &flags);
1955 ok(hr == S_OK, "Failed to get output status, hr %#lx.\n", hr);
1956 ok(flags == MFT_OUTPUT_STATUS_SAMPLE_READY, "Unexpected flags %#lx.\n", flags);
1958 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
1959 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#lx.\n", hr);
1961 check_mft_get_input_stream_info(copier, S_OK, &input_info);
1962 check_mft_get_output_stream_info(copier, S_OK, &output_info);
1964 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &media_buffer);
1965 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
1967 hr = MFCreateSample(&client_sample);
1968 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
1970 hr = IMFSample_AddBuffer(client_sample, media_buffer);
1971 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
1972 IMFMediaBuffer_Release(media_buffer);
1974 hr = check_mft_process_output(copier, client_sample, &output_status);
1975 ok(hr == S_OK, "Failed to get output, hr %#lx.\n", hr);
1976 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
1977 EXPECT_REF(sample, 1);
1979 hr = check_mft_process_output(copier, client_sample, &output_status);
1980 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Failed to get output, hr %#lx.\n", hr);
1981 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
1983 /* Flushing. */
1984 hr = IMFTransform_ProcessInput(copier, 0, sample, 0);
1985 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
1986 EXPECT_REF(sample, 2);
1988 hr = IMFTransform_ProcessMessage(copier, MFT_MESSAGE_COMMAND_FLUSH, 0);
1989 ok(hr == S_OK, "Failed to flush, hr %#lx.\n", hr);
1991 ref = IMFSample_Release(sample);
1992 ok(ref == 0, "Release returned %ld\n", ref);
1993 ref = IMFSample_Release(client_sample);
1994 ok(ref == 0, "Release returned %ld\n", ref);
1996 ref = IMFTransform_Release(copier);
1997 ok(ref == 0, "Release returned %ld\n", ref);
1998 ref = IMFMediaType_Release(mediatype);
1999 ok(ref == 0, "Release returned %ld\n", ref);
2001 winetest_pop_context();
2004 struct sample_metadata
2006 unsigned int flags;
2007 LONGLONG duration;
2008 LONGLONG time;
2011 static void sample_copier_process(IMFTransform *copier, IMFMediaBuffer *input_buffer,
2012 IMFMediaBuffer *output_buffer, const struct sample_metadata *md)
2014 static const struct sample_metadata zero_md = { 0, ~0u, ~0u };
2015 IMFSample *input_sample, *output_sample;
2016 DWORD flags, output_status;
2017 LONGLONG time;
2018 HRESULT hr;
2019 LONG ref;
2021 hr = MFCreateSample(&input_sample);
2022 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
2024 if (md)
2026 hr = IMFSample_SetSampleFlags(input_sample, md->flags);
2027 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2029 hr = IMFSample_SetSampleTime(input_sample, md->time);
2030 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2032 hr = IMFSample_SetSampleDuration(input_sample, md->duration);
2033 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2036 hr = MFCreateSample(&output_sample);
2037 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
2039 hr = IMFSample_SetSampleFlags(output_sample, ~0u);
2040 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2042 hr = IMFSample_SetSampleTime(output_sample, ~0u);
2043 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2045 hr = IMFSample_SetSampleDuration(output_sample, ~0u);
2046 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2048 hr = IMFSample_AddBuffer(input_sample, input_buffer);
2049 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2051 hr = IMFSample_AddBuffer(output_sample, output_buffer);
2052 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2054 hr = IMFTransform_ProcessInput(copier, 0, input_sample, 0);
2055 ok(hr == S_OK, "Failed to process input, hr %#lx.\n", hr);
2057 hr = check_mft_process_output(copier, output_sample, &output_status);
2058 ok(hr == S_OK, "Failed to get output, hr %#lx.\n", hr);
2059 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
2061 if (!md) md = &zero_md;
2063 hr = IMFSample_GetSampleFlags(output_sample, &flags);
2064 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2065 ok(md->flags == flags, "Unexpected flags.\n");
2066 hr = IMFSample_GetSampleTime(output_sample, &time);
2067 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2068 ok(md->time == time, "Unexpected time.\n");
2069 hr = IMFSample_GetSampleDuration(output_sample, &time);
2070 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2071 ok(md->duration == time, "Unexpected duration.\n");
2073 ref = IMFSample_Release(input_sample);
2074 ok(ref == 0, "Release returned %ld\n", ref);
2075 ref = IMFSample_Release(output_sample);
2076 ok(ref == 0, "Release returned %ld\n", ref);
2079 static void test_sample_copier_output_processing(void)
2081 IMFMediaBuffer *input_buffer, *output_buffer;
2082 MFT_OUTPUT_STREAM_INFO output_info;
2083 struct sample_metadata md;
2084 IMFMediaType *mediatype;
2085 IMFTransform *copier;
2086 DWORD max_length;
2087 HRESULT hr;
2088 BYTE *ptr;
2089 LONG ref;
2091 if (!pMFCreateSampleCopierMFT)
2092 return;
2094 hr = pMFCreateSampleCopierMFT(&copier);
2095 ok(hr == S_OK, "Failed to create sample copier, hr %#lx.\n", hr);
2097 /* Configure for 16 x 16 of D3DFMT_X8R8G8B8. */
2098 hr = MFCreateMediaType(&mediatype);
2099 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
2101 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
2102 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2104 hr = IMFMediaType_SetGUID(mediatype, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
2105 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2107 hr = IMFMediaType_SetUINT64(mediatype, &MF_MT_FRAME_SIZE, ((UINT64)16) << 32 | 16);
2108 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
2110 hr = IMFTransform_SetInputType(copier, 0, mediatype, 0);
2111 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
2113 hr = IMFTransform_SetOutputType(copier, 0, mediatype, 0);
2114 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
2116 /* Source and destination are linear buffers, destination is twice as large. */
2117 hr = IMFTransform_GetOutputStreamInfo(copier, 0, &output_info);
2118 ok(hr == S_OK, "Failed to get output info, hr %#lx.\n", hr);
2120 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &output_buffer);
2121 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
2123 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
2124 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2125 memset(ptr, 0xcc, max_length);
2126 hr = IMFMediaBuffer_Unlock(output_buffer);
2127 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2129 hr = MFCreateAlignedMemoryBuffer(output_info.cbSize, output_info.cbAlignment, &input_buffer);
2130 ok(hr == S_OK, "Failed to create media buffer, hr %#lx.\n", hr);
2132 hr = IMFMediaBuffer_Lock(input_buffer, &ptr, &max_length, NULL);
2133 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2134 memset(ptr, 0xaa, max_length);
2135 hr = IMFMediaBuffer_Unlock(input_buffer);
2136 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2137 hr = IMFMediaBuffer_SetCurrentLength(input_buffer, 4);
2138 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2140 sample_copier_process(copier, input_buffer, output_buffer, NULL);
2142 hr = IMFMediaBuffer_Lock(output_buffer, &ptr, &max_length, NULL);
2143 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2144 ok(ptr[0] == 0xaa && ptr[4] == 0xcc, "Unexpected buffer contents.\n");
2146 hr = IMFMediaBuffer_Unlock(output_buffer);
2147 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2149 md.flags = 123;
2150 md.time = 10;
2151 md.duration = 2;
2152 sample_copier_process(copier, input_buffer, output_buffer, &md);
2154 ref = IMFMediaBuffer_Release(input_buffer);
2155 ok(ref == 0, "Release returned %ld\n", ref);
2156 ref = IMFMediaBuffer_Release(output_buffer);
2157 ok(ref == 0, "Release returned %ld\n", ref);
2159 ref = IMFTransform_Release(copier);
2160 ok(ref == 0, "Release returned %ld\n", ref);
2161 ref = IMFMediaType_Release(mediatype);
2162 ok(ref == 0, "Release returned %ld\n", ref);
2165 static IMFSample *create_sample(const BYTE *data, ULONG size)
2167 IMFMediaBuffer *media_buffer;
2168 IMFSample *sample;
2169 DWORD length;
2170 BYTE *buffer;
2171 HRESULT hr;
2172 ULONG ret;
2174 hr = MFCreateSample(&sample);
2175 ok(hr == S_OK, "MFCreateSample returned %#lx\n", hr);
2176 hr = MFCreateMemoryBuffer(size, &media_buffer);
2177 ok(hr == S_OK, "MFCreateMemoryBuffer returned %#lx\n", hr);
2178 hr = IMFMediaBuffer_Lock(media_buffer, &buffer, NULL, &length);
2179 ok(hr == S_OK, "Lock returned %#lx\n", hr);
2180 ok(length == 0, "got length %lu\n", length);
2181 if (!data) memset(buffer, 0xcd, size);
2182 else memcpy(buffer, data, size);
2183 hr = IMFMediaBuffer_Unlock(media_buffer);
2184 ok(hr == S_OK, "Unlock returned %#lx\n", hr);
2185 hr = IMFMediaBuffer_SetCurrentLength(media_buffer, data ? size : 0);
2186 ok(hr == S_OK, "SetCurrentLength returned %#lx\n", hr);
2187 hr = IMFSample_AddBuffer(sample, media_buffer);
2188 ok(hr == S_OK, "AddBuffer returned %#lx\n", hr);
2189 ret = IMFMediaBuffer_Release(media_buffer);
2190 ok(ret == 1, "Release returned %lu\n", ret);
2192 return sample;
2195 static const BYTE aac_codec_data[14] = {0x00,0x00,0x29,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x08};
2197 static void test_aac_encoder(void)
2199 const GUID *const class_id = &CLSID_AACMFTEncoder;
2200 const struct transform_info expect_mft_info =
2202 .name = L"Microsoft AAC Audio Encoder MFT",
2203 .major_type = &MFMediaType_Audio,
2204 .inputs =
2206 {.subtype = &MFAudioFormat_PCM},
2208 .outputs =
2210 {.subtype = &MFAudioFormat_AAC},
2214 static const struct attribute_desc input_type_desc[] =
2216 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2217 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM, .required = TRUE),
2218 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1, .required = TRUE),
2219 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
2220 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .required = TRUE),
2221 {0},
2223 const struct attribute_desc output_type_desc[] =
2225 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2226 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC, .required = TRUE),
2227 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1, .required = TRUE),
2228 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
2229 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .required = TRUE),
2230 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 12000, .required = TRUE),
2231 {0},
2234 static const struct attribute_desc expect_input_type_desc[] =
2236 ATTR_GUID(MF_MT_AM_FORMAT_TYPE, FORMAT_WaveFormatEx),
2237 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2238 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2239 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
2240 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2241 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2),
2242 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2243 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 * 2),
2244 ATTR_UINT32(MF_MT_AVG_BITRATE, 44100 * 2 * 8),
2245 ATTR_UINT32(MF_MT_COMPRESSED, 0),
2246 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
2247 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2248 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2249 {0},
2251 const struct attribute_desc expect_output_type_desc[] =
2253 ATTR_GUID(MF_MT_AM_FORMAT_TYPE, FORMAT_WaveFormatEx),
2254 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2255 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC),
2256 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
2257 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2258 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
2259 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2260 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 12000),
2261 ATTR_UINT32(MF_MT_AVG_BITRATE, 96000),
2262 ATTR_UINT32(MF_MT_COMPRESSED, 1),
2263 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 0),
2264 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2265 ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 41),
2266 ATTR_UINT32(MF_MT_AAC_PAYLOAD_TYPE, 0),
2267 ATTR_BLOB(MF_MT_USER_DATA, aac_codec_data, sizeof(aac_codec_data)),
2268 {0},
2270 const MFT_OUTPUT_STREAM_INFO initial_output_info = {0}, output_info = {.cbSize = 0x600};
2271 const MFT_INPUT_STREAM_INFO input_info = {0};
2273 const struct buffer_desc output_buffer_desc[] =
2275 {.length = -1 /* variable */},
2277 const struct attribute_desc output_sample_attributes[] =
2279 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
2280 {0},
2282 const struct sample_desc output_sample_desc[] =
2285 .repeat_count = 88,
2286 .attributes = output_sample_attributes,
2287 .sample_time = 0, .sample_duration = 113823,
2288 .buffer_count = 1, .buffers = output_buffer_desc,
2292 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_AAC};
2293 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_PCM};
2294 IMFSample *input_sample, *output_sample;
2295 IMFCollection *output_samples;
2296 ULONG i, ret, audio_data_len;
2297 DWORD length, output_status;
2298 IMFTransform *transform;
2299 const BYTE *audio_data;
2300 HRESULT hr;
2301 LONG ref;
2303 hr = CoInitialize(NULL);
2304 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
2306 winetest_push_context("aacenc");
2308 if (!check_mft_enum(MFT_CATEGORY_AUDIO_ENCODER, &input_type, &output_type, class_id))
2309 goto failed;
2310 check_mft_get_info(class_id, &expect_mft_info);
2312 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
2313 &IID_IMFTransform, (void **)&transform)))
2314 goto failed;
2316 check_interface(transform, &IID_IMFTransform, TRUE);
2317 check_interface(transform, &IID_IMediaObject, FALSE);
2318 check_interface(transform, &IID_IPropertyStore, FALSE);
2319 check_interface(transform, &IID_IPropertyBag, FALSE);
2321 check_mft_optional_methods(transform, 1);
2322 check_mft_get_attributes(transform, NULL, FALSE);
2323 check_mft_get_input_stream_info(transform, S_OK, &input_info);
2324 check_mft_get_output_stream_info(transform, S_OK, &initial_output_info);
2326 check_mft_set_output_type_required(transform, output_type_desc);
2327 check_mft_set_output_type(transform, output_type_desc, S_OK);
2328 check_mft_get_output_current_type(transform, expect_output_type_desc);
2330 check_mft_set_input_type_required(transform, input_type_desc);
2331 check_mft_set_input_type(transform, input_type_desc);
2332 check_mft_get_input_current_type(transform, expect_input_type_desc);
2334 check_mft_get_input_stream_info(transform, S_OK, &input_info);
2335 check_mft_get_output_stream_info(transform, S_OK, &output_info);
2337 if (!has_video_processor)
2339 win_skip("Skipping AAC encoder tests on Win7\n");
2340 goto done;
2343 load_resource(L"audiodata.bin", &audio_data, &audio_data_len);
2344 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
2346 input_sample = create_sample(audio_data, audio_data_len);
2347 hr = IMFSample_SetSampleTime(input_sample, 0);
2348 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
2349 hr = IMFSample_SetSampleDuration(input_sample, 10000000);
2350 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
2351 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2352 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2353 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
2354 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
2355 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2356 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2357 ref = IMFSample_Release(input_sample);
2358 ok(ref <= 1, "Release returned %ld\n", ref);
2360 hr = MFCreateCollection(&output_samples);
2361 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
2363 output_sample = create_sample(NULL, output_info.cbSize);
2364 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
2366 winetest_push_context("%lu", i);
2367 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
2368 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
2369 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
2370 ref = IMFSample_Release(output_sample);
2371 ok(ref == 1, "Release returned %ld\n", ref);
2372 output_sample = create_sample(NULL, output_info.cbSize);
2373 winetest_pop_context();
2375 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2376 ret = IMFSample_Release(output_sample);
2377 ok(ret == 0, "Release returned %lu\n", ret);
2378 ok(i == 88, "got %lu output samples\n", i);
2380 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"aacencdata.bin");
2381 ok(ret == 0, "got %lu%% diff\n", ret);
2382 IMFCollection_Release(output_samples);
2384 output_sample = create_sample(NULL, output_info.cbSize);
2385 hr = check_mft_process_output(transform, output_sample, &output_status);
2386 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2387 hr = IMFSample_GetTotalLength(output_sample, &length);
2388 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
2389 ok(length == 0, "got length %lu\n", length);
2390 ret = IMFSample_Release(output_sample);
2391 ok(ret == 0, "Release returned %lu\n", ret);
2393 done:
2394 ret = IMFTransform_Release(transform);
2395 ok(ret == 0, "Release returned %lu\n", ret);
2397 failed:
2398 winetest_pop_context();
2399 CoUninitialize();
2402 static void test_aac_decoder_subtype(const struct attribute_desc *input_type_desc)
2404 const GUID *const class_id = &CLSID_MSAACDecMFT;
2405 const struct transform_info expect_mft_info =
2407 .name = L"Microsoft AAC Audio Decoder MFT",
2408 .major_type = &MFMediaType_Audio,
2409 .inputs =
2411 {.subtype = &MFAudioFormat_AAC},
2412 {.subtype = &MFAudioFormat_RAW_AAC1},
2413 {.subtype = &MFAudioFormat_ADTS, .broken = TRUE /* <= w8 */},
2415 .outputs =
2417 {.subtype = &MFAudioFormat_Float},
2418 {.subtype = &MFAudioFormat_PCM},
2422 static const struct attribute_desc expect_input_attributes[] =
2424 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2425 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2426 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
2427 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 6),
2428 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 24),
2429 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
2430 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 1152000),
2431 {0},
2433 static const media_type_desc expect_available_inputs[] =
2436 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC),
2437 ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 0),
2438 ATTR_UINT32(MF_MT_AAC_PAYLOAD_TYPE, 0),
2439 /* MF_MT_USER_DATA with some AAC codec data */
2442 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_RAW_AAC1),
2445 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC),
2446 ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 0),
2447 ATTR_UINT32(MF_MT_AAC_PAYLOAD_TYPE, 1),
2448 /* MF_MT_USER_DATA with some AAC codec data */
2451 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC),
2452 ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 0),
2453 ATTR_UINT32(MF_MT_AAC_PAYLOAD_TYPE, 3),
2454 /* MF_MT_USER_DATA with some AAC codec data */
2457 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_ADTS),
2460 static const struct attribute_desc expect_output_attributes[] =
2462 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2463 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2464 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2465 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
2466 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2467 {0},
2469 static const media_type_desc expect_available_outputs[] =
2472 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2473 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
2474 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
2475 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
2476 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4 * 44100),
2479 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2480 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
2481 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
2482 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2),
2483 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * 44100),
2486 const struct attribute_desc expect_transform_attributes[] =
2488 ATTR_UINT32(MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE, !has_video_processor /* 1 on W7 */, .todo = TRUE),
2489 /* more AAC decoder specific attributes from CODECAPI */
2490 {0},
2492 static const struct attribute_desc output_type_desc[] =
2494 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2495 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM, .required = TRUE),
2496 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1, .required = TRUE),
2497 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
2498 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .required = TRUE),
2499 {0},
2501 const MFT_OUTPUT_STREAM_INFO output_info =
2503 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES,
2504 .cbSize = 0xc000,
2506 const MFT_INPUT_STREAM_INFO input_info =
2508 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
2509 MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE | MFT_INPUT_STREAM_HOLDS_BUFFERS,
2512 const struct buffer_desc output_buffer_desc[] =
2514 {.length = 0x800},
2516 const struct attribute_desc output_sample_attributes[] =
2518 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
2519 {0},
2521 const struct sample_desc output_sample_desc[] =
2524 .attributes = output_sample_attributes + (has_video_processor ? 0 : 1) /* MFSampleExtension_CleanPoint missing on Win7 */,
2525 .sample_time = 0, .sample_duration = 232200,
2526 .buffer_count = 1, .buffers = output_buffer_desc,
2530 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_Float};
2531 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_AAC};
2532 IMFSample *input_sample, *output_sample;
2533 ULONG i, ret, ref, aacenc_data_len;
2534 IMFCollection *output_samples;
2535 DWORD length, output_status;
2536 IMFMediaType *media_type;
2537 IMFTransform *transform;
2538 const BYTE *aacenc_data;
2539 DWORD flags;
2540 HRESULT hr;
2542 hr = CoInitialize(NULL);
2543 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
2545 winetest_push_context("aacdec");
2547 if (!check_mft_enum(MFT_CATEGORY_AUDIO_DECODER, &input_type, &output_type, class_id))
2548 goto failed;
2549 check_mft_get_info(class_id, &expect_mft_info);
2551 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
2552 &IID_IMFTransform, (void **)&transform)))
2553 goto failed;
2555 check_interface(transform, &IID_IMFTransform, TRUE);
2556 check_interface(transform, &IID_IMediaObject, FALSE);
2557 check_interface(transform, &IID_IPropertyStore, FALSE);
2558 check_interface(transform, &IID_IPropertyBag, FALSE);
2560 check_mft_optional_methods(transform, 1);
2561 check_mft_get_attributes(transform, expect_transform_attributes, FALSE);
2562 check_mft_get_input_stream_info(transform, S_OK, &input_info);
2563 check_mft_get_output_stream_info(transform, S_OK, &output_info);
2565 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
2566 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
2568 i = -1;
2569 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
2571 winetest_push_context("in %lu", i);
2572 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
2573 check_media_type(media_type, expect_input_attributes, -1);
2574 check_media_type(media_type, expect_available_inputs[i], -1);
2575 ret = IMFMediaType_Release(media_type);
2576 ok(ret <= 1, "Release returned %lu\n", ret);
2577 winetest_pop_context();
2579 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
2580 ok(i == ARRAY_SIZE(expect_available_inputs)
2581 || broken(i == 2) /* w7 */ || broken(i == 4) /* w8 */,
2582 "%lu input media types\n", i);
2584 /* setting output media type first doesn't work */
2585 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
2586 check_mft_get_output_current_type(transform, NULL);
2588 check_mft_set_input_type_required(transform, input_type_desc);
2589 check_mft_set_input_type(transform, input_type_desc);
2590 check_mft_get_input_current_type(transform, input_type_desc);
2592 /* check new output media types */
2594 i = -1;
2595 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
2597 winetest_push_context("out %lu", i);
2598 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
2599 check_media_type(media_type, expect_output_attributes, -1);
2600 check_media_type(media_type, expect_available_outputs[i], -1);
2601 ret = IMFMediaType_Release(media_type);
2602 ok(ret <= 1, "Release returned %lu\n", ret);
2603 winetest_pop_context();
2605 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
2606 ok(i == ARRAY_SIZE(expect_available_outputs), "%lu input media types\n", i);
2608 check_mft_set_output_type_required(transform, output_type_desc);
2609 check_mft_set_output_type(transform, output_type_desc, S_OK);
2610 check_mft_get_output_current_type(transform, output_type_desc);
2612 check_mft_get_input_stream_info(transform, S_OK, &input_info);
2613 check_mft_get_output_stream_info(transform, S_OK, &output_info);
2615 load_resource(L"aacencdata.bin", &aacenc_data, &aacenc_data_len);
2616 ok(aacenc_data_len == 24861, "got length %lu\n", aacenc_data_len);
2618 input_sample = create_sample(aacenc_data + sizeof(DWORD), *(DWORD *)aacenc_data);
2620 flags = 0;
2621 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
2622 ok(hr == S_OK, "Got %#lx\n", hr);
2623 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Got flags %#lx.\n", flags);
2624 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2625 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2626 flags = 0xdeadbeef;
2627 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
2628 ok(hr == S_OK, "Got %#lx\n", hr);
2629 ok(!flags, "Got flags %#lx.\n", flags);
2630 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2631 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2632 flags = 0xdeadbeef;
2633 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
2634 ok(hr == S_OK, "Got %#lx\n", hr);
2635 ok(!flags, "Got flags %#lx.\n", flags);
2637 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
2638 * IMFTransform_ProcessOutput needs a sample or returns MF_E_TRANSFORM_NEED_MORE_INPUT */
2640 hr = check_mft_process_output(transform, NULL, &output_status);
2641 ok(hr == E_INVALIDARG, "ProcessOutput returned %#lx\n", hr);
2642 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
2643 flags = 0xdeadbeef;
2644 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
2645 ok(hr == S_OK, "Got %#lx\n", hr);
2646 ok(!flags, "Got flags %#lx.\n", flags);
2647 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2648 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2650 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
2651 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
2652 flags = 0xdeadbeef;
2653 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
2654 ok(hr == S_OK, "Got %#lx\n", hr);
2655 ok(!flags, "Got flags %#lx.\n", flags);
2656 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2657 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2659 hr = MFCreateCollection(&output_samples);
2660 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
2662 output_sample = create_sample(NULL, output_info.cbSize);
2663 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
2665 winetest_push_context("%lu", i);
2666 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
2667 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
2668 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
2669 ref = IMFSample_Release(output_sample);
2670 ok(ref == 1, "Release returned %ld\n", ref);
2671 output_sample = create_sample(NULL, output_info.cbSize);
2672 winetest_pop_context();
2674 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2676 flags = 0;
2677 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
2678 ok(hr == S_OK, "Got %#lx\n", hr);
2679 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Got flags %#lx.\n", flags);
2681 ok(output_status == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE, "got output[0].dwStatus %#lx\n", output_status);
2682 ret = IMFSample_Release(output_sample);
2683 ok(ret == 0, "Release returned %lu\n", ret);
2684 ok(i == 1, "got %lu output samples\n", i);
2686 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"aacdecdata.bin");
2687 todo_wine_if(ret <= 5)
2688 ok(ret == 0, "got %lu%% diff\n", ret);
2689 IMFCollection_Release(output_samples);
2691 output_sample = create_sample(NULL, output_info.cbSize);
2692 hr = check_mft_process_output(transform, output_sample, &output_status);
2693 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2694 ok(output_status == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE, "got output[0].dwStatus %#lx\n", output_status);
2695 hr = IMFSample_GetTotalLength(output_sample, &length);
2696 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
2697 ok(length == 0, "got length %lu\n", length);
2698 ret = IMFSample_Release(output_sample);
2699 ok(ret == 0, "Release returned %lu\n", ret);
2701 ret = IMFSample_Release(input_sample);
2702 ok(ret == 0, "Release returned %lu\n", ret);
2703 ret = IMFTransform_Release(transform);
2704 ok(ret == 0, "Release returned %lu\n", ret);
2706 failed:
2707 winetest_pop_context();
2708 CoUninitialize();
2711 static void test_aac_decoder(void)
2713 static const BYTE aac_raw_codec_data[] = {0x12, 0x08};
2714 static const struct attribute_desc raw_aac_input_type_desc[] =
2716 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2717 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_RAW_AAC1, .required = TRUE),
2718 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .required = TRUE),
2719 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2720 ATTR_BLOB(MF_MT_USER_DATA, aac_raw_codec_data, sizeof(aac_raw_codec_data), .required = TRUE),
2721 {0},
2723 static const struct attribute_desc aac_input_type_desc[] =
2725 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2726 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_AAC, .required = TRUE),
2727 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .required = TRUE),
2728 ATTR_BLOB(MF_MT_USER_DATA, aac_codec_data, sizeof(aac_codec_data), .required = TRUE),
2729 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
2730 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
2731 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 12000),
2732 ATTR_UINT32(MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 41),
2733 ATTR_UINT32(MF_MT_AAC_PAYLOAD_TYPE, 0),
2734 {0},
2737 test_aac_decoder_subtype(aac_input_type_desc);
2738 test_aac_decoder_subtype(raw_aac_input_type_desc);
2741 static const BYTE wma_codec_data[10] = {0, 0x44, 0, 0, 0x17, 0, 0, 0, 0, 0};
2742 static const ULONG wmaenc_block_size = 1487;
2743 static const ULONG wmadec_block_size = 0x2000;
2745 static void test_wma_encoder(void)
2747 const GUID *const class_id = &CLSID_CWMAEncMediaObject;
2748 const struct transform_info expect_mft_info =
2750 .name = L"WMAudio Encoder MFT",
2751 .major_type = &MFMediaType_Audio,
2752 .inputs =
2754 {.subtype = &MFAudioFormat_PCM},
2755 {.subtype = &MFAudioFormat_Float},
2757 .outputs =
2759 {.subtype = &MFAudioFormat_WMAudioV8},
2760 {.subtype = &MFAudioFormat_WMAudioV9},
2761 {.subtype = &MFAudioFormat_WMAudio_Lossless},
2764 const struct transform_info expect_dmo_info =
2766 .name = L"WMAudio Encoder DMO",
2767 .major_type = &MEDIATYPE_Audio,
2768 .inputs =
2770 {.subtype = &MEDIASUBTYPE_PCM},
2772 .outputs =
2774 {.subtype = &MEDIASUBTYPE_WMAUDIO2},
2775 {.subtype = &MEDIASUBTYPE_WMAUDIO3},
2776 {.subtype = &MEDIASUBTYPE_WMAUDIO_LOSSLESS},
2780 static const struct attribute_desc input_type_desc[] =
2782 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2783 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float, .required = TRUE),
2784 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
2785 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32, .required = TRUE),
2786 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
2787 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2 * (32 / 8), .required = TRUE),
2788 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * (32 / 8) * 22050, .required = TRUE),
2789 {0},
2791 const struct attribute_desc output_type_desc[] =
2793 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
2794 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8, .required = TRUE),
2795 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
2796 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
2797 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003, .required = TRUE),
2798 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size, .required = TRUE),
2799 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data), .required = TRUE),
2800 {0},
2802 static const struct attribute_desc expect_input_type_desc[] =
2804 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2805 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
2806 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
2807 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2808 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
2809 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
2810 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 22050 * 8),
2811 ATTR_UINT32(MF_MT_AUDIO_CHANNEL_MASK, 3),
2812 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
2813 {0},
2815 const struct attribute_desc expect_output_type_desc[] =
2817 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
2818 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
2819 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
2820 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
2821 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003),
2822 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size),
2823 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)),
2824 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
2825 {0},
2827 const MFT_OUTPUT_STREAM_INFO output_info =
2829 .cbSize = wmaenc_block_size,
2830 .cbAlignment = 1,
2832 const MFT_INPUT_STREAM_INFO input_info =
2834 .hnsMaxLatency = 19969161,
2835 .cbSize = 8,
2836 .cbAlignment = 1,
2839 const struct buffer_desc output_buffer_desc[] =
2841 {.length = wmaenc_block_size},
2843 const struct attribute_desc output_sample_attributes[] =
2845 ATTR_UINT32(mft_output_sample_incomplete, 1),
2846 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
2847 {0},
2849 const struct sample_desc output_sample_desc[] =
2852 .attributes = output_sample_attributes,
2853 .sample_time = 0, .sample_duration = 3250794,
2854 .buffer_count = 1, .buffers = output_buffer_desc,
2857 .attributes = output_sample_attributes,
2858 .sample_time = 3250794, .sample_duration = 3715193,
2859 .buffer_count = 1, .buffers = output_buffer_desc,
2862 .attributes = output_sample_attributes,
2863 .sample_time = 6965986, .sample_duration = 3366893,
2864 .buffer_count = 1, .buffers = output_buffer_desc,
2868 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8};
2869 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_Float};
2870 IMFSample *input_sample, *output_sample;
2871 IMFCollection *output_samples;
2872 DWORD length, output_status;
2873 IMFMediaType *media_type;
2874 IMFTransform *transform;
2875 const BYTE *audio_data;
2876 ULONG audio_data_len;
2877 ULONG i, ret;
2878 HRESULT hr;
2879 LONG ref;
2881 hr = CoInitialize(NULL);
2882 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
2884 winetest_push_context("wmaenc");
2886 if (!check_mft_enum(MFT_CATEGORY_AUDIO_ENCODER, &input_type, &output_type, class_id))
2887 goto failed;
2888 check_mft_get_info(class_id, &expect_mft_info);
2889 check_dmo_get_info(class_id, &expect_dmo_info);
2891 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
2892 &IID_IMFTransform, (void **)&transform)))
2893 goto failed;
2895 check_interface(transform, &IID_IMFTransform, TRUE);
2896 check_interface(transform, &IID_IMediaObject, TRUE);
2897 check_interface(transform, &IID_IPropertyStore, TRUE);
2898 check_interface(transform, &IID_IPropertyBag, TRUE);
2900 check_mft_optional_methods(transform, 1);
2901 check_mft_get_attributes(transform, NULL, FALSE);
2902 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
2903 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
2905 check_mft_set_input_type_required(transform, input_type_desc);
2907 hr = MFCreateMediaType(&media_type);
2908 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
2909 init_media_type(media_type, input_type_desc, -1);
2910 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
2911 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
2912 ret = IMFMediaType_Release(media_type);
2913 ok(ret == 0, "Release returned %lu\n", ret);
2915 check_mft_set_output_type_required(transform, output_type_desc);
2916 check_mft_set_output_type(transform, output_type_desc, S_OK);
2917 check_mft_get_output_current_type(transform, expect_output_type_desc);
2919 check_mft_set_input_type_required(transform, input_type_desc);
2920 check_mft_set_input_type(transform, input_type_desc);
2921 check_mft_get_input_current_type(transform, expect_input_type_desc);
2923 check_mft_get_input_stream_info(transform, S_OK, &input_info);
2924 check_mft_get_output_stream_info(transform, S_OK, &output_info);
2926 load_resource(L"audiodata.bin", &audio_data, &audio_data_len);
2927 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
2929 input_sample = create_sample(audio_data, audio_data_len);
2930 hr = IMFSample_SetSampleTime(input_sample, 0);
2931 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
2932 hr = IMFSample_SetSampleDuration(input_sample, 10000000);
2933 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
2934 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2935 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
2936 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
2937 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
2938 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
2939 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
2940 ref = IMFSample_Release(input_sample);
2941 ok(ref <= 1, "Release returned %ld\n", ref);
2943 hr = MFCreateCollection(&output_samples);
2944 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
2946 output_sample = create_sample(NULL, output_info.cbSize);
2947 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
2949 winetest_push_context("%lu", i);
2950 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
2951 ok(output_status == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE, "got output[0].dwStatus %#lx\n", output_status);
2952 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
2953 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
2954 ref = IMFSample_Release(output_sample);
2955 ok(ref == 1, "Release returned %ld\n", ref);
2956 output_sample = create_sample(NULL, output_info.cbSize);
2957 winetest_pop_context();
2959 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2960 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
2961 ret = IMFSample_Release(output_sample);
2962 ok(ret == 0, "Release returned %lu\n", ret);
2963 ok(i == 3, "got %lu output samples\n", i);
2965 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"wmaencdata.bin");
2966 ok(ret == 0, "got %lu%% diff\n", ret);
2967 IMFCollection_Release(output_samples);
2969 output_sample = create_sample(NULL, output_info.cbSize);
2970 hr = check_mft_process_output(transform, output_sample, &output_status);
2971 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
2972 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
2973 hr = IMFSample_GetTotalLength(output_sample, &length);
2974 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
2975 ok(length == 0, "got length %lu\n", length);
2976 ret = IMFSample_Release(output_sample);
2977 ok(ret == 0, "Release returned %lu\n", ret);
2979 ret = IMFTransform_Release(transform);
2980 ok(ret == 0, "Release returned %lu\n", ret);
2982 failed:
2983 winetest_pop_context();
2984 CoUninitialize();
2987 static void test_wma_decoder(void)
2989 const GUID *const class_id = &CLSID_CWMADecMediaObject;
2990 const struct transform_info expect_mft_info =
2992 .name = L"WMAudio Decoder MFT",
2993 .major_type = &MFMediaType_Audio,
2994 .inputs =
2996 {.subtype = &MEDIASUBTYPE_MSAUDIO1},
2997 {.subtype = &MFAudioFormat_WMAudioV8},
2998 {.subtype = &MFAudioFormat_WMAudioV9},
2999 {.subtype = &MFAudioFormat_WMAudio_Lossless},
3001 .outputs =
3003 {.subtype = &MFAudioFormat_PCM},
3004 {.subtype = &MFAudioFormat_Float},
3007 const struct transform_info expect_dmo_info =
3009 .name = L"WMAudio Decoder DMO",
3010 .major_type = &MEDIATYPE_Audio,
3011 .inputs =
3013 {.subtype = &MEDIASUBTYPE_MSAUDIO1},
3014 {.subtype = &MEDIASUBTYPE_WMAUDIO2},
3015 {.subtype = &MEDIASUBTYPE_WMAUDIO3},
3016 {.subtype = &MEDIASUBTYPE_WMAUDIO_LOSSLESS},
3018 .outputs =
3020 {.subtype = &MEDIASUBTYPE_PCM},
3021 {.subtype = &MEDIASUBTYPE_IEEE_FLOAT},
3025 static const media_type_desc expect_available_inputs[] =
3028 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3029 ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_MSAUDIO1),
3030 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3033 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3034 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
3035 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3038 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3039 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV9),
3040 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3043 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3044 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudio_Lossless),
3045 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3048 static const media_type_desc expect_available_outputs[] =
3051 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3052 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
3053 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
3054 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
3055 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
3056 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
3057 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
3058 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3059 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3060 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
3063 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3064 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
3065 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
3066 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
3067 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
3068 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
3069 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
3070 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3071 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3072 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
3076 const struct attribute_desc input_type_desc[] =
3078 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
3079 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8, .required = TRUE),
3080 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data), .required = TRUE),
3081 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size, .required = TRUE),
3082 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
3083 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
3084 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003), /* not required by SetInputType, but needed for the transform to work */
3085 {0},
3087 static const struct attribute_desc output_type_desc[] =
3089 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
3090 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM, .required = TRUE),
3091 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
3092 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
3093 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
3094 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2 * (16 / 8), .required = TRUE),
3095 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * (16 / 8) * 22050, .required = TRUE),
3096 {0},
3098 const struct attribute_desc expect_input_type_desc[] =
3100 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3101 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_WMAudioV8),
3102 ATTR_BLOB(MF_MT_USER_DATA, wma_codec_data, sizeof(wma_codec_data)),
3103 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, wmaenc_block_size),
3104 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
3105 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
3106 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 4003),
3107 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
3108 {0},
3110 static const struct attribute_desc expect_output_type_desc[] =
3112 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
3113 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
3114 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 22050 * 4),
3115 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
3116 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
3117 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
3118 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
3119 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
3120 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3121 {0},
3123 const MFT_INPUT_STREAM_INFO input_info =
3125 .cbSize = wmaenc_block_size,
3126 .cbAlignment = 1,
3128 const MFT_OUTPUT_STREAM_INFO output_info =
3130 .cbSize = wmadec_block_size,
3131 .cbAlignment = 1,
3134 const struct buffer_desc output_buffer_desc[] =
3136 {.length = wmadec_block_size, .compare = compare_pcm16},
3137 {.length = wmadec_block_size / 2, .compare = compare_pcm16, .todo_length = TRUE},
3139 const struct attribute_desc output_sample_attributes[] =
3141 ATTR_UINT32(mft_output_sample_incomplete, 1),
3142 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
3143 {0},
3145 const struct attribute_desc output_sample_attributes_todo[] =
3147 ATTR_UINT32(mft_output_sample_incomplete, 1, .todo = TRUE),
3148 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
3149 {0},
3151 struct sample_desc output_sample_desc[] =
3154 .attributes = output_sample_attributes + 0,
3155 .sample_time = 0, .sample_duration = 928798,
3156 .buffer_count = 1, .buffers = output_buffer_desc + 0, .repeat_count = 1,
3159 .attributes = output_sample_attributes + 0,
3160 .sample_time = 1857596, .sample_duration = 928798,
3161 .buffer_count = 1, .buffers = output_buffer_desc + 0,
3164 .attributes = output_sample_attributes + 1, /* not MFT_OUTPUT_DATA_BUFFER_INCOMPLETE */
3165 .sample_time = 2786394, .sample_duration = 464399, .todo_duration = 928798,
3166 .buffer_count = 1, .buffers = output_buffer_desc + 1, .todo_length = TRUE,
3170 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8};
3171 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_Float};
3172 IUnknown *unknown, *tmp_unknown, outer = {&test_unk_vtbl};
3173 IMFSample *input_sample, *output_sample;
3174 IMFCollection *output_samples;
3175 DWORD length, output_status;
3176 IMediaObject *media_object;
3177 IPropertyBag *property_bag;
3178 IMFMediaType *media_type;
3179 IMFTransform *transform;
3180 const BYTE *wmaenc_data;
3181 ULONG wmaenc_data_len;
3182 ULONG i, ret, ref;
3183 HRESULT hr;
3185 hr = CoInitialize(NULL);
3186 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
3188 winetest_push_context("wmadec");
3190 if (!check_mft_enum(MFT_CATEGORY_AUDIO_DECODER, &input_type, &output_type, class_id))
3191 goto failed;
3192 check_mft_get_info(class_id, &expect_mft_info);
3193 check_dmo_get_info(class_id, &expect_dmo_info);
3195 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
3196 &IID_IMFTransform, (void **)&transform)))
3197 goto failed;
3199 check_interface(transform, &IID_IMFTransform, TRUE);
3200 check_interface(transform, &IID_IMediaObject, TRUE);
3201 todo_wine
3202 check_interface(transform, &IID_IPropertyStore, TRUE);
3203 check_interface(transform, &IID_IPropertyBag, TRUE);
3205 check_mft_optional_methods(transform, 1);
3206 check_mft_get_attributes(transform, NULL, FALSE);
3207 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
3208 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
3210 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
3211 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
3213 i = -1;
3214 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
3216 winetest_push_context("in %lu", i);
3217 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
3218 check_media_type(media_type, expect_available_inputs[i], -1);
3219 ret = IMFMediaType_Release(media_type);
3220 ok(ret == 0, "Release returned %lu\n", ret);
3221 winetest_pop_context();
3223 todo_wine
3224 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
3225 todo_wine
3226 ok(i == 4, "%lu input media types\n", i);
3228 /* setting output media type first doesn't work */
3229 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
3230 check_mft_get_output_current_type_(transform, NULL, TRUE, FALSE);
3232 check_mft_set_input_type_required(transform, input_type_desc);
3233 check_mft_set_input_type(transform, input_type_desc);
3234 check_mft_get_input_current_type_(transform, expect_input_type_desc, TRUE, FALSE);
3236 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
3237 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
3239 /* check new output media types */
3241 i = -1;
3242 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
3244 winetest_push_context("out %lu", i);
3245 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3246 check_media_type(media_type, expect_available_outputs[i], -1);
3247 ret = IMFMediaType_Release(media_type);
3248 ok(ret == 0, "Release returned %lu\n", ret);
3249 winetest_pop_context();
3251 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3252 ok(i == 2, "%lu output media types\n", i);
3254 check_mft_set_output_type_required(transform, output_type_desc);
3255 check_mft_set_output_type(transform, output_type_desc, S_OK);
3256 check_mft_get_output_current_type_(transform, expect_output_type_desc, TRUE, FALSE);
3258 check_mft_get_input_stream_info(transform, S_OK, &input_info);
3259 check_mft_get_output_stream_info(transform, S_OK, &output_info);
3261 load_resource(L"wmaencdata.bin", &wmaenc_data, &wmaenc_data_len);
3262 ok(wmaenc_data_len % wmaenc_block_size == 0, "got length %lu\n", wmaenc_data_len);
3264 input_sample = create_sample(wmaenc_data, wmaenc_block_size / 2);
3265 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3266 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3267 ret = IMFSample_Release(input_sample);
3268 ok(ret == 0, "Release returned %lu\n", ret);
3269 input_sample = create_sample(wmaenc_data, wmaenc_block_size + 1);
3270 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3271 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3272 ret = IMFSample_Release(input_sample);
3273 ok(ret == 0, "Release returned %lu\n", ret);
3274 input_sample = create_sample(wmaenc_data, wmaenc_block_size);
3275 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3276 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3277 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3278 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
3279 ret = IMFSample_Release(input_sample);
3280 ok(ret == 1, "Release returned %lu\n", ret);
3282 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
3283 * IMFTransform_ProcessOutput needs a sample or returns MF_E_TRANSFORM_NEED_MORE_INPUT */
3285 hr = check_mft_process_output(transform, NULL, &output_status);
3286 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3287 ok(output_status == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE
3288 || broken(output_status == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
3289 "got output[0].dwStatus %#lx\n", output_status);
3291 input_sample = create_sample(wmaenc_data, wmaenc_block_size);
3292 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3293 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
3294 ret = IMFSample_Release(input_sample);
3295 ok(ret == 0, "Release returned %lu\n", ret);
3297 hr = check_mft_process_output(transform, NULL, &output_status);
3298 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3299 ok(output_status == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE
3300 || broken(output_status == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */,
3301 "got output[0].dwStatus %#lx\n", output_status);
3303 hr = MFCreateCollection(&output_samples);
3304 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
3306 output_sample = create_sample(NULL, output_info.cbSize);
3307 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
3309 winetest_push_context("%lu", i);
3310 ok(!(output_status & ~MFT_OUTPUT_DATA_BUFFER_INCOMPLETE), "got output[0].dwStatus %#lx\n", output_status);
3311 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
3312 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
3313 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
3314 ref = IMFSample_Release(output_sample);
3315 ok(ref == 1, "Release returned %ld\n", ref);
3316 output_sample = create_sample(NULL, output_info.cbSize);
3317 winetest_pop_context();
3319 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3320 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3321 ret = IMFSample_Release(output_sample);
3322 ok(ret == 0, "Release returned %lu\n", ret);
3323 todo_wine_if(i == 3) /* wmadec output depends on ffmpeg version used */
3324 ok(i == 4, "got %lu output samples\n", i);
3326 if (!strcmp(winetest_platform, "wine") && i == 3)
3327 output_sample_desc[1].attributes = output_sample_attributes_todo;
3329 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"wmadecdata.bin");
3330 todo_wine_if(ret > 0 && ret <= 10) /* ffmpeg sometimes offsets the decoded data */
3331 ok(ret == 0, "got %lu%% diff\n", ret);
3332 IMFCollection_Release(output_samples);
3334 output_sample = create_sample(NULL, output_info.cbSize);
3335 hr = check_mft_process_output(transform, output_sample, &output_status);
3336 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3337 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3338 hr = IMFSample_GetTotalLength(output_sample, &length);
3339 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
3340 ok(length == 0, "got length %lu\n", length);
3341 ret = IMFSample_Release(output_sample);
3342 ok(ret == 0, "Release returned %lu\n", ret);
3344 input_sample = create_sample(wmaenc_data, wmaenc_block_size);
3345 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3346 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3348 ret = IMFTransform_Release(transform);
3349 ok(ret == 0, "Release returned %lu\n", ret);
3350 ret = IMFSample_Release(input_sample);
3351 ok(ret == 0, "Release returned %lu\n", ret);
3353 hr = CoCreateInstance( &CLSID_CWMADecMediaObject, &outer, CLSCTX_INPROC_SERVER, &IID_IUnknown,
3354 (void **)&unknown );
3355 ok( hr == S_OK, "CoCreateInstance returned %#lx\n", hr );
3356 hr = IUnknown_QueryInterface( unknown, &IID_IMFTransform, (void **)&transform );
3357 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
3358 hr = IUnknown_QueryInterface( unknown, &IID_IMediaObject, (void **)&media_object );
3359 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
3360 hr = IUnknown_QueryInterface( unknown, &IID_IPropertyBag, (void **)&property_bag );
3361 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
3362 hr = IUnknown_QueryInterface( media_object, &IID_IUnknown, (void **)&tmp_unknown );
3363 ok( hr == S_OK, "QueryInterface returned %#lx\n", hr );
3365 ok( unknown != &outer, "got outer IUnknown\n" );
3366 ok( transform != (void *)unknown, "got IUnknown == IMFTransform\n" );
3367 ok( media_object != (void *)unknown, "got IUnknown == IMediaObject\n" );
3368 ok( property_bag != (void *)unknown, "got IUnknown == IPropertyBag\n" );
3369 ok( tmp_unknown != unknown, "got inner IUnknown\n" );
3371 check_interface( unknown, &IID_IPersistPropertyBag, FALSE );
3372 check_interface( unknown, &IID_IAMFilterMiscFlags, FALSE );
3373 check_interface( unknown, &IID_IMediaSeeking, FALSE );
3374 check_interface( unknown, &IID_IMediaPosition, FALSE );
3375 check_interface( unknown, &IID_IReferenceClock, FALSE );
3376 check_interface( unknown, &IID_IBasicAudio, FALSE );
3378 ref = IUnknown_Release( tmp_unknown );
3379 ok( ref == 1, "Release returned %lu\n", ref );
3380 ref = IPropertyBag_Release( property_bag );
3381 ok( ref == 1, "Release returned %lu\n", ref );
3382 ref = IMediaObject_Release( media_object );
3383 ok( ref == 1, "Release returned %lu\n", ref );
3384 ref = IMFTransform_Release( transform );
3385 ok( ref == 1, "Release returned %lu\n", ref );
3386 ref = IUnknown_Release( unknown );
3387 ok( ref == 0, "Release returned %lu\n", ref );
3389 failed:
3390 winetest_pop_context();
3391 CoUninitialize();
3394 #define next_h264_sample(a, b) next_h264_sample_(__LINE__, a, b)
3395 static IMFSample *next_h264_sample_(int line, const BYTE **h264_buf, ULONG *h264_len)
3397 const BYTE *sample_data;
3399 ok_(__FILE__, line)(*h264_len > 4, "invalid h264 length\n");
3400 ok_(__FILE__, line)(*(UINT32 *)*h264_buf == 0x01000000, "invalid h264 buffer\n");
3401 sample_data = *h264_buf;
3403 (*h264_len) -= 4;
3404 (*h264_buf) += 4;
3406 while (*h264_len >= 4 && *(UINT32 *)*h264_buf != 0x01000000)
3408 (*h264_len)--;
3409 (*h264_buf)++;
3412 return create_sample(sample_data, *h264_buf - sample_data);
3415 static void test_h264_decoder(void)
3417 const GUID *const class_id = &CLSID_MSH264DecoderMFT;
3418 const struct transform_info expect_mft_info =
3420 .name = L"Microsoft H264 Video Decoder MFT",
3421 .major_type = &MFMediaType_Video,
3422 .inputs =
3424 {.subtype = &MFVideoFormat_H264},
3425 {.subtype = &MFVideoFormat_H264_ES},
3427 .outputs =
3429 {.subtype = &MFVideoFormat_NV12},
3430 {.subtype = &MFVideoFormat_YV12},
3431 {.subtype = &MFVideoFormat_IYUV},
3432 {.subtype = &MFVideoFormat_I420},
3433 {.subtype = &MFVideoFormat_YUY2},
3436 static const media_type_desc default_inputs[] =
3439 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3440 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
3443 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3444 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264_ES),
3447 static const struct attribute_desc expect_transform_attributes[] =
3449 ATTR_UINT32(MF_LOW_LATENCY, 0),
3450 ATTR_UINT32(MF_SA_D3D_AWARE, 1, .todo = TRUE),
3451 ATTR_UINT32(MF_SA_D3D11_AWARE, 1),
3452 ATTR_UINT32(MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER, 0, .todo = TRUE),
3453 /* more H264 decoder specific attributes from CODECAPI */
3454 {0},
3456 static const DWORD input_width = 120, input_height = 248;
3457 const media_type_desc default_outputs[] =
3460 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3461 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
3462 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3463 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
3464 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
3465 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3466 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3467 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3468 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
3469 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
3470 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3473 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3474 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
3475 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3476 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
3477 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
3478 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3479 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3480 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3481 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
3482 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
3483 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3486 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3487 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
3488 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3489 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
3490 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
3491 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3492 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3493 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3494 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
3495 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
3496 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3499 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3500 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
3501 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3502 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
3503 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width),
3504 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3505 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3506 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3507 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
3508 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 3 / 2),
3509 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3512 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3513 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
3514 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3515 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
3516 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, input_width * 2),
3517 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3518 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3519 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3520 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
3521 ATTR_UINT32(MF_MT_SAMPLE_SIZE, input_width * input_height * 2),
3522 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3525 const struct attribute_desc input_type_desc[] =
3527 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
3528 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264, .required = TRUE),
3529 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
3530 {0},
3532 const struct attribute_desc output_type_desc[] =
3534 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
3535 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE),
3536 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height, .required = TRUE),
3537 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
3538 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 2, 1),
3539 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
3540 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * input_height * 3 / 2),
3541 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
3542 {0},
3544 const struct attribute_desc expect_input_type_desc[] =
3546 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3547 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_H264),
3548 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
3549 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 0),
3550 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 0),
3551 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 0),
3552 ATTR_UINT32(MF_MT_AVG_BIT_ERROR_RATE, 0),
3553 ATTR_UINT32(MF_MT_COMPRESSED, 1),
3554 {0},
3556 const struct attribute_desc expect_output_type_desc[] =
3558 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3559 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
3560 ATTR_RATIO(MF_MT_FRAME_SIZE, input_width, input_height),
3561 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
3562 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 2, 1),
3563 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, 3840),
3564 ATTR_UINT32(MF_MT_SAMPLE_SIZE, 3840 * input_height * 3 / 2),
3565 ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0),
3566 ATTR_UINT32(MF_MT_AVG_BIT_ERROR_RATE, 0),
3567 ATTR_UINT32(MF_MT_COMPRESSED, 0),
3568 {0},
3570 static const struct attribute_desc new_output_type_desc[] =
3572 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3573 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
3574 ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96),
3575 ATTR_RATIO(MF_MT_FRAME_RATE, 1, 1),
3576 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 2),
3577 {0},
3579 static const struct attribute_desc expect_new_output_type_desc[] =
3581 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3582 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
3583 ATTR_RATIO(MF_MT_FRAME_SIZE, 96, 96),
3584 ATTR_RATIO(MF_MT_FRAME_RATE, 1, 1),
3585 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 2),
3586 ATTR_UINT32(MF_MT_COMPRESSED, 0),
3587 ATTR_UINT32(MF_MT_AVG_BIT_ERROR_RATE, 0),
3588 {0},
3590 static const MFVideoArea actual_aperture = {.Area={82,84}};
3591 static const DWORD actual_width = 96, actual_height = 96;
3592 const media_type_desc actual_outputs[] =
3595 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3596 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
3597 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3598 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
3599 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3600 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
3601 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
3602 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3603 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3604 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3605 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3606 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
3609 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3610 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
3611 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3612 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
3613 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3614 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
3615 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
3616 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3617 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3618 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3619 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3620 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
3623 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3624 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
3625 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3626 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
3627 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3628 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
3629 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
3630 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3631 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3632 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3633 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3634 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
3637 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3638 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
3639 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3640 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
3641 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3642 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
3643 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
3644 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3645 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3646 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3647 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3648 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
3651 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
3652 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
3653 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
3654 ATTR_RATIO(MF_MT_FRAME_RATE, 60000, 1000),
3655 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
3656 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
3657 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
3658 /* ATTR_UINT32(MF_MT_VIDEO_ROTATION, 0), missing on Win7 */
3659 ATTR_UINT32(MF_MT_INTERLACE_MODE, 7),
3660 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
3661 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
3662 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
3665 const MFT_OUTPUT_STREAM_INFO initial_output_info =
3667 .dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
3668 MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE,
3669 .cbSize = 1920 * 1088 * 2,
3671 const MFT_OUTPUT_STREAM_INFO output_info =
3673 .dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
3674 MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE,
3675 .cbSize = input_width * input_height * 2,
3677 const MFT_OUTPUT_STREAM_INFO actual_output_info =
3679 .dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
3680 MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE,
3681 .cbSize = actual_width * actual_height * 2,
3683 const MFT_INPUT_STREAM_INFO input_info =
3685 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER |
3686 MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE,
3687 .cbSize = 0x1000,
3690 const struct attribute_desc output_sample_attributes[] =
3692 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
3693 {0},
3695 const struct buffer_desc output_buffer_desc_nv12 =
3697 .length = actual_width * actual_height * 3 / 2,
3698 .compare = compare_nv12, .dump = dump_nv12, .rect = {.right = 82, .bottom = 84},
3700 const struct sample_desc output_sample_desc_nv12 =
3702 .attributes = output_sample_attributes,
3703 .sample_time = 0, .sample_duration = 333667,
3704 .buffer_count = 1, .buffers = &output_buffer_desc_nv12,
3706 const struct buffer_desc output_buffer_desc_i420 =
3708 .length = actual_width * actual_height * 3 / 2,
3709 .compare = compare_i420, .dump = dump_i420, .rect = {.right = 82, .bottom = 84},
3711 const struct sample_desc expect_output_sample_i420 =
3713 .attributes = output_sample_attributes,
3714 .sample_time = 333667, .sample_duration = 333667,
3715 .buffer_count = 1, .buffers = &output_buffer_desc_i420,
3718 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_H264};
3719 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
3720 IMFSample *input_sample, *output_sample;
3721 const BYTE *h264_encoded_data;
3722 IMFCollection *output_samples;
3723 ULONG h264_encoded_data_len;
3724 DWORD length, output_status;
3725 IMFAttributes *attributes;
3726 IMFMediaType *media_type;
3727 IMFTransform *transform;
3728 ULONG i, ret, ref;
3729 DWORD flags;
3730 HRESULT hr;
3732 hr = CoInitialize(NULL);
3733 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
3735 winetest_push_context("h264dec");
3737 if (!check_mft_enum(MFT_CATEGORY_VIDEO_DECODER, &input_type, &output_type, class_id))
3738 goto failed;
3739 check_mft_get_info(class_id, &expect_mft_info);
3741 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
3742 &IID_IMFTransform, (void **)&transform)))
3743 goto failed;
3745 check_interface(transform, &IID_IMFTransform, TRUE);
3746 check_interface(transform, &IID_IMediaObject, FALSE);
3747 check_interface(transform, &IID_IPropertyStore, FALSE);
3748 check_interface(transform, &IID_IPropertyBag, FALSE);
3750 check_mft_optional_methods(transform, 1);
3751 check_mft_get_attributes(transform, expect_transform_attributes, TRUE);
3752 check_mft_get_input_stream_info(transform, S_OK, &input_info);
3753 check_mft_get_output_stream_info(transform, S_OK, &initial_output_info);
3755 hr = IMFTransform_GetAttributes(transform, &attributes);
3756 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
3757 hr = IMFAttributes_SetUINT32(attributes, &MF_LOW_LATENCY, 1);
3758 ok(hr == S_OK, "SetUINT32 returned %#lx\n", hr);
3759 IMFAttributes_Release(attributes);
3761 /* no output type is available before an input type is set */
3763 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
3764 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
3766 flags = 0xdeadbeef;
3767 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
3768 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Got %#lx\n", hr);
3769 ok(flags == 0xdeadbeef, "Got flags %#lx.\n", flags);
3771 /* setting output media type first doesn't work */
3772 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
3773 check_mft_get_output_current_type(transform, NULL);
3775 /* check available input types */
3777 i = -1;
3778 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
3780 winetest_push_context("in %lu", i);
3781 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
3782 check_media_type(media_type, default_inputs[i], -1);
3783 ret = IMFMediaType_Release(media_type);
3784 ok(ret == 0, "Release returned %lu\n", ret);
3785 winetest_pop_context();
3787 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
3788 ok(i == 2 || broken(i == 1) /* Win7 */, "%lu input media types\n", i);
3790 check_mft_set_input_type_required(transform, input_type_desc);
3791 check_mft_set_input_type(transform, input_type_desc);
3792 check_mft_get_input_current_type_(transform, expect_input_type_desc, TRUE, FALSE);
3794 check_mft_get_input_stream_info(transform, S_OK, &input_info);
3795 check_mft_get_output_stream_info(transform, S_OK, &output_info);
3797 /* output types can now be enumerated (though they are actually the same for all input types) */
3799 i = -1;
3800 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
3802 winetest_push_context("out %lu", i);
3803 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3804 check_media_type(media_type, default_outputs[i], -1);
3805 ret = IMFMediaType_Release(media_type);
3806 ok(ret == 0, "Release returned %lu\n", ret);
3807 winetest_pop_context();
3809 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3810 ok(i == 5, "%lu output media types\n", i);
3812 check_mft_set_output_type_required(transform, output_type_desc);
3813 check_mft_set_output_type(transform, output_type_desc, S_OK);
3814 check_mft_get_output_current_type_(transform, expect_output_type_desc, FALSE, TRUE);
3816 /* check that the output media type we've selected don't change the enumeration */
3818 i = -1;
3819 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
3821 winetest_push_context("out %lu", i);
3822 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3823 check_media_type(media_type, default_outputs[i], -1);
3824 ret = IMFMediaType_Release(media_type);
3825 ok(ret == 0, "Release returned %lu\n", ret);
3826 winetest_pop_context();
3828 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3829 ok(i == 5, "%lu output media types\n", i);
3831 check_mft_get_input_stream_info(transform, S_OK, &input_info);
3832 check_mft_get_output_stream_info(transform, S_OK, &output_info);
3834 load_resource(L"h264data.bin", &h264_encoded_data, &h264_encoded_data_len);
3836 /* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES
3837 * IMFTransform_ProcessOutput needs a sample or returns an error */
3839 hr = check_mft_process_output(transform, NULL, &output_status);
3840 ok(hr == E_INVALIDARG || hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3841 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3843 i = 0;
3844 input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
3845 while (1)
3847 output_sample = create_sample(NULL, output_info.cbSize);
3848 hr = check_mft_process_output(transform, output_sample, &output_status);
3849 if (hr != MF_E_TRANSFORM_NEED_MORE_INPUT) break;
3851 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3852 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3853 hr = IMFSample_GetTotalLength(output_sample, &length);
3854 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
3855 ok(length == 0, "got length %lu\n", length);
3856 ret = IMFSample_Release(output_sample);
3857 ok(ret == 0, "Release returned %lu\n", ret);
3859 flags = 0;
3860 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
3861 ok(hr == S_OK, "Got %#lx\n", hr);
3862 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Got flags %#lx.\n", flags);
3863 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3864 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3865 ret = IMFSample_Release(input_sample);
3866 ok(ret <= 1, "Release returned %lu\n", ret);
3867 input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
3869 flags = 0;
3870 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
3871 ok(hr == S_OK, "Got %#lx\n", hr);
3872 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Got flags %#lx.\n", flags);
3873 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3874 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3875 ret = IMFSample_Release(input_sample);
3876 ok(ret <= 1, "Release returned %lu\n", ret);
3877 input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
3878 i++;
3880 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
3881 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
3882 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
3883 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
3885 ok(i == 2, "got %lu iterations\n", i);
3886 ok(h264_encoded_data_len == 2425, "got h264_encoded_data_len %lu\n", h264_encoded_data_len);
3887 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
3888 ok(output_status == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got output[0].dwStatus %#lx\n", output_status);
3889 hr = IMFSample_GetTotalLength(output_sample, &length);
3890 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
3891 ok(length == 0, "got length %lu\n", length);
3892 ret = IMFSample_Release(output_sample);
3893 ok(ret == 0, "Release returned %lu\n", ret);
3895 check_mft_get_input_stream_info(transform, S_OK, &input_info);
3896 check_mft_get_output_stream_info(transform, S_OK, &actual_output_info);
3898 i = -1;
3899 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
3901 winetest_push_context("out %lu", i);
3902 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
3903 check_media_type(media_type, actual_outputs[i], -1);
3904 ret = IMFMediaType_Release(media_type);
3905 ok(ret == 0, "Release returned %lu\n", ret);
3906 winetest_pop_context();
3908 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
3909 ok(i == 5, "%lu output media types\n", i);
3911 /* current output type is still the one we selected */
3912 check_mft_get_output_current_type_(transform, expect_output_type_desc, FALSE, TRUE);
3914 hr = MFCreateCollection(&output_samples);
3915 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
3917 output_sample = create_sample(NULL, output_info.cbSize);
3918 hr = check_mft_process_output(transform, output_sample, &output_status);
3919 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
3920 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3921 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
3922 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
3923 ref = IMFSample_Release(output_sample);
3924 ok(ref == 1, "Release returned %ld\n", ref);
3926 ret = check_mf_sample_collection(output_samples, &output_sample_desc_nv12, L"nv12frame.bmp");
3927 ok(ret == 0, "got %lu%% diff\n", ret);
3928 IMFCollection_Release(output_samples);
3930 /* we can change it, but only with the correct frame size */
3931 hr = MFCreateMediaType(&media_type);
3932 ok(hr == S_OK, "MFCreateMediaType returned %#lx\n", hr);
3933 init_media_type(media_type, output_type_desc, -1);
3934 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3935 ok(hr == MF_E_INVALIDMEDIATYPE, "SetOutputType returned %#lx.\n", hr);
3936 init_media_type(media_type, new_output_type_desc, -1);
3937 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
3938 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
3939 ret = IMFMediaType_Release(media_type);
3940 ok(ret == 1, "Release returned %lu\n", ret);
3942 check_mft_get_output_current_type_(transform, expect_new_output_type_desc, FALSE, TRUE);
3944 output_sample = create_sample(NULL, actual_width * actual_height * 2);
3945 hr = check_mft_process_output(transform, output_sample, &output_status);
3946 todo_wine
3947 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
3948 todo_wine
3949 ok(output_status == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got output[0].dwStatus %#lx\n", output_status);
3951 while (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
3953 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3954 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
3955 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
3956 ret = IMFSample_Release(input_sample);
3957 ok(ret <= 1, "Release returned %lu\n", ret);
3958 input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
3959 hr = check_mft_process_output(transform, output_sample, &output_status);
3962 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
3963 ok(output_status == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got output[0].dwStatus %#lx\n", output_status);
3965 hr = IMFSample_GetTotalLength(output_sample, &length);
3966 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
3967 ok(length == 0, "got length %lu\n", length);
3968 ret = IMFSample_Release(output_sample);
3969 ok(ret == 0, "Release returned %lu\n", ret);
3971 hr = MFCreateCollection(&output_samples);
3972 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
3974 output_sample = create_sample(NULL, actual_width * actual_height * 2);
3975 hr = check_mft_process_output(transform, output_sample, &output_status);
3976 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
3977 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3978 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
3979 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
3980 ref = IMFSample_Release(output_sample);
3981 ok(ref == 1, "Release returned %ld\n", ref);
3983 ret = check_mf_sample_collection(output_samples, &expect_output_sample_i420, L"i420frame.bmp");
3984 todo_wine /* wg_transform_set_output_format() should convert already processed samples instead of dropping */
3985 ok(ret == 0, "got %lu%% diff\n", ret);
3986 IMFCollection_Release(output_samples);
3988 output_sample = create_sample(NULL, actual_width * actual_height * 2);
3989 hr = check_mft_process_output(transform, output_sample, &output_status);
3990 todo_wine_if(hr == S_OK) /* when VA-API plugin is used */
3991 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
3992 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
3993 ret = IMFSample_Release(output_sample);
3994 ok(ret == 0, "Release returned %lu\n", ret);
3998 flags = 0;
3999 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
4000 ok(hr == S_OK, "Got %#lx\n", hr);
4001 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Got flags %#lx.\n", flags);
4002 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
4003 ok(hr == S_OK || hr == MF_E_NOTACCEPTING, "Got %#lx\n", hr);
4004 input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
4005 } while (hr == S_OK);
4007 ok(hr == MF_E_NOTACCEPTING, "Got %#lx\n", hr);
4008 flags = 0;
4009 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
4010 ok(hr == S_OK, "Got %#lx\n", hr);
4011 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Got flags %#lx.\n", flags);
4013 ret = IMFTransform_Release(transform);
4014 ok(ret == 0, "Release returned %lu\n", ret);
4015 ret = IMFSample_Release(input_sample);
4016 ok(ret == 0, "Release returned %lu\n", ret);
4018 failed:
4019 winetest_pop_context();
4020 CoUninitialize();
4023 static void test_h264_decoder_concat_streams(void)
4025 const struct buffer_desc output_buffer_desc[] =
4027 {.length = 0x3600},
4028 {.length = 0x4980},
4029 {.length = 0, .todo_length = TRUE},
4031 const struct attribute_desc output_sample_attributes[] =
4033 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
4034 {0},
4036 const struct sample_desc output_sample_desc[] =
4039 .attributes = output_sample_attributes + 0,
4040 .sample_time = 0, .sample_duration = 400000,
4041 .buffer_count = 1, .buffers = output_buffer_desc + 0, .repeat_count = 29,
4044 .attributes = output_sample_attributes + 0,
4045 .sample_time = 12000000, .sample_duration = 400000,
4046 .buffer_count = 1, .buffers = output_buffer_desc + 1, .repeat_count = 29,
4049 .attributes = output_sample_attributes + 0,
4050 .sample_time = 0, .sample_duration = 400000,
4051 .buffer_count = 1, .buffers = output_buffer_desc + 0, .repeat_count = 29,
4052 .todo_time = TRUE,
4055 .attributes = output_sample_attributes + 0,
4056 .sample_time = 12000000, .sample_duration = 400000,
4057 .buffer_count = 1, .buffers = output_buffer_desc + 1, .repeat_count = 6,
4058 .todo_time = TRUE,
4061 /* Wine outputs spurious buffers */
4062 .attributes = output_sample_attributes + 0,
4063 .sample_time = 0, .sample_duration = 400000,
4064 .buffer_count = 1, .buffers = output_buffer_desc + 2, .repeat_count = 22,
4065 .todo_time = TRUE, .todo_length = TRUE,
4067 {0},
4069 const WCHAR *filenames[] =
4071 L"h264data-1.bin",
4072 L"h264data-2.bin",
4073 L"h264data-1.bin",
4074 L"h264data-2.bin",
4075 NULL,
4077 DWORD output_status, input_count, output_count;
4078 const WCHAR **filename = filenames;
4079 const BYTE *h264_encoded_data;
4080 IMFCollection *output_samples;
4081 ULONG h264_encoded_data_len;
4082 IMFAttributes *attributes;
4083 IMFMediaType *media_type;
4084 IMFTransform *transform;
4085 IMFSample *input_sample;
4086 HRESULT hr;
4087 LONG ret;
4089 hr = CoInitialize(NULL);
4090 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
4092 if (FAILED(hr = CoCreateInstance(&CLSID_MSH264DecoderMFT, NULL, CLSCTX_INPROC_SERVER,
4093 &IID_IMFTransform, (void **)&transform)))
4094 goto failed;
4095 ok(hr == S_OK, "hr %#lx\n", hr);
4097 hr = IMFTransform_GetAttributes(transform, &attributes);
4098 ok(hr == S_OK, "GetAttributes returned %#lx\n", hr);
4099 hr = IMFAttributes_SetUINT32(attributes, &MF_LOW_LATENCY, 1);
4100 ok(hr == S_OK, "SetUINT32 returned %#lx\n", hr);
4101 IMFAttributes_Release(attributes);
4103 hr = IMFTransform_GetInputAvailableType(transform, 0, 0, &media_type);
4104 ok(hr == S_OK, "got %#lx\n", hr);
4105 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_RATE, (UINT64)25000 << 32 | 1000);
4106 ok(hr == S_OK, "got %#lx\n", hr);
4107 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
4108 ok(hr == S_OK, "got %#lx\n", hr);
4109 IMFMediaType_Release(media_type);
4111 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
4112 ok(hr == S_OK, "got %#lx\n", hr);
4113 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_RATE, (UINT64)50000 << 32 | 1000);
4114 ok(hr == S_OK, "got %#lx\n", hr);
4115 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
4116 ok(hr == S_OK, "got %#lx\n", hr);
4117 IMFMediaType_Release(media_type);
4119 load_resource(*filename, &h264_encoded_data, &h264_encoded_data_len);
4121 hr = MFCreateCollection(&output_samples);
4122 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
4124 input_count = 0;
4125 input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
4126 while (input_sample)
4128 MFT_OUTPUT_STREAM_INFO info = {0};
4130 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
4131 ok(hr == S_OK || hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
4133 if (hr == S_OK && input_count < 2)
4135 MFT_OUTPUT_DATA_BUFFER data = {.pSample = create_sample(NULL, 1)};
4136 hr = IMFTransform_ProcessOutput(transform, 0, 1, &data, &output_status);
4137 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
4138 IMFSample_Release(data.pSample);
4139 hr = S_OK;
4142 if (hr == S_OK)
4144 IMFSample_Release(input_sample);
4146 hr = IMFCollection_GetElementCount(output_samples, &output_count);
4147 ok(hr == S_OK, "GetElementCount returned %#lx\n", hr);
4149 if (output_count == 96)
4151 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_FLUSH, 0);
4152 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
4155 if (h264_encoded_data_len <= 4 && *++filename)
4157 load_resource(*filename, &h264_encoded_data, &h264_encoded_data_len);
4159 if (!wcscmp(*filename, L"h264data-1.bin"))
4161 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
4162 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
4166 if (h264_encoded_data_len > 4)
4168 input_count++;
4169 input_sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
4171 else
4173 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
4174 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
4175 input_sample = NULL;
4179 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &info);
4180 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
4182 while (hr != MF_E_TRANSFORM_NEED_MORE_INPUT)
4184 MFT_OUTPUT_DATA_BUFFER data = {.pSample = create_sample(NULL, info.cbSize)};
4186 hr = IMFTransform_ProcessOutput(transform, 0, 1, &data, &output_status);
4187 todo_wine_if(hr == 0xd0000001)
4188 ok(hr == S_OK || hr == MF_E_TRANSFORM_NEED_MORE_INPUT || hr == MF_E_TRANSFORM_STREAM_CHANGE,
4189 "ProcessOutput returned %#lx\n", hr);
4191 if (hr == S_OK)
4193 hr = IMFCollection_AddElement(output_samples, (IUnknown *)data.pSample);
4194 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
4196 if (hr == MF_E_TRANSFORM_STREAM_CHANGE)
4198 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
4199 ok(hr == S_OK, "got %#lx\n", hr);
4200 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_RATE, (UINT64)50000 << 32 | 1000);
4201 ok(hr == S_OK, "got %#lx\n", hr);
4202 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
4203 ok(hr == S_OK, "got %#lx\n", hr);
4204 IMFMediaType_Release(media_type);
4205 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &info);
4206 ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr);
4209 IMFSample_Release(data.pSample);
4213 hr = IMFCollection_GetElementCount(output_samples, &output_count);
4214 ok(hr == S_OK, "GetElementCount returned %#lx\n", hr);
4215 todo_wine
4216 ok(output_count == 96, "GetElementCount returned %#lx\n", output_count);
4218 ret = check_mf_sample_collection(output_samples, output_sample_desc, NULL);
4219 ok(ret == 0, "got %lu%% diff\n", ret);
4221 ret = IMFTransform_Release(transform);
4222 ok(ret == 0, "Release returned %lu\n", ret);
4224 failed:
4225 CoUninitialize();
4228 static void test_audio_convert(void)
4230 const GUID *const class_id = &CLSID_CResamplerMediaObject;
4231 const struct transform_info expect_mft_info =
4233 .name = L"Resampler MFT",
4234 .major_type = &MFMediaType_Audio,
4235 .inputs =
4237 {.subtype = &MFAudioFormat_PCM},
4238 {.subtype = &MFAudioFormat_Float},
4240 .outputs =
4242 {.subtype = &MFAudioFormat_PCM},
4243 {.subtype = &MFAudioFormat_Float},
4246 const struct transform_info expect_dmo_info =
4248 .name = L"Resampler DMO",
4249 .major_type = &MEDIATYPE_Audio,
4250 .inputs =
4252 {.subtype = &MEDIASUBTYPE_PCM},
4253 {.subtype = &MEDIASUBTYPE_IEEE_FLOAT},
4255 .outputs =
4257 {.subtype = &MEDIASUBTYPE_PCM},
4258 {.subtype = &MEDIASUBTYPE_IEEE_FLOAT},
4262 static const media_type_desc expect_available_inputs[] =
4265 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
4266 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
4267 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4270 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
4271 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
4272 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4275 static const media_type_desc expect_available_outputs[] =
4278 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
4279 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
4280 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4283 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
4284 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
4285 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4288 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
4289 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
4290 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
4291 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
4292 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
4293 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 384000),
4294 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
4295 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4296 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
4299 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
4300 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
4301 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
4302 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
4303 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000),
4304 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 192000),
4305 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
4306 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4307 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
4311 static const struct attribute_desc input_type_desc[] =
4313 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
4314 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float, .required = TRUE),
4315 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
4316 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32, .required = TRUE),
4317 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
4318 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2 * (32 / 8), .required = TRUE),
4319 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * (32 / 8) * 22050, .required = TRUE),
4320 {0},
4322 const struct attribute_desc output_type_desc[] =
4324 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
4325 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM, .required = TRUE),
4326 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
4327 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
4328 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100, .required = TRUE),
4329 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2 * (16 / 8), .required = TRUE),
4330 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * (16 / 8) * 44100, .required = TRUE),
4331 {0},
4333 static const struct attribute_desc expect_input_type_desc[] =
4335 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
4336 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
4337 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
4338 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
4339 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
4340 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
4341 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 22050 * 8),
4342 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4343 ATTR_UINT32(MF_MT_AUDIO_CHANNEL_MASK, 3),
4344 {0},
4346 const struct attribute_desc expect_output_type_desc[] =
4348 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
4349 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
4350 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
4351 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
4352 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100),
4353 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
4354 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100 * 4),
4355 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4356 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
4357 {0},
4359 const MFT_OUTPUT_STREAM_INFO output_info =
4361 .cbSize = 4,
4362 .cbAlignment = 1,
4364 const MFT_INPUT_STREAM_INFO input_info =
4366 .cbSize = 8,
4367 .cbAlignment = 1,
4370 static const ULONG audioconv_block_size = 0x4000;
4371 const struct buffer_desc output_buffer_desc[] =
4373 {.length = audioconv_block_size, .compare = compare_pcm16},
4374 {.length = 0x3dd8, .compare = compare_pcm16, .todo_length = TRUE},
4375 {.length = 0xfc, .compare = compare_pcm16},
4377 const struct attribute_desc output_sample_attributes[] =
4379 ATTR_UINT32(mft_output_sample_incomplete, 1),
4380 ATTR_UINT32(MFSampleExtension_CleanPoint, has_video_processor /* 0 on Win7 */, .todo = TRUE),
4381 {0},
4383 const struct sample_desc output_sample_desc[] =
4386 .attributes = output_sample_attributes + 0,
4387 .sample_time = 0, .sample_duration = 928798,
4388 .buffer_count = 1, .buffers = output_buffer_desc + 0, .repeat_count = 9,
4391 .attributes = output_sample_attributes + 1, /* not MFT_OUTPUT_DATA_BUFFER_INCOMPLETE */
4392 .sample_time = 9287980, .sample_duration = 897506, .todo_duration = 897280,
4393 .buffer_count = 1, .buffers = output_buffer_desc + 1, .todo_length = TRUE,
4396 .attributes = output_sample_attributes + 0,
4397 .sample_time = 10185486, .sample_duration = 14286,
4398 .buffer_count = 1, .buffers = output_buffer_desc + 2,
4402 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_PCM};
4403 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_Float};
4404 IMFSample *input_sample, *output_sample;
4405 IMFCollection *output_samples;
4406 DWORD length, output_status;
4407 IMFMediaType *media_type;
4408 IMFTransform *transform;
4409 const BYTE *audio_data;
4410 ULONG audio_data_len;
4411 ULONG i, ret, ref;
4412 HRESULT hr;
4414 hr = CoInitialize(NULL);
4415 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
4417 winetest_push_context("resampler");
4419 if (!check_mft_enum(MFT_CATEGORY_AUDIO_EFFECT, &input_type, &output_type, class_id))
4420 goto failed;
4421 check_mft_get_info(class_id, &expect_mft_info);
4422 check_dmo_get_info(class_id, &expect_dmo_info);
4424 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
4425 &IID_IMFTransform, (void **)&transform)))
4426 goto failed;
4428 check_interface(transform, &IID_IMFTransform, TRUE);
4429 check_interface(transform, &IID_IMediaObject, TRUE);
4430 check_interface(transform, &IID_IPropertyStore, TRUE);
4431 check_interface(transform, &IID_IPropertyBag, TRUE);
4432 /* check_interface(transform, &IID_IWMResamplerProps, TRUE); */
4434 check_mft_optional_methods(transform, 1);
4435 check_mft_get_attributes(transform, NULL, FALSE);
4436 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
4437 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
4439 i = -1;
4440 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
4442 winetest_push_context("out %lu", i);
4443 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
4444 check_media_type(media_type, expect_available_outputs[i], -1);
4445 ret = IMFMediaType_Release(media_type);
4446 ok(ret == 0, "Release returned %lu\n", ret);
4447 winetest_pop_context();
4449 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
4450 ok(i == 4, "%lu output media types\n", i);
4452 i = -1;
4453 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
4455 winetest_push_context("in %lu", i);
4456 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
4457 check_media_type(media_type, expect_available_inputs[i], -1);
4458 ret = IMFMediaType_Release(media_type);
4459 ok(ret == 0, "Release returned %lu\n", ret);
4460 winetest_pop_context();
4462 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
4463 ok(i == 2, "%lu input media types\n", i);
4465 /* setting output media type first doesn't work */
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_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
4474 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
4476 /* check new output media types */
4478 i = -1;
4479 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
4481 winetest_push_context("out %lu", i);
4482 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
4483 check_media_type(media_type, expect_available_outputs[i], -1);
4484 ret = IMFMediaType_Release(media_type);
4485 ok(ret == 0, "Release returned %lu\n", ret);
4486 winetest_pop_context();
4488 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
4489 ok(i == 4, "%lu output media types\n", i);
4491 check_mft_set_output_type_required(transform, output_type_desc);
4492 check_mft_set_output_type(transform, output_type_desc, S_OK);
4493 check_mft_get_output_current_type_(transform, expect_output_type_desc, FALSE, TRUE);
4495 check_mft_get_input_stream_info(transform, S_OK, &input_info);
4496 check_mft_get_output_stream_info(transform, S_OK, &output_info);
4498 load_resource(L"audiodata.bin", &audio_data, &audio_data_len);
4499 ok(audio_data_len == 179928, "got length %lu\n", audio_data_len);
4501 input_sample = create_sample(audio_data, audio_data_len);
4502 hr = IMFSample_SetSampleTime(input_sample, 0);
4503 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
4504 hr = IMFSample_SetSampleDuration(input_sample, 10000000);
4505 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
4506 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
4507 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
4508 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
4509 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
4510 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
4511 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
4512 ret = IMFSample_Release(input_sample);
4513 ok(ret <= 1, "Release returned %ld\n", ret);
4515 hr = MFCreateCollection(&output_samples);
4516 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
4518 output_sample = create_sample(NULL, audioconv_block_size);
4519 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
4521 winetest_push_context("%lu", i);
4522 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
4523 ok(!(output_status & ~MFT_OUTPUT_DATA_BUFFER_INCOMPLETE), "got output[0].dwStatus %#lx\n", output_status);
4524 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
4525 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
4526 ref = IMFSample_Release(output_sample);
4527 ok(ref == 1, "Release returned %ld\n", ref);
4528 output_sample = create_sample(NULL, audioconv_block_size);
4529 winetest_pop_context();
4531 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
4532 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
4533 ret = IMFSample_Release(output_sample);
4534 ok(ret == 0, "Release returned %lu\n", ret);
4535 todo_wine
4536 ok(i == 12 || broken(i == 11) /* Win7 */, "got %lu output samples\n", i);
4538 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"audioconvdata.bin");
4539 ok(ret == 0, "got %lu%% diff\n", ret);
4540 IMFCollection_Release(output_samples);
4542 output_sample = create_sample(NULL, audioconv_block_size);
4543 hr = check_mft_process_output(transform, output_sample, &output_status);
4544 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
4545 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
4546 hr = IMFSample_GetTotalLength(output_sample, &length);
4547 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
4548 ok(length == 0, "got length %lu\n", length);
4549 ret = IMFSample_Release(output_sample);
4550 ok(ret == 0, "Release returned %lu\n", ret);
4552 ret = IMFTransform_Release(transform);
4553 ok(ret == 0, "Release returned %lu\n", ret);
4555 failed:
4556 winetest_pop_context();
4557 CoUninitialize();
4560 static void test_wmv_encoder(void)
4562 const GUID *const class_id = &CLSID_CWMVXEncMediaObject;
4563 const struct transform_info expect_mft_info =
4565 .name = L"WMVideo8 Encoder MFT",
4566 .major_type = &MFMediaType_Video,
4567 .inputs =
4569 {.subtype = &MFVideoFormat_IYUV},
4570 {.subtype = &MFVideoFormat_I420},
4571 {.subtype = &MFVideoFormat_YV12},
4572 {.subtype = &MFVideoFormat_NV11},
4573 {.subtype = &MFVideoFormat_NV12},
4574 {.subtype = &MFVideoFormat_YUY2},
4575 {.subtype = &MFVideoFormat_UYVY},
4576 {.subtype = &MFVideoFormat_YVYU},
4577 {.subtype = &MFVideoFormat_YVU9},
4578 {.subtype = &DMOVideoFormat_RGB32},
4579 {.subtype = &DMOVideoFormat_RGB24},
4580 {.subtype = &DMOVideoFormat_RGB565},
4581 {.subtype = &DMOVideoFormat_RGB555},
4582 {.subtype = &DMOVideoFormat_RGB8},
4584 .outputs =
4586 {.subtype = &MFVideoFormat_WMV1},
4587 {.subtype = &MFVideoFormat_WMV2},
4590 const struct transform_info expect_dmo_info =
4592 .name = L"WMVideo8 Encoder DMO",
4593 .major_type = &MEDIATYPE_Video,
4594 .inputs =
4596 {.subtype = &MEDIASUBTYPE_IYUV},
4597 {.subtype = &MEDIASUBTYPE_I420},
4598 {.subtype = &MEDIASUBTYPE_YV12},
4599 {.subtype = &MEDIASUBTYPE_NV11},
4600 {.subtype = &MEDIASUBTYPE_NV12},
4601 {.subtype = &MEDIASUBTYPE_YUY2},
4602 {.subtype = &MEDIASUBTYPE_UYVY},
4603 {.subtype = &MEDIASUBTYPE_YVYU},
4604 {.subtype = &MEDIASUBTYPE_YVU9},
4605 {.subtype = &MEDIASUBTYPE_RGB32},
4606 {.subtype = &MEDIASUBTYPE_RGB24},
4607 {.subtype = &MEDIASUBTYPE_RGB565},
4608 {.subtype = &MEDIASUBTYPE_RGB555},
4609 {.subtype = &MEDIASUBTYPE_RGB8},
4611 .outputs =
4613 {.subtype = &MEDIASUBTYPE_WMV1},
4614 {.subtype = &MEDIASUBTYPE_WMV2},
4618 static const media_type_desc expect_available_inputs[] =
4621 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4622 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
4623 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4624 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4625 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4626 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4627 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4628 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4631 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4632 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
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_TRANSFER_FUNCTION, 0),
4637 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4638 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4641 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4642 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
4643 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4644 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4645 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4646 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4647 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4648 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4651 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4652 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11),
4653 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4654 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4655 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4656 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4657 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4658 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4661 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4662 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
4663 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4664 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4665 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4666 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4667 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4668 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4671 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4672 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
4673 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4674 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4675 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4676 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4677 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4678 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4681 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4682 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY),
4683 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4684 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4685 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4686 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4687 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4688 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4691 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4692 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU),
4693 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4694 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4695 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4696 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4697 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4698 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4701 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4702 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
4703 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4704 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4705 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4706 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4707 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4708 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4711 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4712 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24),
4713 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4714 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4715 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4716 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4717 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4718 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4721 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4722 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565),
4723 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4724 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4725 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4726 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4727 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4728 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4731 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4732 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555),
4733 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4734 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4735 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4736 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4737 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4738 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4741 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4742 ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_RGB8),
4743 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4744 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4745 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4746 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4747 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4748 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4751 static const media_type_desc expect_available_outputs[] =
4754 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4755 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1),
4756 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4757 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4758 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4759 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4762 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4763 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV2),
4764 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4765 ATTR_UINT32(MF_MT_TRANSFER_FUNCTION, 0),
4766 ATTR_UINT32(MF_MT_VIDEO_PRIMARIES, 0),
4767 ATTR_UINT32(MF_MT_YUV_MATRIX, 0),
4771 static const DWORD actual_width = 96, actual_height = 96;
4772 const struct attribute_desc input_type_desc[] =
4774 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
4775 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE),
4776 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001, .required = TRUE),
4777 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height), /* required for SetOutputType */
4778 {0},
4780 const struct attribute_desc output_type_desc[] =
4782 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
4783 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1, .required = TRUE),
4784 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
4785 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001, .required = TRUE),
4786 ATTR_UINT32(MF_MT_AVG_BITRATE, 193540, .required = TRUE),
4787 {0},
4790 const struct attribute_desc expect_input_type_desc[] =
4792 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4793 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
4794 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
4795 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4796 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
4797 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
4798 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
4799 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4800 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
4801 {0},
4803 const struct attribute_desc expect_output_type_desc[] =
4805 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
4806 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1),
4807 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
4808 ATTR_RATIO(MF_MT_FRAME_RATE, 30000, 1001),
4809 ATTR_UINT32(MF_MT_AVG_BITRATE, 193540),
4810 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
4811 {0},
4813 static const MFT_OUTPUT_STREAM_INFO empty_output_info =
4815 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER,
4817 static const MFT_INPUT_STREAM_INFO empty_input_info =
4819 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER,
4821 static const MFT_OUTPUT_STREAM_INFO expect_output_info =
4823 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER,
4824 .cbSize = 0x8000,
4825 .cbAlignment = 1,
4827 static const MFT_INPUT_STREAM_INFO expect_input_info =
4829 .dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER,
4830 .cbSize = 0x3600,
4831 .cbAlignment = 1,
4834 const struct buffer_desc output_buffer_desc[] =
4836 {.length = -1 /* variable */},
4838 const struct attribute_desc output_sample_attributes_key[] =
4840 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
4841 {0},
4843 const struct attribute_desc output_sample_attributes[] =
4845 ATTR_UINT32(MFSampleExtension_CleanPoint, 0),
4846 {0},
4848 const struct sample_desc output_sample_desc[] =
4851 .attributes = output_sample_attributes_key,
4852 .sample_time = 0, .sample_duration = 333333,
4853 .buffer_count = 1, .buffers = output_buffer_desc,
4856 .attributes = output_sample_attributes,
4857 .sample_time = 333333, .sample_duration = 333333,
4858 .buffer_count = 1, .buffers = output_buffer_desc, .repeat_count = 4
4862 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_WMV1};
4863 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_NV12};
4864 IMFSample *input_sample, *output_sample;
4865 DWORD status, length, output_status;
4866 MFT_OUTPUT_DATA_BUFFER output;
4867 IMFCollection *output_samples;
4868 const BYTE *nv12frame_data;
4869 IMFMediaType *media_type;
4870 ULONG nv12frame_data_len;
4871 IMFTransform *transform;
4872 ULONG i, ret;
4873 HRESULT hr;
4874 LONG ref;
4876 hr = CoInitialize(NULL);
4877 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
4879 winetest_push_context("wmvenc");
4881 if (!check_mft_enum(MFT_CATEGORY_VIDEO_ENCODER, &input_type, &output_type, class_id))
4882 goto failed;
4883 check_mft_get_info(class_id, &expect_mft_info);
4884 check_dmo_get_info(class_id, &expect_dmo_info);
4886 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
4887 &IID_IMFTransform, (void **)&transform)))
4888 goto failed;
4890 check_interface(transform, &IID_IMFTransform, TRUE);
4891 check_interface(transform, &IID_IMediaObject, TRUE);
4892 check_interface(transform, &IID_IPropertyStore, TRUE);
4893 check_interface(transform, &IID_IPropertyBag, TRUE);
4895 check_mft_optional_methods(transform, 2);
4896 check_mft_get_attributes(transform, NULL, FALSE);
4897 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, &empty_input_info);
4898 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, &empty_output_info);
4900 i = -1;
4901 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
4903 winetest_push_context("in 0 %lu", i);
4904 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
4905 ret = IMFMediaType_Release(media_type);
4906 ok(ret <= 1, "Release returned %lu\n", ret);
4907 winetest_pop_context();
4909 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
4910 ok(i == ARRAY_SIZE(expect_available_inputs), "%lu input media types\n", i);
4912 i = -1;
4913 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
4915 winetest_push_context("out %lu", i);
4916 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
4917 ret = IMFMediaType_Release(media_type);
4918 ok(ret <= 1, "Release returned %lu\n", ret);
4919 winetest_pop_context();
4921 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
4922 ok(i == ARRAY_SIZE(expect_available_outputs), "%lu output media types\n", i);
4924 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
4925 check_mft_get_output_current_type(transform, NULL);
4927 check_mft_set_input_type_required(transform, input_type_desc);
4928 check_mft_set_input_type(transform, input_type_desc);
4929 check_mft_get_input_current_type_(transform, expect_input_type_desc, FALSE, TRUE);
4931 check_mft_set_output_type_required(transform, output_type_desc);
4932 check_mft_set_output_type(transform, output_type_desc, S_OK);
4933 check_mft_get_output_current_type_(transform, expect_output_type_desc, FALSE, TRUE);
4935 check_mft_get_input_stream_info(transform, S_OK, &expect_input_info);
4936 check_mft_get_output_stream_info(transform, S_OK, &expect_output_info);
4938 if (!has_video_processor)
4940 win_skip("Skipping WMV encoder tests on Win7\n");
4941 goto done;
4944 load_resource(L"nv12frame.bmp", &nv12frame_data, &nv12frame_data_len);
4945 /* skip BMP header and RGB data from the dump */
4946 length = *(DWORD *)(nv12frame_data + 2);
4947 nv12frame_data_len = nv12frame_data_len - length;
4948 nv12frame_data = nv12frame_data + length;
4949 ok(nv12frame_data_len == 13824, "got length %lu\n", nv12frame_data_len);
4951 hr = MFCreateCollection(&output_samples);
4952 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
4954 for (i = 0; i < 5; i++)
4956 input_sample = create_sample(nv12frame_data, nv12frame_data_len);
4957 hr = IMFSample_SetSampleTime(input_sample, i * 333333);
4958 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
4959 hr = IMFSample_SetSampleDuration(input_sample, 333333);
4960 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
4961 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
4962 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
4963 ref = IMFSample_Release(input_sample);
4964 ok(ref <= 1, "Release returned %ld\n", ref);
4966 output_sample = create_sample(NULL, expect_output_info.cbSize);
4967 hr = check_mft_process_output(transform, output_sample, &output_status);
4968 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
4969 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
4970 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
4971 ref = IMFSample_Release(output_sample);
4972 ok(ref == 1, "Release returned %ld\n", ref);
4975 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"wmvencdata.bin");
4976 ok(ret == 0, "got %lu%% diff\n", ret);
4977 IMFCollection_Release(output_samples);
4979 output_sample = create_sample(NULL, expect_output_info.cbSize);
4980 status = 0xdeadbeef;
4981 memset(&output, 0, sizeof(output));
4982 output.pSample = output_sample;
4983 hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
4984 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
4985 ok(output.pSample == output_sample, "got pSample %p\n", output.pSample);
4986 ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
4987 ok(status == 0, "got status %#lx\n", status);
4988 hr = IMFSample_GetTotalLength(output.pSample, &length);
4989 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
4990 ok(length == 0, "got length %lu\n", length);
4991 ret = IMFSample_Release(output_sample);
4992 ok(ret == 0, "Release returned %lu\n", ret);
4994 done:
4995 ret = IMFTransform_Release(transform);
4996 ok(ret == 0, "Release returned %lu\n", ret);
4998 failed:
4999 winetest_pop_context();
5000 CoUninitialize();
5003 static void test_wmv_decoder(void)
5005 const GUID *const class_id = &CLSID_CWMVDecMediaObject;
5006 const struct transform_info expect_mft_info =
5008 .name = L"WMVideo Decoder MFT",
5009 .major_type = &MFMediaType_Video,
5010 .inputs =
5012 {.subtype = &MFVideoFormat_WMV1},
5013 {.subtype = &MFVideoFormat_WMV2},
5014 {.subtype = &MFVideoFormat_WMV3},
5015 {.subtype = &MEDIASUBTYPE_WMVP},
5016 {.subtype = &MEDIASUBTYPE_WVP2},
5017 {.subtype = &MEDIASUBTYPE_WMVR},
5018 {.subtype = &MEDIASUBTYPE_WMVA},
5019 {.subtype = &MFVideoFormat_WVC1},
5020 {.subtype = &MFVideoFormat_VC1S},
5022 .outputs =
5024 {.subtype = &MFVideoFormat_YV12},
5025 {.subtype = &MFVideoFormat_YUY2},
5026 {.subtype = &MFVideoFormat_UYVY},
5027 {.subtype = &MFVideoFormat_YVYU},
5028 {.subtype = &MFVideoFormat_NV11},
5029 {.subtype = &MFVideoFormat_NV12},
5030 {.subtype = &DMOVideoFormat_RGB32},
5031 {.subtype = &DMOVideoFormat_RGB24},
5032 {.subtype = &DMOVideoFormat_RGB565},
5033 {.subtype = &DMOVideoFormat_RGB555},
5034 {.subtype = &DMOVideoFormat_RGB8},
5037 const struct transform_info expect_dmo_info =
5039 .name = L"WMVideo Decoder DMO",
5040 .major_type = &MEDIATYPE_Video,
5041 .inputs =
5043 {.subtype = &MEDIASUBTYPE_WMV1},
5044 {.subtype = &MEDIASUBTYPE_WMV2},
5045 {.subtype = &MEDIASUBTYPE_WMV3},
5046 {.subtype = &MEDIASUBTYPE_WMVA},
5047 {.subtype = &MEDIASUBTYPE_WVC1},
5048 {.subtype = &MEDIASUBTYPE_WMVP},
5049 {.subtype = &MEDIASUBTYPE_WVP2},
5050 {.subtype = &MFVideoFormat_VC1S},
5052 .outputs =
5054 {.subtype = &MEDIASUBTYPE_YV12},
5055 {.subtype = &MEDIASUBTYPE_YUY2},
5056 {.subtype = &MEDIASUBTYPE_UYVY},
5057 {.subtype = &MEDIASUBTYPE_YVYU},
5058 {.subtype = &MEDIASUBTYPE_NV11},
5059 {.subtype = &MEDIASUBTYPE_NV12},
5060 {.subtype = &MEDIASUBTYPE_RGB32},
5061 {.subtype = &MEDIASUBTYPE_RGB24},
5062 {.subtype = &MEDIASUBTYPE_RGB565},
5063 {.subtype = &MEDIASUBTYPE_RGB555},
5064 {.subtype = &MEDIASUBTYPE_RGB8},
5068 static const struct attribute_desc expect_common_attributes[] =
5070 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5071 {0},
5073 static const media_type_desc expect_available_inputs[] =
5075 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1)},
5076 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV2)},
5077 {ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_WMVA)},
5078 {ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_WMVP)},
5079 {ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_WVP2)},
5080 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV_Unknown)},
5081 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WVC1)},
5082 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV3)},
5083 {ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_VC1S)},
5085 static const MFVideoArea actual_aperture = {.Area={96,96}};
5086 static const DWORD actual_width = 96, actual_height = 96;
5087 const struct attribute_desc expect_output_attributes[] =
5089 ATTR_BLOB(MF_MT_GEOMETRIC_APERTURE, &actual_aperture, sizeof(actual_aperture)),
5090 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, sizeof(actual_aperture)),
5091 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
5092 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
5093 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
5094 ATTR_UINT32(MF_MT_INTERLACE_MODE, 2),
5095 {0},
5097 const media_type_desc expect_available_outputs[] =
5100 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5101 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
5102 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
5103 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
5104 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
5107 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5108 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12),
5109 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
5110 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
5111 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
5114 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5115 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV),
5116 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
5117 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
5118 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
5121 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5122 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420),
5123 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
5124 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
5125 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
5128 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5129 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2),
5130 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
5131 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
5132 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
5135 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5136 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY),
5137 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
5138 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
5139 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
5142 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5143 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU),
5144 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
5145 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
5146 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
5149 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5150 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11),
5151 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
5152 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
5153 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
5156 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5157 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
5158 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
5159 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 4),
5160 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 4),
5163 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5164 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24),
5165 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
5166 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 3),
5167 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3),
5170 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5171 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565),
5172 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
5173 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
5174 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
5175 /* ATTR_BLOB(MF_MT_PALETTE, ... with 12 elements), */
5178 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5179 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555),
5180 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
5181 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
5182 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 2),
5185 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5186 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB8),
5187 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
5188 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
5189 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height),
5190 /* ATTR_BLOB(MF_MT_PALETTE, ... with 904 elements), */
5193 const struct attribute_desc expect_attributes[] =
5195 ATTR_UINT32(MF_LOW_LATENCY, 0),
5196 ATTR_UINT32(MF_SA_D3D11_AWARE, 1),
5197 ATTR_UINT32(MF_SA_D3D_AWARE, 1),
5198 ATTR_UINT32(MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER, 0),
5199 /* more attributes from CODECAPI */
5200 {0},
5202 const struct attribute_desc input_type_desc[] =
5204 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
5205 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1, .required = TRUE),
5206 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
5207 {0},
5209 const struct attribute_desc output_type_desc[] =
5211 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
5212 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE),
5213 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
5214 {0},
5216 const struct attribute_desc output_type_desc_negative_stride[] =
5218 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
5219 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE),
5220 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
5221 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, -actual_width),
5222 {0},
5224 const struct attribute_desc output_type_desc_rgb[] =
5226 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
5227 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32, .required = TRUE),
5228 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
5229 {0},
5231 const struct attribute_desc output_type_desc_rgb_negative_stride[] =
5233 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
5234 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32, .required = TRUE),
5235 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
5236 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, -actual_width * 4),
5237 {0},
5239 const struct attribute_desc output_type_desc_rgb_positive_stride[] =
5241 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
5242 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32, .required = TRUE),
5243 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
5244 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 4),
5245 {0},
5247 const struct attribute_desc expect_input_type_desc[] =
5249 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5250 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1),
5251 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
5252 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
5253 {0},
5255 const struct attribute_desc expect_output_type_desc[] =
5257 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5258 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
5259 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
5260 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
5261 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
5262 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
5263 ATTR_UINT32(MF_MT_VIDEO_NOMINAL_RANGE, 2),
5264 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
5265 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
5266 {0},
5268 const struct attribute_desc expect_output_type_desc_rgb[] =
5270 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5271 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
5272 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
5273 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 4),
5274 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 4),
5275 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
5276 ATTR_UINT32(MF_MT_VIDEO_NOMINAL_RANGE, 2),
5277 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
5278 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
5279 {0},
5281 const struct attribute_desc expect_output_type_desc_rgb_negative_stride[] =
5283 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
5284 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
5285 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
5286 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, -actual_width * 4),
5287 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 4),
5288 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
5289 ATTR_UINT32(MF_MT_VIDEO_NOMINAL_RANGE, 2),
5290 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
5291 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
5292 {0},
5294 const MFT_OUTPUT_STREAM_INFO expect_output_info =
5296 .dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_DISCARDABLE,
5297 .cbSize = 0x3600,
5298 .cbAlignment = 1,
5300 const MFT_OUTPUT_STREAM_INFO expect_output_info_rgb =
5302 .dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_DISCARDABLE,
5303 .cbSize = 0x9000,
5304 .cbAlignment = 1,
5306 const MFT_OUTPUT_STREAM_INFO empty_output_info =
5308 .dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_OUTPUT_STREAM_DISCARDABLE,
5310 const MFT_INPUT_STREAM_INFO expect_input_info =
5312 .cbSize = 0x3600,
5313 .cbAlignment = 1,
5315 const MFT_INPUT_STREAM_INFO expect_input_info_rgb =
5317 .cbSize = 0x9000,
5318 .cbAlignment = 1,
5321 const struct attribute_desc output_sample_attributes[] =
5323 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
5324 {0},
5326 const struct buffer_desc output_buffer_desc_nv12 =
5328 .length = actual_width * actual_height * 3 / 2,
5329 .compare = compare_nv12, .dump = dump_nv12, .rect = {.right = 82, .bottom = 84},
5331 const struct buffer_desc output_buffer_desc_rgb =
5333 .length = actual_width * actual_height * 4,
5334 .compare = compare_rgb32, .dump = dump_rgb32, .rect = {.right = 82, .bottom = 84},
5336 const struct sample_desc output_sample_desc_nv12 =
5338 .attributes = output_sample_attributes,
5339 .sample_time = 0, .sample_duration = 333333,
5340 .buffer_count = 1, .buffers = &output_buffer_desc_nv12,
5342 const struct sample_desc output_sample_desc_rgb =
5344 .attributes = output_sample_attributes,
5345 .sample_time = 0, .sample_duration = 333333,
5346 .buffer_count = 1, .buffers = &output_buffer_desc_rgb,
5349 const struct transform_desc
5351 const struct attribute_desc *output_type_desc;
5352 const struct attribute_desc *expect_output_type_desc;
5353 const MFT_INPUT_STREAM_INFO *expect_input_info;
5354 const MFT_OUTPUT_STREAM_INFO *expect_output_info;
5355 const struct sample_desc *output_sample_desc;
5356 const WCHAR *result_bitmap;
5357 ULONG delta;
5359 transform_tests[] =
5362 /* WMV1 -> YUV */
5363 .output_type_desc = output_type_desc,
5364 .expect_output_type_desc = expect_output_type_desc,
5365 .expect_input_info = &expect_input_info,
5366 .expect_output_info = &expect_output_info,
5367 .output_sample_desc = &output_sample_desc_nv12,
5368 .result_bitmap = L"nv12frame.bmp",
5369 .delta = 0,
5373 /* WMV1 -> YUV (negative stride) */
5374 .output_type_desc = output_type_desc_negative_stride,
5375 .expect_output_type_desc = expect_output_type_desc,
5376 .expect_input_info = &expect_input_info,
5377 .expect_output_info = &expect_output_info,
5378 .output_sample_desc = &output_sample_desc_nv12,
5379 .result_bitmap = L"nv12frame.bmp",
5380 .delta = 0,
5384 /* WMV1 -> RGB */
5385 .output_type_desc = output_type_desc_rgb,
5386 .expect_output_type_desc = expect_output_type_desc_rgb,
5387 .expect_input_info = &expect_input_info_rgb,
5388 .expect_output_info = &expect_output_info_rgb,
5389 .output_sample_desc = &output_sample_desc_rgb,
5390 .result_bitmap = L"rgb32frame-flip.bmp",
5391 .delta = 5,
5395 /* WMV1 -> RGB (negative stride) */
5396 .output_type_desc = output_type_desc_rgb_negative_stride,
5397 .expect_output_type_desc = expect_output_type_desc_rgb_negative_stride,
5398 .expect_input_info = &expect_input_info_rgb,
5399 .expect_output_info = &expect_output_info_rgb,
5400 .output_sample_desc = &output_sample_desc_rgb,
5401 .result_bitmap = L"rgb32frame-flip.bmp",
5402 .delta = 5,
5406 /* WMV1 -> RGB (positive stride */
5407 .output_type_desc = output_type_desc_rgb_positive_stride,
5408 .expect_output_type_desc = expect_output_type_desc_rgb,
5409 .expect_input_info = &expect_input_info_rgb,
5410 .expect_output_info = &expect_output_info_rgb,
5411 .output_sample_desc = &output_sample_desc_rgb,
5412 .result_bitmap = L"rgb32frame-flip.bmp",
5413 .delta = 5,
5418 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
5419 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_WMV1};
5420 IMFSample *input_sample, *output_sample;
5421 IMFCollection *output_samples;
5422 IMFMediaType *media_type;
5423 IMFTransform *transform;
5424 const BYTE *wmvenc_data;
5425 ULONG wmvenc_data_len;
5426 DWORD output_status;
5427 ULONG i, j, ret, ref;
5428 HRESULT hr;
5430 hr = CoInitialize(NULL);
5431 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
5433 winetest_push_context("wmvdec");
5435 if (!has_video_processor)
5437 win_skip("Skipping inconsistent WMV decoder tests on Win7\n");
5438 goto failed;
5441 if (!check_mft_enum(MFT_CATEGORY_VIDEO_DECODER, &input_type, &output_type, class_id))
5442 goto failed;
5443 check_mft_get_info(class_id, &expect_mft_info);
5444 check_dmo_get_info(class_id, &expect_dmo_info);
5446 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
5447 &IID_IMFTransform, (void **)&transform)))
5448 goto failed;
5450 check_interface(transform, &IID_IMFTransform, TRUE);
5451 check_interface(transform, &IID_IMediaObject, TRUE);
5452 check_interface(transform, &IID_IPropertyStore, TRUE);
5453 check_interface(transform, &IID_IPropertyBag, TRUE);
5455 check_mft_optional_methods(transform, 1);
5456 check_mft_get_attributes(transform, expect_attributes, TRUE);
5457 todo_wine
5458 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
5459 todo_wine
5460 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, &empty_output_info);
5462 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
5463 todo_wine
5464 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
5466 i = -1;
5467 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
5469 winetest_push_context("in %lu", i);
5470 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
5471 check_media_type(media_type, expect_common_attributes, -1);
5472 check_media_type(media_type, expect_available_inputs[i], -1);
5473 ret = IMFMediaType_Release(media_type);
5474 ok(!ret, "Release returned %lu\n", ret);
5475 winetest_pop_context();
5477 todo_wine
5478 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
5479 todo_wine
5480 ok(i == ARRAY_SIZE(expect_available_inputs), "%lu input media types\n", i);
5482 if (hr == E_NOTIMPL)
5483 goto skip_tests;
5485 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
5486 check_mft_get_output_current_type(transform, NULL);
5488 check_mft_set_input_type_required(transform, input_type_desc);
5489 check_mft_set_input_type(transform, input_type_desc);
5490 check_mft_get_input_current_type_(transform, expect_input_type_desc, FALSE, TRUE);
5492 i = -1;
5493 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
5495 winetest_push_context("out %lu", i);
5496 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
5497 check_media_type(media_type, expect_common_attributes, -1);
5498 check_media_type(media_type, expect_output_attributes, -1);
5499 check_media_type(media_type, expect_available_outputs[i], -1);
5500 ret = IMFMediaType_Release(media_type);
5501 ok(!ret, "Release returned %lu\n", ret);
5502 winetest_pop_context();
5504 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
5505 ok(i == ARRAY_SIZE(expect_available_outputs), "%lu input media types\n", i);
5507 for (j = 0; j < ARRAY_SIZE(transform_tests); j++)
5509 winetest_push_context("transform #%lu", j);
5511 check_mft_set_output_type_required(transform, transform_tests[j].output_type_desc);
5512 check_mft_set_output_type(transform, transform_tests[j].output_type_desc, S_OK);
5513 check_mft_get_output_current_type_(transform, transform_tests[j].expect_output_type_desc, FALSE, TRUE);
5515 check_mft_get_input_stream_info(transform, S_OK, transform_tests[j].expect_input_info);
5516 check_mft_get_output_stream_info(transform, S_OK, transform_tests[j].expect_output_info);
5518 load_resource(L"wmvencdata.bin", &wmvenc_data, &wmvenc_data_len);
5520 input_sample = create_sample(wmvenc_data + sizeof(DWORD), *(DWORD *)wmvenc_data);
5521 wmvenc_data_len -= *(DWORD *)wmvenc_data + sizeof(DWORD);
5522 wmvenc_data += *(DWORD *)wmvenc_data + sizeof(DWORD);
5523 hr = IMFSample_SetSampleTime(input_sample, 0);
5524 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
5525 hr = IMFSample_SetSampleDuration(input_sample, 333333);
5526 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
5527 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
5528 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
5529 ret = IMFSample_Release(input_sample);
5530 ok(ret <= 1, "Release returned %ld\n", ret);
5532 hr = MFCreateCollection(&output_samples);
5533 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
5535 output_sample = create_sample(NULL, transform_tests[j].expect_output_info->cbSize);
5536 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
5538 winetest_push_context("%lu", i);
5539 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
5540 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
5541 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
5542 ref = IMFSample_Release(output_sample);
5543 ok(ref == 1, "Release returned %ld\n", ref);
5544 output_sample = create_sample(NULL, transform_tests[j].expect_output_info->cbSize);
5545 winetest_pop_context();
5547 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
5548 ret = IMFSample_Release(output_sample);
5549 ok(ret == 0, "Release returned %lu\n", ret);
5550 ok(i == 1, "got %lu output samples\n", i);
5552 ret = check_mf_sample_collection(output_samples, transform_tests[j].output_sample_desc,
5553 transform_tests[j].result_bitmap);
5554 ok(ret <= transform_tests[j].delta, "got %lu%% diff\n", ret);
5555 IMFCollection_Release(output_samples);
5556 winetest_pop_context();
5559 skip_tests:
5560 ret = IMFTransform_Release(transform);
5561 ok(ret == 0, "Release returned %lu\n", ret);
5563 failed:
5564 winetest_pop_context();
5565 CoUninitialize();
5568 static void test_wmv_decoder_media_object(void)
5570 const GUID *const class_id = &CLSID_CWMVDecMediaObject;
5571 const DMO_MEDIA_TYPE expected_input_types[] =
5573 {MFMediaType_Video, MEDIASUBTYPE_WMV1, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
5574 {MFMediaType_Video, MEDIASUBTYPE_WMV2, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
5575 {MFMediaType_Video, MEDIASUBTYPE_WMVA, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
5576 {MFMediaType_Video, MEDIASUBTYPE_WMVP, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
5577 {MFMediaType_Video, MEDIASUBTYPE_WVP2, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
5578 {MFMediaType_Video, MFVideoFormat_WMV_Unknown, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
5579 {MFMediaType_Video, MEDIASUBTYPE_WVC1, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
5580 {MFMediaType_Video, MEDIASUBTYPE_WMV3, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
5581 {MFMediaType_Video, MFVideoFormat_VC1S, FALSE, TRUE, 0, GUID_NULL, NULL, 0},
5583 const VIDEOINFOHEADER expected_output_info[] =
5585 {{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}},
5586 {{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}},
5587 {{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}},
5588 {{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}},
5589 {{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}},
5590 {{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}},
5591 {{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}},
5592 {{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}},
5593 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 32, BI_RGB, 1024, 0, 0, 0, 0}},
5594 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 24, BI_RGB, 768, 0, 0, 0, 0}},
5595 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 16, BI_BITFIELDS, 512, 0, 0, 0, 0}},
5596 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 16, BI_RGB, 512, 0, 0, 0, 0}},
5597 {{0, 0, 16, 16}, {0, 0, 16, 16}, 0, 0, 0, {40, 16, 16, 1, 8, BI_RGB, 256, 0, 0, 226, 226}},
5599 const DMO_MEDIA_TYPE expected_output_types[] =
5601 {MFMediaType_Video, MEDIASUBTYPE_NV12, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[0]},
5602 {MFMediaType_Video, MEDIASUBTYPE_YV12, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[1]},
5603 {MFMediaType_Video, MEDIASUBTYPE_IYUV, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[2]},
5604 {MFMediaType_Video, MEDIASUBTYPE_I420, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[3]},
5605 {MFMediaType_Video, MEDIASUBTYPE_YUY2, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[4]},
5606 {MFMediaType_Video, MEDIASUBTYPE_UYVY, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[5]},
5607 {MFMediaType_Video, MEDIASUBTYPE_YVYU, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[6]},
5608 {MFMediaType_Video, MEDIASUBTYPE_NV11, TRUE, FALSE, 384, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[7]},
5609 {MFMediaType_Video, MEDIASUBTYPE_RGB32, TRUE, FALSE, 1024, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[8]},
5610 {MFMediaType_Video, MEDIASUBTYPE_RGB24, TRUE, FALSE, 768, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[9]},
5611 {MFMediaType_Video, MEDIASUBTYPE_RGB565, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 100, (BYTE *)&expected_output_info[10]},
5612 {MFMediaType_Video, MEDIASUBTYPE_RGB555, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[11]},
5613 {MFMediaType_Video, MEDIASUBTYPE_RGB8, TRUE, FALSE, 256, FORMAT_VideoInfo, NULL, 1112, (BYTE *)&expected_output_info[12]},
5615 const DWORD data_width = 96, data_height = 96;
5616 const POINT test_size[] = {{16, 16}, {96, 96}, {320, 240}};
5617 const struct buffer_desc output_buffer_desc_nv12 =
5619 .length = data_width * data_height * 3 / 2,
5620 .compare = compare_nv12, .dump = dump_nv12, .rect = {.right = 82, .bottom = 84},
5622 DWORD in_count, out_count, size, expected_size, alignment, wmv_data_length, status, expected_status, diff;
5623 struct media_buffer *input_media_buffer = NULL, *output_media_buffer = NULL;
5624 DMO_OUTPUT_DATA_BUFFER output_data_buffer;
5625 DMO_MEDIA_TYPE media_type, *type;
5626 IMediaObject *media_object;
5627 const BYTE *wmv_data;
5628 char buffer[1024];
5629 ULONG ret, i, j;
5630 HRESULT hr;
5632 winetest_push_context("wmvdec");
5634 if (!has_video_processor)
5636 win_skip("Skipping inconsistent WMV decoder media object tests on Win7.\n");
5637 winetest_pop_context();
5638 return;
5641 type = (DMO_MEDIA_TYPE *)buffer;
5643 hr = CoInitialize(NULL);
5644 ok(hr == S_OK, "CoInitialize failed, hr %#lx.\n", hr);
5646 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER, &IID_IMediaObject, (void **)&media_object)))
5648 CoUninitialize();
5649 winetest_pop_context();
5650 return;
5653 /* Test GetStreamCount. */
5654 in_count = out_count = 0xdeadbeef;
5655 hr = IMediaObject_GetStreamCount(media_object, &in_count, &out_count);
5656 ok(hr == S_OK, "GetStreamCount returned %#lx.\n", hr);
5657 ok(in_count == 1, "Got unexpected in_count %lu.\n", in_count);
5658 ok(out_count == 1, "Got unexpected in_count %lu.\n", out_count);
5660 /* Test GetStreamCount with invalid arguments. */
5661 in_count = out_count = 0xdeadbeef;
5662 hr = IMediaObject_GetStreamCount(media_object, NULL, &out_count);
5663 ok(hr == E_POINTER, "GetStreamCount returned %#lx.\n", hr);
5664 ok(out_count == 0xdeadbeef, "Got unexpected out_count %lu.\n", out_count);
5665 hr = IMediaObject_GetStreamCount(media_object, &in_count, NULL);
5666 ok(hr == E_POINTER, "GetStreamCount returned %#lx.\n", hr);
5667 ok(in_count == 0xdeadbeef, "Got unexpected in_count %lu.\n", in_count);
5669 /* Test GetInputType. */
5670 check_dmo_get_input_type(media_object, expected_input_types, ARRAY_SIZE(expected_input_types));
5672 /* Test SetInputType. */
5673 for (i = 0; i < ARRAY_SIZE(expected_input_types); ++i)
5675 const GUID *subtype = &expected_input_types[i].subtype;
5676 if (IsEqualGUID(subtype, &MEDIASUBTYPE_WMV2)
5677 || IsEqualGUID(subtype, &MEDIASUBTYPE_WMVA)
5678 || IsEqualGUID(subtype, &MEDIASUBTYPE_WVP2)
5679 || IsEqualGUID(subtype, &MEDIASUBTYPE_WVC1)
5680 || IsEqualGUID(subtype, &MFVideoFormat_VC1S))
5682 skip("Skipping SetInputType tests for video subtype %s.\n", debugstr_guid(subtype));
5683 continue;
5686 winetest_push_context("in %lu", i);
5687 check_dmo_set_input_type(media_object, subtype);
5688 winetest_pop_context();
5691 /* Test GetOutputType without setting input type. */
5692 hr = IMediaObject_SetInputType(media_object, 0, NULL, DMO_SET_TYPEF_CLEAR);
5693 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
5694 hr = IMediaObject_GetOutputType(media_object, 0, 0, &media_type);
5695 ok(hr == DMO_E_TYPE_NOT_SET, "GetOutputType returned %#lx.\n", hr);
5697 /* Test GetOutputType after setting input type. */
5698 init_dmo_media_type_video(type, &expected_input_types[0].subtype, 16, 16);
5699 hr = IMediaObject_SetInputType(media_object, 0, type, 0);
5700 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
5701 check_dmo_get_output_type(media_object, expected_output_types, ARRAY_SIZE(expected_output_types));
5703 /* Test SetOutputType without setting input type. */
5704 hr = IMediaObject_SetInputType(media_object, 0, NULL, DMO_SET_TYPEF_CLEAR);
5705 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
5706 hr = IMediaObject_SetOutputType(media_object, 0, &media_type, 0);
5707 ok(hr == DMO_E_TYPE_NOT_SET, "SetOutputType returned %#lx.\n", hr);
5709 /* Test SetOutputType after setting input type. */
5710 init_dmo_media_type_video(type, &expected_input_types[0].subtype, 16, 16);
5711 hr = IMediaObject_SetInputType(media_object, 0, type, 0);
5712 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
5713 check_dmo_set_output_type(media_object, &MEDIASUBTYPE_RGB24);
5715 /* Test GetOutputSizeInfo. */
5716 hr = IMediaObject_SetOutputType(media_object, 0, NULL, DMO_SET_TYPEF_CLEAR);
5717 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
5718 hr = IMediaObject_GetOutputSizeInfo(media_object, 0, &size, &alignment);
5719 ok(hr == DMO_E_TYPE_NOT_SET, "GetOutputSizeInfo returned %#lx.\n", hr);
5721 for (i = 0; i < ARRAY_SIZE(expected_output_types); ++i)
5723 const GUID *subtype = &expected_output_types[i].subtype;
5724 if (IsEqualGUID(subtype, &MEDIASUBTYPE_RGB565)
5725 || IsEqualGUID(subtype, &MEDIASUBTYPE_RGB8))
5727 skip("Skipping GetOutputSizeInfo tests for video subtype %s.\n", debugstr_guid(subtype));
5728 continue;
5731 winetest_push_context("out %lu", i);
5732 for (j = 0; j < ARRAY_SIZE(test_size); ++j)
5734 init_dmo_media_type_video(type, &expected_output_types[i].subtype, test_size[j].x, test_size[j].y);
5735 hr = IMediaObject_SetOutputType(media_object, 0, type, 0);
5736 todo_wine_if(IsEqualGUID(subtype, &MEDIASUBTYPE_NV11)
5737 || IsEqualGUID(subtype, &MEDIASUBTYPE_IYUV))
5738 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
5739 if (hr != S_OK)
5740 continue;
5742 size = 0xdeadbeef;
5743 alignment = 0xdeadbeef;
5744 hr = MFCalculateImageSize(subtype, test_size[j].x, test_size[j].y, (UINT32 *)&expected_size);
5745 ok(hr == S_OK, "MFCalculateImageSize returned %#lx.\n", hr);
5747 hr = IMediaObject_GetOutputSizeInfo(media_object, 0, &size, &alignment);
5748 ok(hr == S_OK, "GetOutputSizeInfo returned %#lx.\n", hr);
5749 ok(size == expected_size, "Got unexpected size %lu, expected %lu.\n", size, expected_size);
5750 ok(alignment == 1, "Got unexpected alignment %lu.\n", alignment);
5752 winetest_pop_context();
5755 /* Test ProcessInput. */
5756 load_resource(L"wmvencdata.bin", &wmv_data, &wmv_data_length);
5757 wmv_data_length = *((DWORD *)wmv_data);
5758 wmv_data += sizeof(DWORD);
5759 hr = media_buffer_create(wmv_data_length, &input_media_buffer);
5760 ok(hr == S_OK, "Failed to create input media buffer.\n");
5761 memcpy(input_media_buffer->data, wmv_data, wmv_data_length);
5762 input_media_buffer->length = wmv_data_length;
5764 init_dmo_media_type_video(type, &MEDIASUBTYPE_WMV1, data_width, data_height);
5765 hr = IMediaObject_SetInputType(media_object, 0, type, 0);
5766 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
5767 init_dmo_media_type_video(type, &MEDIASUBTYPE_NV12, data_width, data_height);
5768 hr = IMediaObject_SetOutputType(media_object, 0, type, 0);
5769 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
5771 hr = IMediaObject_ProcessInput(media_object, 0, &input_media_buffer->IMediaBuffer_iface, 0, 0, 0);
5772 ok(hr == S_OK, "ProcessInput returned %#lx.\n", hr);
5774 /* Test ProcessOutput. */
5775 hr = IMediaObject_GetOutputSizeInfo(media_object, 0, &size, &alignment);
5776 ok(hr == S_OK, "GetOutputSizeInfo returned %#lx.\n", hr);
5777 hr = media_buffer_create(size, &output_media_buffer);
5778 ok(hr == S_OK, "Failed to create output media buffer.\n");
5779 output_data_buffer.pBuffer = &output_media_buffer->IMediaBuffer_iface;
5780 output_data_buffer.dwStatus = 0xdeadbeef;
5781 output_data_buffer.rtTimestamp = 0xdeadbeef;
5782 output_data_buffer.rtTimelength = 0xdeadbeef;
5783 hr = IMediaObject_ProcessOutput(media_object, 0, 1, &output_data_buffer, &status);
5784 ok(hr == S_OK, "ProcessOutput returned %#lx.\n", hr);
5785 expected_status = DMO_OUTPUT_DATA_BUFFERF_SYNCPOINT | DMO_OUTPUT_DATA_BUFFERF_TIME | DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH;
5786 ok(output_data_buffer.dwStatus == expected_status, "Got unexpected dwStatus %#lx.\n", output_data_buffer.dwStatus);
5787 diff = check_dmo_output_data_buffer(&output_data_buffer, &output_buffer_desc_nv12, L"nv12frame.bmp", 0, 0);
5788 ok(diff == 0, "Got %lu%% diff.\n", diff);
5790 /* Test GetInputStatus. */
5791 hr = IMediaObject_GetInputStatus(media_object, 0xdeadbeef, NULL);
5792 ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetInputStatus returned %#lx.\n", hr);
5794 status = 0xdeadbeef;
5795 hr = IMediaObject_GetInputStatus(media_object, 0xdeadbeef, &status);
5796 ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetInputStatus returned %#lx.\n", hr);
5797 ok(status == 0xdeadbeef, "Unexpected status %#lx.\n", status);
5799 hr = IMediaObject_GetInputStatus(media_object, 0, NULL);
5800 ok(hr == E_POINTER, "GetInputStatus returned %#lx.\n", hr);
5802 hr = IMediaObject_GetInputStatus(media_object, 0, &status);
5803 ok(hr == S_OK, "GetInputStatus returned %#lx.\n", hr);
5804 ok(status == DMO_INPUT_STATUSF_ACCEPT_DATA, "Unexpected status %#lx.\n", status);
5806 /* Test Discontinuity. */
5807 hr = IMediaObject_Discontinuity(media_object, 0xdeadbeef);
5808 ok(hr == DMO_E_INVALIDSTREAMINDEX, "Discontinuity returned %#lx.\n", hr);
5809 hr = IMediaObject_Discontinuity(media_object, 0);
5810 ok(hr == S_OK, "Discontinuity returned %#lx.\n", hr);
5811 hr = IMediaObject_Discontinuity(media_object, 0);
5812 ok(hr == S_OK, "Discontinuity returned %#lx.\n", hr);
5813 hr = IMediaObject_GetInputStatus(media_object, 0, &status);
5814 ok(hr == S_OK, "GetInputStatus returned %#lx.\n", hr);
5815 ok(status == DMO_INPUT_STATUSF_ACCEPT_DATA, "Unexpected status %#lx.\n", status);
5817 /* Test Flush. */
5818 hr = IMediaObject_ProcessInput(media_object, 0, &input_media_buffer->IMediaBuffer_iface, 0, 0, 0);
5819 ok(hr == S_OK, "ProcessInput returned %#lx.\n", hr);
5820 hr = IMediaObject_Flush(media_object);
5821 todo_wine
5822 ok(hr == S_OK, "Flush returned %#lx.\n", hr);
5823 hr = IMediaObject_Flush(media_object);
5824 todo_wine
5825 ok(hr == S_OK, "Flush returned %#lx.\n", hr);
5826 output_media_buffer->length = 0;
5827 output_data_buffer.pBuffer = &output_media_buffer->IMediaBuffer_iface;
5828 output_data_buffer.dwStatus = 0xdeadbeef;
5829 output_data_buffer.rtTimestamp = 0xdeadbeef;
5830 output_data_buffer.rtTimelength = 0xdeadbeef;
5831 hr = IMediaObject_ProcessOutput(media_object, 0, 1, &output_data_buffer, &status);
5832 todo_wine
5833 ok(hr == S_FALSE, "ProcessOutput returned %#lx.\n", hr);
5834 todo_wine
5835 ok(output_media_buffer->length == 0, "Unexpected length %#lx.\n", output_media_buffer->length);
5837 /* Test ProcessOutput with setting framerate. */
5838 init_dmo_media_type_video(type, &MEDIASUBTYPE_WMV1, data_width, data_height);
5839 ((VIDEOINFOHEADER *)type->pbFormat)->AvgTimePerFrame = 100000;
5840 hr = IMediaObject_SetInputType(media_object, 0, type, 0);
5841 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
5842 init_dmo_media_type_video(type, &MEDIASUBTYPE_NV12, data_width, data_height);
5843 ((VIDEOINFOHEADER *)type->pbFormat)->AvgTimePerFrame = 200000;
5844 hr = IMediaObject_SetOutputType(media_object, 0, type, 0);
5845 ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
5847 hr = IMediaObject_ProcessInput(media_object, 0, &input_media_buffer->IMediaBuffer_iface, 0, 0, 300000);
5848 ok(hr == S_OK, "ProcessInput returned %#lx.\n", hr);
5850 output_media_buffer->length = 0;
5851 output_data_buffer.pBuffer = &output_media_buffer->IMediaBuffer_iface;
5852 output_data_buffer.dwStatus = 0xdeadbeef;
5853 output_data_buffer.rtTimestamp = 0xdeadbeef;
5854 output_data_buffer.rtTimelength = 0xdeadbeef;
5855 hr = IMediaObject_ProcessOutput(media_object, 0, 1, &output_data_buffer, &status);
5856 ok(hr == S_OK, "ProcessOutput returned %#lx.\n", hr);
5857 expected_status = DMO_OUTPUT_DATA_BUFFERF_SYNCPOINT | DMO_OUTPUT_DATA_BUFFERF_TIME | DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH;
5858 ok(output_data_buffer.dwStatus == expected_status, "Got unexpected dwStatus %#lx.\n", output_data_buffer.dwStatus);
5859 diff = check_dmo_output_data_buffer(&output_data_buffer, &output_buffer_desc_nv12, L"nv12frame.bmp", 0, 300000);
5860 ok(diff == 0, "Got %lu%% diff.\n", diff);
5862 ret = IMediaBuffer_Release(&output_media_buffer->IMediaBuffer_iface);
5863 ok(ret == 0, "Release returned %lu\n", ret);
5864 ret = IMediaBuffer_Release(&input_media_buffer->IMediaBuffer_iface);
5865 todo_wine
5866 ok(ret == 0, "Release returned %lu\n", ret);
5868 ret = IMediaObject_Release(media_object);
5869 ok(ret == 0, "Release returned %lu\n", ret);
5870 CoUninitialize();
5871 winetest_pop_context();
5874 static void test_color_convert(void)
5876 const GUID *const class_id = &CLSID_CColorConvertDMO;
5877 const struct transform_info expect_mft_info =
5879 .name = L"Color Converter MFT",
5880 .major_type = &MFMediaType_Video,
5881 .inputs =
5883 {.subtype = &MFVideoFormat_YV12},
5884 {.subtype = &MFVideoFormat_YUY2},
5885 {.subtype = &MFVideoFormat_UYVY},
5886 {.subtype = &MFVideoFormat_AYUV},
5887 {.subtype = &MFVideoFormat_NV12},
5888 {.subtype = &DMOVideoFormat_RGB32},
5889 {.subtype = &DMOVideoFormat_RGB565},
5890 {.subtype = &MFVideoFormat_I420},
5891 {.subtype = &MFVideoFormat_IYUV},
5892 {.subtype = &MFVideoFormat_YVYU},
5893 {.subtype = &DMOVideoFormat_RGB24},
5894 {.subtype = &DMOVideoFormat_RGB555},
5895 {.subtype = &DMOVideoFormat_RGB8},
5896 {.subtype = &MEDIASUBTYPE_V216},
5897 {.subtype = &MEDIASUBTYPE_V410},
5898 {.subtype = &MFVideoFormat_NV11},
5899 {.subtype = &MFVideoFormat_Y41P},
5900 {.subtype = &MFVideoFormat_Y41T},
5901 {.subtype = &MFVideoFormat_Y42T},
5902 {.subtype = &MFVideoFormat_YVU9},
5904 .outputs =
5906 {.subtype = &MFVideoFormat_YV12},
5907 {.subtype = &MFVideoFormat_YUY2},
5908 {.subtype = &MFVideoFormat_UYVY},
5909 {.subtype = &MFVideoFormat_AYUV},
5910 {.subtype = &MFVideoFormat_NV12},
5911 {.subtype = &DMOVideoFormat_RGB32},
5912 {.subtype = &DMOVideoFormat_RGB565},
5913 {.subtype = &MFVideoFormat_I420},
5914 {.subtype = &MFVideoFormat_IYUV},
5915 {.subtype = &MFVideoFormat_YVYU},
5916 {.subtype = &DMOVideoFormat_RGB24},
5917 {.subtype = &DMOVideoFormat_RGB555},
5918 {.subtype = &DMOVideoFormat_RGB8},
5919 {.subtype = &MEDIASUBTYPE_V216},
5920 {.subtype = &MEDIASUBTYPE_V410},
5921 {.subtype = &MFVideoFormat_NV11},
5924 const struct transform_info expect_dmo_info =
5926 .name = L"Color Converter DMO",
5927 .major_type = &MEDIATYPE_Video,
5928 .inputs =
5930 {.subtype = &MEDIASUBTYPE_YV12},
5931 {.subtype = &MEDIASUBTYPE_YUY2},
5932 {.subtype = &MEDIASUBTYPE_UYVY},
5933 {.subtype = &MEDIASUBTYPE_AYUV},
5934 {.subtype = &MEDIASUBTYPE_NV12},
5935 {.subtype = &MEDIASUBTYPE_RGB32},
5936 {.subtype = &MEDIASUBTYPE_RGB565},
5937 {.subtype = &MEDIASUBTYPE_I420},
5938 {.subtype = &MEDIASUBTYPE_IYUV},
5939 {.subtype = &MEDIASUBTYPE_YVYU},
5940 {.subtype = &MEDIASUBTYPE_RGB24},
5941 {.subtype = &MEDIASUBTYPE_RGB555},
5942 {.subtype = &MEDIASUBTYPE_RGB8},
5943 {.subtype = &MEDIASUBTYPE_V216},
5944 {.subtype = &MEDIASUBTYPE_V410},
5945 {.subtype = &MEDIASUBTYPE_NV11},
5946 {.subtype = &MEDIASUBTYPE_Y41P},
5947 {.subtype = &MEDIASUBTYPE_Y41T},
5948 {.subtype = &MEDIASUBTYPE_Y42T},
5949 {.subtype = &MEDIASUBTYPE_YVU9},
5951 .outputs =
5953 {.subtype = &MEDIASUBTYPE_YV12},
5954 {.subtype = &MEDIASUBTYPE_YUY2},
5955 {.subtype = &MEDIASUBTYPE_UYVY},
5956 {.subtype = &MEDIASUBTYPE_AYUV},
5957 {.subtype = &MEDIASUBTYPE_NV12},
5958 {.subtype = &MEDIASUBTYPE_RGB32},
5959 {.subtype = &MEDIASUBTYPE_RGB565},
5960 {.subtype = &MEDIASUBTYPE_I420},
5961 {.subtype = &MEDIASUBTYPE_IYUV},
5962 {.subtype = &MEDIASUBTYPE_YVYU},
5963 {.subtype = &MEDIASUBTYPE_RGB24},
5964 {.subtype = &MEDIASUBTYPE_RGB555},
5965 {.subtype = &MEDIASUBTYPE_RGB8},
5966 {.subtype = &MEDIASUBTYPE_V216},
5967 {.subtype = &MEDIASUBTYPE_V410},
5968 {.subtype = &MEDIASUBTYPE_NV11},
5972 static const media_type_desc expect_available_inputs[20] =
5974 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12), },
5975 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), },
5976 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY), },
5977 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_AYUV), },
5978 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), },
5979 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), },
5980 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565), },
5981 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420), },
5982 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV), },
5983 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU), },
5984 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24), },
5985 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555), },
5986 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_RGB8), },
5987 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V216), },
5988 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V410), },
5989 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11), },
5990 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y41P), },
5991 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y41T), },
5992 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_Y42T), },
5993 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVU9), },
5995 static const media_type_desc expect_available_outputs[16] =
5997 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YV12), },
5998 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YUY2), },
5999 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_UYVY), },
6000 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_AYUV), },
6001 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), },
6002 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32), },
6003 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB565), },
6004 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_I420), },
6005 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_IYUV), },
6006 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_YVYU), },
6007 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB24), },
6008 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555), },
6009 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_RGB8), },
6010 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V216), },
6011 { ATTR_GUID(MF_MT_SUBTYPE, MEDIASUBTYPE_V410), },
6012 { ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV11), },
6014 static const media_type_desc expect_available_common =
6016 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6017 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6018 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6021 static const MFVideoArea actual_aperture = {.Area={82,84}};
6022 static const DWORD actual_width = 96, actual_height = 96;
6023 const struct attribute_desc input_type_desc[] =
6025 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
6026 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE),
6027 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
6028 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
6029 {0},
6031 const struct attribute_desc output_type_desc[] =
6033 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
6034 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32, .required = TRUE),
6035 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
6036 {0},
6038 const struct attribute_desc output_type_desc_negative_stride[] =
6040 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
6041 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32, .required = TRUE),
6042 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
6043 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, -actual_width * 4),
6044 {0},
6046 const struct attribute_desc output_type_desc_positive_stride[] =
6048 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
6049 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32, .required = TRUE),
6050 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
6051 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 4),
6052 {0},
6054 const struct attribute_desc expect_input_type_desc[] =
6056 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6057 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12),
6058 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
6059 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
6060 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width),
6061 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 3 / 2),
6062 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6063 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6064 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6065 {0},
6067 const struct attribute_desc expect_output_type_desc[] =
6069 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6070 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
6071 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
6072 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 4),
6073 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 4),
6074 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6075 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6076 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6077 {0},
6079 const struct attribute_desc expect_output_type_desc_negative_stride[] =
6081 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6082 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32),
6083 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height),
6084 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, -actual_width * 4),
6085 ATTR_UINT32(MF_MT_SAMPLE_SIZE, actual_width * actual_height * 4),
6086 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
6087 ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1),
6088 ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1),
6089 {0},
6091 const MFT_OUTPUT_STREAM_INFO output_info =
6093 .cbSize = actual_width * actual_height * 4,
6094 .cbAlignment = 1,
6096 const MFT_INPUT_STREAM_INFO input_info =
6098 .cbSize = actual_width * actual_height * 3 / 2,
6099 .cbAlignment = 1,
6102 const struct buffer_desc output_buffer_desc =
6104 .length = actual_width * actual_height * 4,
6105 .compare = compare_rgb32, .dump = dump_rgb32, .rect = {.right = 82, .bottom = 84},
6107 const struct attribute_desc output_sample_attributes[] =
6109 ATTR_UINT32(MFSampleExtension_CleanPoint, 0, .todo = TRUE),
6110 {0},
6112 const struct sample_desc output_sample_desc =
6114 .attributes = output_sample_attributes,
6115 .sample_time = 0, .sample_duration = 10000000,
6116 .buffer_count = 1, .buffers = &output_buffer_desc,
6118 const struct transform_desc
6120 const struct attribute_desc *output_type_desc;
6121 const struct attribute_desc *expect_output_type_desc;
6122 const WCHAR *result_bitmap;
6123 ULONG delta;
6125 color_conversion_tests[] =
6129 /* YUV -> RGB */
6130 .output_type_desc = output_type_desc,
6131 .expect_output_type_desc = expect_output_type_desc,
6132 .result_bitmap = L"rgb32frame.bmp",
6133 .delta = 4, /* Windows return 0, Wine needs 4 */
6137 /* YUV -> RGB (negative stride) */
6138 .output_type_desc = output_type_desc_negative_stride,
6139 .expect_output_type_desc = expect_output_type_desc_negative_stride,
6140 .result_bitmap = L"rgb32frame-flip.bmp",
6141 .delta = 6,
6145 /* YUV -> RGB (positive stride) */
6146 .output_type_desc = output_type_desc_positive_stride,
6147 .expect_output_type_desc = expect_output_type_desc,
6148 .result_bitmap = L"rgb32frame.bmp",
6149 .delta = 4, /* Windows return 0, Wine needs 4 */
6154 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
6155 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_I420};
6156 IMFSample *input_sample, *output_sample;
6157 IMFCollection *output_samples;
6158 DWORD length, output_status;
6159 const BYTE *nv12frame_data;
6160 ULONG nv12frame_data_len;
6161 IMFMediaType *media_type;
6162 IMFTransform *transform;
6163 ULONG i, ret, ref;
6164 HRESULT hr;
6166 hr = CoInitialize(NULL);
6167 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
6169 winetest_push_context("colorconv");
6171 if (!check_mft_enum(MFT_CATEGORY_VIDEO_EFFECT, &input_type, &output_type, class_id))
6172 goto failed;
6173 check_mft_get_info(class_id, &expect_mft_info);
6174 check_dmo_get_info(class_id, &expect_dmo_info);
6176 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
6177 &IID_IMFTransform, (void **)&transform)))
6178 goto failed;
6180 check_interface(transform, &IID_IMFTransform, TRUE);
6181 check_interface(transform, &IID_IMediaObject, TRUE);
6182 check_interface(transform, &IID_IPropertyStore, TRUE);
6183 todo_wine
6184 check_interface(transform, &IID_IPropertyBag, FALSE);
6185 todo_wine
6186 check_interface(transform, &IID_IMFRealTimeClient, TRUE);
6187 /* check_interface(transform, &IID_IWMColorConvProps, TRUE); */
6189 check_mft_optional_methods(transform, 1);
6190 check_mft_get_attributes(transform, NULL, FALSE);
6191 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
6192 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
6194 i = -1;
6195 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
6197 winetest_push_context("out %lu", i);
6198 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
6199 check_media_type(media_type, expect_available_common, -1);
6200 check_media_type(media_type, expect_available_outputs[i], -1);
6201 ret = IMFMediaType_Release(media_type);
6202 ok(ret == 0, "Release returned %lu\n", ret);
6203 winetest_pop_context();
6205 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
6206 ok(i == 16, "%lu output media types\n", i);
6208 i = -1;
6209 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
6211 winetest_push_context("in %lu", i);
6212 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
6213 check_media_type(media_type, expect_available_common, -1);
6214 check_media_type(media_type, expect_available_inputs[i], -1);
6215 ret = IMFMediaType_Release(media_type);
6216 ok(ret == 0, "Release returned %lu\n", ret);
6217 winetest_pop_context();
6219 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
6220 ok(i == 20, "%lu input media types\n", i);
6222 check_mft_set_input_type_required(transform, input_type_desc);
6223 check_mft_set_input_type(transform, input_type_desc);
6224 check_mft_get_input_current_type_(transform, expect_input_type_desc, FALSE, TRUE);
6226 for (i = 0; i < ARRAY_SIZE(color_conversion_tests); i++)
6228 winetest_push_context("color conversion #%lu", i);
6229 check_mft_set_output_type_required(transform, color_conversion_tests[i].output_type_desc);
6230 check_mft_set_output_type(transform, color_conversion_tests[i].output_type_desc, S_OK);
6231 check_mft_get_output_current_type_(transform, color_conversion_tests[i].expect_output_type_desc, FALSE, TRUE);
6233 check_mft_get_input_stream_info(transform, S_OK, &input_info);
6234 check_mft_get_output_stream_info(transform, S_OK, &output_info);
6236 load_resource(L"nv12frame.bmp", &nv12frame_data, &nv12frame_data_len);
6237 /* skip BMP header and RGB data from the dump */
6238 length = *(DWORD *)(nv12frame_data + 2);
6239 nv12frame_data_len = nv12frame_data_len - length;
6240 nv12frame_data = nv12frame_data + length;
6241 ok(nv12frame_data_len == 13824, "got length %lu\n", nv12frame_data_len);
6243 input_sample = create_sample(nv12frame_data, nv12frame_data_len);
6244 hr = IMFSample_SetSampleTime(input_sample, 0);
6245 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
6246 hr = IMFSample_SetSampleDuration(input_sample, 10000000);
6247 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
6248 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
6249 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
6250 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
6251 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
6252 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
6253 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
6254 ret = IMFSample_Release(input_sample);
6255 ok(ret <= 1, "Release returned %ld\n", ret);
6257 hr = MFCreateCollection(&output_samples);
6258 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
6260 output_sample = create_sample(NULL, output_info.cbSize);
6261 hr = check_mft_process_output(transform, output_sample, &output_status);
6262 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
6263 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
6264 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
6265 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
6266 ref = IMFSample_Release(output_sample);
6267 ok(ref == 1, "Release returned %ld\n", ref);
6269 ret = check_mf_sample_collection(output_samples, &output_sample_desc, color_conversion_tests[i].result_bitmap);
6270 ok(ret <= color_conversion_tests[i].delta, "got %lu%% diff\n", ret);
6271 IMFCollection_Release(output_samples);
6273 output_sample = create_sample(NULL, output_info.cbSize);
6274 hr = check_mft_process_output(transform, output_sample, &output_status);
6275 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
6276 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
6277 hr = IMFSample_GetTotalLength(output_sample, &length);
6278 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
6279 ok(length == 0, "got length %lu\n", length);
6280 ret = IMFSample_Release(output_sample);
6281 ok(ret == 0, "Release returned %lu\n", ret);
6282 winetest_pop_context();
6285 ret = IMFTransform_Release(transform);
6286 ok(ret == 0, "Release returned %ld\n", ret);
6288 failed:
6289 winetest_pop_context();
6290 CoUninitialize();
6293 static void test_video_processor(void)
6295 const GUID *const class_id = &CLSID_VideoProcessorMFT;
6296 const struct transform_info expect_mft_info =
6298 .name = L"Microsoft Video Processor MFT",
6299 .major_type = &MFMediaType_Video,
6300 .inputs =
6302 {.subtype = &MFVideoFormat_IYUV},
6303 {.subtype = &MFVideoFormat_YV12},
6304 {.subtype = &MFVideoFormat_NV12},
6305 {.subtype = &MFVideoFormat_YUY2},
6306 {.subtype = &MFVideoFormat_ARGB32},
6307 {.subtype = &MFVideoFormat_RGB32},
6308 {.subtype = &MFVideoFormat_NV11},
6309 {.subtype = &MFVideoFormat_AYUV},
6310 {.subtype = &MFVideoFormat_UYVY},
6311 {.subtype = &MEDIASUBTYPE_P208},
6312 {.subtype = &MFVideoFormat_RGB24},
6313 {.subtype = &MFVideoFormat_RGB555},
6314 {.subtype = &MFVideoFormat_RGB565},
6315 {.subtype = &MFVideoFormat_RGB8},
6316 {.subtype = &MFVideoFormat_I420},
6317 {.subtype = &MFVideoFormat_Y216},
6318 {.subtype = &MFVideoFormat_v410},
6319 {.subtype = &MFVideoFormat_Y41P},
6320 {.subtype = &MFVideoFormat_Y41T},
6321 {.subtype = &MFVideoFormat_Y42T},
6322 {.subtype = &MFVideoFormat_YVYU},
6323 {.subtype = &MFVideoFormat_420O},
6325 .outputs =
6327 {.subtype = &MFVideoFormat_IYUV},
6328 {.subtype = &MFVideoFormat_YV12},
6329 {.subtype = &MFVideoFormat_NV12},
6330 {.subtype = &MFVideoFormat_YUY2},
6331 {.subtype = &MFVideoFormat_ARGB32},
6332 {.subtype = &MFVideoFormat_RGB32},
6333 {.subtype = &MFVideoFormat_NV11},
6334 {.subtype = &MFVideoFormat_AYUV},
6335 {.subtype = &MFVideoFormat_UYVY},
6336 {.subtype = &MEDIASUBTYPE_P208},
6337 {.subtype = &MFVideoFormat_RGB24},
6338 {.subtype = &MFVideoFormat_RGB555},
6339 {.subtype = &MFVideoFormat_RGB565},
6340 {.subtype = &MFVideoFormat_RGB8},
6341 {.subtype = &MFVideoFormat_I420},
6342 {.subtype = &MFVideoFormat_Y216},
6343 {.subtype = &MFVideoFormat_v410},
6344 {.subtype = &MFVideoFormat_Y41P},
6345 {.subtype = &MFVideoFormat_Y41T},
6346 {.subtype = &MFVideoFormat_Y42T},
6347 {.subtype = &MFVideoFormat_YVYU},
6350 const struct input_type_desc
6352 GUID guid;
6353 BOOL optional;
6355 expect_available_inputs[] =
6357 {MFVideoFormat_L8, .optional = TRUE /* >= W10 */},
6358 {MFVideoFormat_L16, .optional = TRUE /* >= W10 */},
6359 {MFAudioFormat_MPEG, .optional = TRUE /* >= W10 */},
6360 {MFVideoFormat_IYUV},
6361 {MFVideoFormat_YV12},
6362 {MFVideoFormat_NV12},
6363 {MFVideoFormat_NV21, .optional = TRUE /* >= W11 */},
6364 {MFVideoFormat_420O},
6365 {MFVideoFormat_P010, .optional = TRUE /* >= W10 */},
6366 {MFVideoFormat_P016, .optional = TRUE /* >= W10 */},
6367 {MFVideoFormat_UYVY},
6368 {MFVideoFormat_YUY2},
6369 {MFVideoFormat_P208},
6370 {MFVideoFormat_NV11},
6371 {MFVideoFormat_AYUV},
6372 {MFVideoFormat_ARGB32},
6373 {MFVideoFormat_ABGR32, .optional = TRUE /* >= W10 */},
6374 {MFVideoFormat_RGB32},
6375 {MFVideoFormat_A2R10G10B10, .optional = TRUE /* >= W10 */},
6376 {MFVideoFormat_A16B16G16R16F, .optional = TRUE /* >= W10 */},
6377 {MFVideoFormat_RGB24},
6378 {MFVideoFormat_I420},
6379 {MFVideoFormat_YVYU},
6380 {MFVideoFormat_RGB555},
6381 {MFVideoFormat_RGB565},
6382 {MFVideoFormat_RGB8},
6383 {MFVideoFormat_Y216},
6384 {MFVideoFormat_v410},
6385 {MFVideoFormat_Y41P},
6386 {MFVideoFormat_Y41T},
6387 {MFVideoFormat_Y42T},
6389 const GUID expect_available_outputs[] =
6391 MFVideoFormat_A2R10G10B10, /* enumerated with MFVideoFormat_P010 input */
6392 MFVideoFormat_P010, /* enumerated with MFVideoFormat_A2R10G10B10 input */
6393 MFVideoFormat_YUY2,
6394 MFVideoFormat_IYUV,
6395 MFVideoFormat_I420,
6396 MFVideoFormat_NV12,
6397 MFVideoFormat_RGB24,
6398 MFVideoFormat_ARGB32,
6399 MFVideoFormat_RGB32,
6400 MFVideoFormat_YV12,
6401 MFVideoFormat_Y216, /* enumerated with some input formats */
6402 MFVideoFormat_UYVY, /* enumerated with some input formats */
6403 MFVideoFormat_YVYU, /* enumerated with some input formats */
6404 MFVideoFormat_AYUV,
6405 MFVideoFormat_RGB555,
6406 MFVideoFormat_RGB565,
6407 MFVideoFormat_AYUV, /* some inputs enumerate MFVideoFormat_AYUV after RGB565 */
6408 MFVideoFormat_NV12, /* P010 enumerates NV12 after (A)RGB32 formats */
6409 MFVideoFormat_A16B16G16R16F, /* enumerated with MFVideoFormat_P010 input */
6410 MFVideoFormat_NV21, /* enumerated with some input formats */
6412 static const media_type_desc expect_available_common =
6414 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video),
6416 static const struct attribute_desc expect_transform_attributes[] =
6418 ATTR_UINT32(MFT_SUPPORT_3DVIDEO, 1, .todo = TRUE),
6419 /* ATTR_UINT32(MF_SA_D3D_AWARE, 1), only on W7 */
6420 {0},
6423 static const MFVideoArea actual_aperture = {.Area={82,84}};
6424 static const DWORD actual_width = 96, actual_height = 96;
6425 const struct attribute_desc rgb32_with_aperture[] =
6427 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
6428 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32, .required = TRUE),
6429 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
6430 ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16),
6431 {0},
6433 const struct attribute_desc nv12_default_stride[] =
6435 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
6436 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12, .required = TRUE),
6437 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
6438 {0},
6440 const struct attribute_desc rgb32_default_stride[] =
6442 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
6443 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32, .required = TRUE),
6444 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
6445 {0},
6447 const struct attribute_desc rgb32_negative_stride[] =
6449 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
6450 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32, .required = TRUE),
6451 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
6452 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, -actual_width * 4),
6453 {0},
6455 const struct attribute_desc rgb32_positive_stride[] =
6457 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
6458 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32, .required = TRUE),
6459 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
6460 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 4),
6461 {0},
6463 const struct attribute_desc rgb555_default_stride[] =
6465 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
6466 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555, .required = TRUE),
6467 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
6468 {0},
6470 const struct attribute_desc rgb555_negative_stride[] =
6472 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
6473 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555, .required = TRUE),
6474 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
6475 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, -actual_width * 2),
6476 {0},
6478 const struct attribute_desc rgb555_positive_stride[] =
6480 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE),
6481 ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_RGB555, .required = TRUE),
6482 ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE),
6483 ATTR_UINT32(MF_MT_DEFAULT_STRIDE, actual_width * 2),
6484 {0},
6486 const MFT_OUTPUT_STREAM_INFO initial_output_info = {0};
6487 const MFT_INPUT_STREAM_INFO initial_input_info = {0};
6488 MFT_OUTPUT_STREAM_INFO output_info = {0};
6489 MFT_INPUT_STREAM_INFO input_info = {0};
6491 const struct attribute_desc output_sample_attributes[] =
6493 ATTR_UINT32(MFSampleExtension_CleanPoint, 1, .todo = TRUE),
6494 {0},
6496 const struct buffer_desc rgb32_buffer_desc =
6498 .length = actual_width * actual_height * 4,
6499 .compare = compare_rgb32, .dump = dump_rgb32, .rect = {.top = 12, .right = 82, .bottom = 96},
6501 const struct sample_desc rgb32_sample_desc =
6503 .attributes = output_sample_attributes,
6504 .sample_time = 0, .sample_duration = 10000000,
6505 .buffer_count = 1, .buffers = &rgb32_buffer_desc,
6508 const struct buffer_desc rgb555_buffer_desc =
6510 .length = actual_width * actual_height * 2,
6511 .compare = compare_rgb16, .dump = dump_rgb16, .rect = {.top = 12, .right = 82, .bottom = 96},
6513 const struct sample_desc rgb555_sample_desc =
6515 .attributes = output_sample_attributes,
6516 .sample_time = 0, .sample_duration = 10000000,
6517 .buffer_count = 1, .buffers = &rgb555_buffer_desc,
6520 const struct buffer_desc nv12_buffer_desc =
6522 .length = actual_width * actual_height * 3 / 2,
6523 .compare = compare_nv12, .dump = dump_nv12, .rect = {.top = 12, .right = 82, .bottom = 96},
6525 const struct sample_desc nv12_sample_desc =
6527 .attributes = output_sample_attributes,
6528 .sample_time = 0, .sample_duration = 10000000,
6529 .buffer_count = 1, .buffers = &nv12_buffer_desc,
6532 const struct transform_desc
6534 const struct attribute_desc *input_type_desc;
6535 const struct attribute_desc *output_type_desc;
6536 const struct sample_desc *output_sample_desc;
6537 const WCHAR *result_bitmap;
6538 ULONG delta;
6539 BOOL broken;
6541 video_processor_tests[] =
6544 .input_type_desc = nv12_default_stride, .output_type_desc = rgb32_default_stride,
6545 .output_sample_desc = &rgb32_sample_desc, .result_bitmap = L"rgb32frame-flip.bmp",
6546 .delta = 2, /* Windows returns 0, Wine needs 2 */
6549 .input_type_desc = nv12_default_stride, .output_type_desc = rgb32_negative_stride,
6550 .output_sample_desc = &rgb32_sample_desc, .result_bitmap = L"rgb32frame-flip.bmp",
6551 .delta = 2, /* Windows returns 0, Wine needs 2 */
6554 .input_type_desc = nv12_default_stride, .output_type_desc = rgb32_positive_stride,
6555 .output_sample_desc = &rgb32_sample_desc, .result_bitmap = L"rgb32frame.bmp",
6556 .delta = 6,
6559 .input_type_desc = rgb32_default_stride, .output_type_desc = nv12_default_stride,
6560 .output_sample_desc = &nv12_sample_desc, .result_bitmap = L"nv12frame-flip.bmp",
6561 .delta = 2, /* Windows returns 0, Wine needs 2 */
6564 .input_type_desc = rgb32_negative_stride, .output_type_desc = nv12_default_stride,
6565 .output_sample_desc = &nv12_sample_desc, .result_bitmap = L"nv12frame-flip.bmp",
6566 .delta = 2, /* Windows returns 0, Wine needs 2 */
6569 .input_type_desc = rgb32_positive_stride, .output_type_desc = nv12_default_stride,
6570 .output_sample_desc = &nv12_sample_desc, .result_bitmap = L"nv12frame.bmp",
6571 .delta = 2, /* Windows returns 1, Wine needs 2 */
6574 .input_type_desc = rgb32_negative_stride, .output_type_desc = rgb32_negative_stride,
6575 .output_sample_desc = &rgb32_sample_desc, .result_bitmap = L"rgb32frame.bmp",
6578 .input_type_desc = rgb32_negative_stride, .output_type_desc = rgb32_positive_stride,
6579 .output_sample_desc = &rgb32_sample_desc, .result_bitmap = L"rgb32frame-flip.bmp",
6580 .delta = 3, /* Windows returns 3 */
6583 .input_type_desc = rgb32_positive_stride, .output_type_desc = rgb32_negative_stride,
6584 .output_sample_desc = &rgb32_sample_desc, .result_bitmap = L"rgb32frame-flip.bmp",
6585 .delta = 3, /* Windows returns 3 */
6588 .input_type_desc = rgb32_positive_stride, .output_type_desc = rgb32_positive_stride,
6589 .output_sample_desc = &rgb32_sample_desc, .result_bitmap = L"rgb32frame.bmp",
6592 .input_type_desc = rgb32_with_aperture, .output_type_desc = rgb32_with_aperture,
6593 .output_sample_desc = &rgb32_sample_desc, .result_bitmap = L"rgb32frame.bmp",
6594 .broken = TRUE /* old Windows version incorrectly rescale */
6597 .input_type_desc = rgb32_default_stride, .output_type_desc = rgb555_default_stride,
6598 .output_sample_desc = &rgb555_sample_desc, .result_bitmap = L"rgb555frame.bmp",
6601 .input_type_desc = rgb32_default_stride, .output_type_desc = rgb555_negative_stride,
6602 .output_sample_desc = &rgb555_sample_desc, .result_bitmap = L"rgb555frame.bmp",
6605 .input_type_desc = rgb32_default_stride, .output_type_desc = rgb555_positive_stride,
6606 .output_sample_desc = &rgb555_sample_desc, .result_bitmap = L"rgb555frame-flip.bmp",
6607 .delta = 3, /* Windows returns 0, Wine needs 3 */
6610 .input_type_desc = rgb555_default_stride, .output_type_desc = rgb555_positive_stride,
6611 .output_sample_desc = &rgb555_sample_desc, .result_bitmap = L"rgb555frame-flip.bmp",
6612 .delta = 4, /* Windows returns 0, Wine needs 4 */
6616 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12};
6617 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_I420};
6618 const struct input_type_desc *expect_input = expect_available_inputs;
6619 DWORD i, j, k, flags, length, output_status;
6620 IMFSample *input_sample, *output_sample;
6621 IMFMediaType *media_type, *media_type2;
6622 IMFCollection *output_samples;
6623 IMFTransform *transform;
6624 IMFMediaBuffer *buffer;
6625 const BYTE *input_data;
6626 ULONG input_data_len;
6627 UINT32 count;
6628 HRESULT hr;
6629 ULONG ret;
6630 GUID guid;
6631 LONG ref;
6633 hr = CoInitialize(NULL);
6634 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
6636 winetest_push_context("videoproc");
6638 if (!check_mft_enum(MFT_CATEGORY_VIDEO_PROCESSOR, &input_type, &output_type, class_id))
6639 goto failed;
6640 check_mft_get_info(class_id, &expect_mft_info);
6642 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
6643 &IID_IMFTransform, (void **)&transform)))
6644 goto failed;
6646 todo_wine
6647 check_interface(transform, &IID_IMFVideoProcessorControl, TRUE);
6648 todo_wine
6649 check_interface(transform, &IID_IMFRealTimeClientEx, TRUE);
6650 check_interface(transform, &IID_IMFMediaEventGenerator, FALSE);
6651 check_interface(transform, &IID_IMFShutdown, FALSE);
6653 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
6654 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
6656 hr = IMFTransform_GetOutputStatus(transform, &flags);
6657 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
6659 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
6660 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
6662 check_mft_get_input_current_type(transform, NULL);
6663 check_mft_get_output_current_type(transform, NULL);
6665 check_mft_get_input_stream_info(transform, S_OK, &initial_input_info);
6666 check_mft_get_output_stream_info(transform, S_OK, &initial_output_info);
6668 /* Configure stream types. */
6669 for (i = 0;;++i)
6671 if (FAILED(hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type)))
6673 ok(hr == MF_E_NO_MORE_TYPES, "Unexpected hr %#lx.\n", hr);
6674 break;
6677 hr = IMFTransform_GetInputAvailableType(transform, 0, i, &media_type2);
6678 ok(hr == S_OK, "Failed to get available type, hr %#lx.\n", hr);
6679 ok(media_type != media_type2, "Unexpected instance.\n");
6680 ref = IMFMediaType_Release(media_type2);
6681 ok(ref == 0, "Release returned %ld\n", ref);
6683 hr = IMFMediaType_GetMajorType(media_type, &guid);
6684 ok(hr == S_OK, "Failed to get major type, hr %#lx.\n", hr);
6685 ok(IsEqualGUID(&guid, &MFMediaType_Video), "Unexpected major type.\n");
6687 hr = IMFMediaType_GetCount(media_type, &count);
6688 ok(hr == S_OK, "Failed to get attributes count, hr %#lx.\n", hr);
6689 ok(count == 2, "Unexpected count %u.\n", count);
6691 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
6692 ok(hr == S_OK, "Failed to get subtype, hr %#lx.\n", hr);
6693 ok(is_supported_video_type(&guid), "Unexpected media type %s.\n", wine_dbgstr_guid(&guid));
6695 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
6696 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
6698 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6699 ok(FAILED(hr), "Unexpected hr %#lx.\n", hr);
6701 hr = IMFTransform_GetOutputCurrentType(transform, 0, &media_type2);
6702 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "Unexpected hr %#lx.\n", hr);
6704 /* FIXME: figure out if those require additional attributes or simply advertised but not supported */
6705 if (IsEqualGUID(&guid, &MFVideoFormat_L8) || IsEqualGUID(&guid, &MFVideoFormat_L16)
6706 || IsEqualGUID(&guid, &MFVideoFormat_D16) || IsEqualGUID(&guid, &MFVideoFormat_420O)
6707 || IsEqualGUID(&guid, &MFVideoFormat_A16B16G16R16F))
6709 ref = IMFMediaType_Release(media_type);
6710 ok(ref == 0, "Release returned %ld\n", ref);
6711 continue;
6714 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
6715 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
6717 hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY);
6718 ok(hr == S_OK, "Failed to test input type %s, hr %#lx.\n", wine_dbgstr_guid(&guid), hr);
6720 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6721 ok(hr == S_OK, "Failed to test input type, hr %#lx.\n", hr);
6723 hr = IMFTransform_GetInputCurrentType(transform, 0, &media_type2);
6724 ok(hr == S_OK, "Failed to get current type, hr %#lx.\n", hr);
6725 ok(media_type != media_type2, "Unexpected instance.\n");
6726 IMFMediaType_Release(media_type2);
6728 hr = IMFTransform_GetInputStatus(transform, 0, &flags);
6729 ok(hr == S_OK, "Failed to get input status, hr %#lx.\n", hr);
6730 ok(flags == MFT_INPUT_STATUS_ACCEPT_DATA, "Unexpected input status %#lx.\n", flags);
6732 input_info.cbSize = 0;
6733 if (IsEqualGUID(&guid, &MFVideoFormat_NV21))
6734 input_info.cbSize = 0x180;
6735 else if (!IsEqualGUID(&guid, &MFVideoFormat_P208) && !IsEqualGUID(&guid, &MEDIASUBTYPE_Y41T)
6736 && !IsEqualGUID(&guid, &MEDIASUBTYPE_Y42T))
6738 hr = MFCalculateImageSize(&guid, 16, 16, (UINT32 *)&input_info.cbSize);
6739 todo_wine_if(IsEqualGUID(&guid, &MFVideoFormat_Y216)
6740 || IsEqualGUID(&guid, &MFVideoFormat_v410)
6741 || IsEqualGUID(&guid, &MFVideoFormat_Y41P))
6742 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6744 check_mft_get_input_stream_info(transform, S_OK, &input_info);
6745 check_mft_get_output_stream_info(transform, S_OK, &initial_output_info);
6747 IMFMediaType_Release(media_type);
6750 /* IYUV -> RGB32 */
6751 hr = MFCreateMediaType(&media_type);
6752 ok(hr == S_OK, "Failed to create media type, hr %#lx.\n", hr);
6754 hr = IMFMediaType_SetGUID(media_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
6755 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
6757 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_IYUV);
6758 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
6760 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, ((UINT64)16 << 32) | 16);
6761 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
6763 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6764 ok(hr == S_OK, "Failed to set input type, hr %#lx.\n", hr);
6766 hr = IMFMediaType_SetGUID(media_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB32);
6767 ok(hr == S_OK, "Failed to set attribute, hr %#lx.\n", hr);
6769 hr = IMFTransform_SetOutputType(transform, 0, media_type, 0);
6770 ok(hr == S_OK, "Failed to set output type, hr %#lx.\n", hr);
6772 hr = MFCalculateImageSize(&MFVideoFormat_IYUV, 16, 16, (UINT32 *)&input_info.cbSize);
6773 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6774 hr = MFCalculateImageSize(&MFVideoFormat_RGB32, 16, 16, (UINT32 *)&output_info.cbSize);
6775 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6776 check_mft_get_input_stream_info(transform, S_OK, &input_info);
6777 check_mft_get_output_stream_info(transform, S_OK, &output_info);
6779 hr = MFCreateSample(&input_sample);
6780 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
6782 hr = MFCreateSample(&output_sample);
6783 ok(hr == S_OK, "Failed to create a sample, hr %#lx.\n", hr);
6785 hr = check_mft_process_output(transform, output_sample, &output_status);
6786 todo_wine
6787 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#lx.\n", hr);
6789 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
6790 todo_wine
6791 ok(hr == S_OK, "Failed to push a sample, hr %#lx.\n", hr);
6793 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
6794 todo_wine
6795 ok(hr == MF_E_NOTACCEPTING, "Unexpected hr %#lx.\n", hr);
6797 hr = check_mft_process_output(transform, output_sample, &output_status);
6798 todo_wine
6799 ok(hr == MF_E_NO_SAMPLE_TIMESTAMP, "Unexpected hr %#lx.\n", hr);
6801 hr = IMFSample_SetSampleTime(input_sample, 0);
6802 ok(hr == S_OK, "Failed to set sample time, hr %#lx.\n", hr);
6803 hr = check_mft_process_output(transform, output_sample, &output_status);
6804 todo_wine
6805 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6807 hr = MFCreateMemoryBuffer(1024 * 1024, &buffer);
6808 ok(hr == S_OK, "Failed to create a buffer, hr %#lx.\n", hr);
6810 hr = IMFSample_AddBuffer(input_sample, buffer);
6811 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
6813 hr = IMFSample_AddBuffer(output_sample, buffer);
6814 ok(hr == S_OK, "Failed to add a buffer, hr %#lx.\n", hr);
6816 hr = check_mft_process_output(transform, output_sample, &output_status);
6817 todo_wine
6818 ok(hr == S_OK || broken(FAILED(hr)) /* Win8 */, "Failed to get output buffer, hr %#lx.\n", hr);
6820 if (SUCCEEDED(hr))
6822 hr = check_mft_process_output(transform, output_sample, &output_status);
6823 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "Unexpected hr %#lx.\n", hr);
6826 ref = IMFTransform_Release(transform);
6827 ok(ref == 0, "Release returned %ld\n", ref);
6829 ref = IMFMediaType_Release(media_type);
6830 ok(ref == 0, "Release returned %ld\n", ref);
6831 ref = IMFSample_Release(input_sample);
6832 ok(ref == 0, "Release returned %ld\n", ref);
6833 ref = IMFSample_Release(output_sample);
6834 ok(ref == 0, "Release returned %ld\n", ref);
6835 ref = IMFMediaBuffer_Release(buffer);
6836 ok(ref == 0, "Release returned %ld\n", ref);
6839 hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER, &IID_IMFTransform, (void **)&transform);
6840 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6842 check_interface(transform, &IID_IMFTransform, TRUE);
6843 check_interface(transform, &IID_IMediaObject, FALSE);
6844 check_interface(transform, &IID_IPropertyStore, FALSE);
6845 check_interface(transform, &IID_IPropertyBag, FALSE);
6847 check_mft_optional_methods(transform, 1);
6848 check_mft_get_attributes(transform, expect_transform_attributes, TRUE);
6849 check_mft_get_input_stream_info(transform, S_OK, &initial_input_info);
6850 check_mft_get_output_stream_info(transform, S_OK, &initial_output_info);
6852 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
6853 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
6855 i = -1;
6856 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
6858 winetest_push_context("in %lu", i);
6860 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
6861 check_media_type(media_type, expect_available_common, -1);
6863 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
6864 ok(hr == S_OK, "GetGUID returned %#lx\n", hr);
6866 while (!IsEqualGUID(&expect_input->guid, &guid))
6868 if (!expect_input->optional)
6869 break;
6870 expect_input++;
6872 ok(IsEqualGUID(&expect_input->guid, &guid), "got subtype %s\n", debugstr_guid(&guid));
6873 expect_input++;
6875 /* FIXME: Skip exotic input types which aren't directly accepted */
6876 if (IsEqualGUID(&guid, &MFVideoFormat_L8) || IsEqualGUID(&guid, &MFVideoFormat_L16)
6877 || IsEqualGUID(&guid, &MFAudioFormat_MPEG) || IsEqualGUID(&guid, &MFVideoFormat_420O)
6878 || IsEqualGUID(&guid, &MFVideoFormat_A16B16G16R16F) /* w1064v1507 */)
6880 IMFMediaType_Release(media_type);
6881 winetest_pop_context();
6882 continue;
6885 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6886 ok(hr == MF_E_ATTRIBUTENOTFOUND, "SetInputType returned %#lx.\n", hr);
6887 hr = IMFMediaType_SetUINT64(media_type, &MF_MT_FRAME_SIZE, (UINT64)actual_width << 32 | actual_height);
6888 ok(hr == S_OK, "SetUINT64 returned %#lx.\n", hr);
6889 hr = IMFTransform_SetInputType(transform, 0, media_type, 0);
6890 ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
6892 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type2);
6893 ok(hr == S_OK, "GetOutputAvailableType returned %#lx.\n", hr);
6894 hr = IMFMediaType_IsEqual(media_type, media_type2, &flags);
6895 ok(hr == S_OK, "IsEqual returned %#lx.\n", hr);
6896 IMFMediaType_Release(media_type2);
6898 ret = IMFMediaType_Release(media_type);
6899 ok(ret == 1, "Release returned %lu\n", ret);
6901 j = k = 0;
6902 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++j, &media_type)))
6904 winetest_push_context("out %lu", j);
6905 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
6906 check_media_type(media_type, expect_available_common, -1);
6908 hr = IMFMediaType_GetGUID(media_type, &MF_MT_SUBTYPE, &guid);
6909 ok(hr == S_OK, "GetGUID returned %#lx\n", hr);
6911 for (; k < ARRAY_SIZE(expect_available_outputs); k++)
6912 if (IsEqualGUID(&expect_available_outputs[k], &guid))
6913 break;
6914 ok(k < ARRAY_SIZE(expect_available_outputs), "got subtype %s\n", debugstr_guid(&guid));
6916 ret = IMFMediaType_Release(media_type);
6917 ok(ret == 0, "Release returned %lu\n", ret);
6918 winetest_pop_context();
6920 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
6922 winetest_pop_context();
6924 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
6926 for (i = 0; i < ARRAY_SIZE(video_processor_tests); i++)
6928 const struct transform_desc *test = video_processor_tests + i;
6930 winetest_push_context("transform #%lu", i);
6932 check_mft_set_input_type_required(transform, test->input_type_desc);
6933 check_mft_set_input_type(transform, test->input_type_desc);
6934 check_mft_get_input_current_type(transform, test->input_type_desc);
6936 check_mft_set_output_type_required(transform, test->output_type_desc);
6937 check_mft_set_output_type(transform, test->output_type_desc, S_OK);
6938 check_mft_get_output_current_type(transform, test->output_type_desc);
6940 if (test->output_sample_desc == &nv12_sample_desc)
6942 output_info.cbSize = actual_width * actual_height * 3 / 2;
6943 check_mft_get_output_stream_info(transform, S_OK, &output_info);
6945 else if (test->output_sample_desc == &rgb555_sample_desc)
6947 output_info.cbSize = actual_width * actual_height * 2;
6948 check_mft_get_output_stream_info(transform, S_OK, &output_info);
6950 else
6952 output_info.cbSize = actual_width * actual_height * 4;
6953 check_mft_get_output_stream_info(transform, S_OK, &output_info);
6956 if (test->input_type_desc == nv12_default_stride)
6958 input_info.cbSize = actual_width * actual_height * 3 / 2;
6959 check_mft_get_input_stream_info(transform, S_OK, &input_info);
6961 load_resource(L"nv12frame.bmp", &input_data, &input_data_len);
6962 /* skip BMP header and RGB data from the dump */
6963 length = *(DWORD *)(input_data + 2);
6964 input_data_len = input_data_len - length;
6965 ok(input_data_len == 13824, "got length %lu\n", input_data_len);
6966 input_data = input_data + length;
6968 else if (test->input_type_desc == rgb555_default_stride)
6970 input_info.cbSize = actual_width * actual_height * 2;
6971 check_mft_get_input_stream_info(transform, S_OK, &input_info);
6973 load_resource(L"rgb555frame.bmp", &input_data, &input_data_len);
6974 /* skip BMP header and RGB data from the dump */
6975 length = *(DWORD *)(input_data + 2 + 2 * sizeof(DWORD));
6976 input_data_len -= length;
6977 ok(input_data_len == 18432, "got length %lu\n", input_data_len);
6978 input_data += length;
6980 else
6982 input_info.cbSize = actual_width * actual_height * 4;
6983 check_mft_get_input_stream_info(transform, S_OK, &input_info);
6985 load_resource(L"rgb32frame.bmp", &input_data, &input_data_len);
6986 /* skip BMP header and RGB data from the dump */
6987 length = *(DWORD *)(input_data + 2 + 2 * sizeof(DWORD));
6988 input_data_len -= length;
6989 ok(input_data_len == 36864, "got length %lu\n", input_data_len);
6990 input_data += length;
6993 input_sample = create_sample(input_data, input_data_len);
6994 hr = IMFSample_SetSampleTime(input_sample, 0);
6995 ok(hr == S_OK, "SetSampleTime returned %#lx\n", hr);
6996 hr = IMFSample_SetSampleDuration(input_sample, 10000000);
6997 ok(hr == S_OK, "SetSampleDuration returned %#lx\n", hr);
6998 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
6999 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
7000 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
7001 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
7002 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
7003 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
7004 ret = IMFSample_Release(input_sample);
7005 ok(ret <= 1, "Release returned %ld\n", ret);
7007 hr = MFCreateCollection(&output_samples);
7008 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
7010 output_sample = create_sample(NULL, output_info.cbSize);
7011 hr = check_mft_process_output(transform, output_sample, &output_status);
7013 ok(hr == S_OK || broken(hr == MF_E_SHUTDOWN) /* w8 */, "ProcessOutput returned %#lx\n", hr);
7014 if (hr != S_OK)
7016 win_skip("ProcessOutput returned MF_E_SHUTDOWN, skipping tests.\n");
7018 else
7020 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
7022 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
7023 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
7024 ref = IMFSample_Release(output_sample);
7025 ok(ref == 1, "Release returned %ld\n", ref);
7027 ret = check_mf_sample_collection(output_samples, test->output_sample_desc, test->result_bitmap);
7028 ok(ret <= test->delta || broken(test->broken), "got %lu%% diff\n", ret);
7029 IMFCollection_Release(output_samples);
7031 output_sample = create_sample(NULL, output_info.cbSize);
7032 hr = check_mft_process_output(transform, output_sample, &output_status);
7033 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
7034 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
7035 hr = IMFSample_GetTotalLength(output_sample, &length);
7036 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7037 ok(length == 0, "got length %lu\n", length);
7039 ret = IMFSample_Release(output_sample);
7040 ok(ret == 0, "Release returned %lu\n", ret);
7041 winetest_pop_context();
7044 ret = IMFTransform_Release(transform);
7045 ok(ret == 0, "Release returned %ld\n", ret);
7047 failed:
7048 winetest_pop_context();
7049 CoUninitialize();
7052 static void test_mp3_decoder(void)
7054 const GUID *const class_id = &CLSID_CMP3DecMediaObject;
7055 const struct transform_info expect_mft_info =
7057 .name = L"MP3 Decoder MFT",
7058 .major_type = &MFMediaType_Audio,
7059 .inputs =
7061 {.subtype = &MFAudioFormat_MP3},
7063 .outputs =
7065 {.subtype = &MFAudioFormat_PCM},
7068 const struct transform_info expect_dmo_info =
7070 .name = L"MP3 Decoder DMO",
7071 .major_type = &MEDIATYPE_Audio,
7072 .inputs =
7074 {.subtype = &MFAudioFormat_MP3},
7076 .outputs =
7078 {.subtype = &MEDIASUBTYPE_PCM},
7082 static const ULONG mp3dec_block_size = 0x1200;
7083 static const media_type_desc expect_available_inputs[] =
7086 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7087 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3),
7088 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7091 static const media_type_desc expect_available_outputs[] =
7094 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7095 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
7096 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
7097 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
7098 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
7099 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 176400),
7100 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 8),
7101 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7104 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7105 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
7106 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
7107 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
7108 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
7109 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
7110 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
7111 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7114 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7115 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
7116 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
7117 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
7118 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
7119 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
7120 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2),
7121 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7124 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7125 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_Float),
7126 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 32),
7127 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
7128 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
7129 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 88200),
7130 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
7131 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7134 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7135 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
7136 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
7137 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
7138 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
7139 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 44100),
7140 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2),
7141 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7144 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7145 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
7146 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 8),
7147 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 1),
7148 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
7149 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 22050),
7150 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 1),
7151 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7155 const struct attribute_desc input_type_desc[] =
7157 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
7158 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3, .required = TRUE),
7159 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
7160 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
7161 {0},
7163 static const struct attribute_desc output_type_desc[] =
7165 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio, .required = TRUE),
7166 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM, .required = TRUE),
7167 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2, .required = TRUE),
7168 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16, .required = TRUE),
7169 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050, .required = TRUE),
7170 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 2 * (16 / 8), .required = TRUE),
7171 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 2 * (16 / 8) * 22050, .required = TRUE),
7172 {0},
7174 const struct attribute_desc expect_input_type_desc[] =
7176 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7177 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_MP3),
7178 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
7179 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
7180 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
7181 {0},
7183 static const struct attribute_desc expect_output_type_desc[] =
7185 ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio),
7186 ATTR_GUID(MF_MT_SUBTYPE, MFAudioFormat_PCM),
7187 ATTR_UINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, 16),
7188 ATTR_UINT32(MF_MT_AUDIO_NUM_CHANNELS, 2),
7189 ATTR_UINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, 22050),
7190 ATTR_UINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, 4),
7191 ATTR_UINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 22050 * 4),
7192 ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1),
7193 ATTR_UINT32(MF_MT_AUDIO_PREFER_WAVEFORMATEX, 1),
7194 {0},
7196 const MFT_OUTPUT_STREAM_INFO output_info =
7198 .cbSize = mp3dec_block_size,
7199 .cbAlignment = 1,
7201 const MFT_INPUT_STREAM_INFO input_info =
7203 .cbAlignment = 1,
7206 const struct buffer_desc output_buffer_desc[] =
7208 {.length = 0x9c0, .compare = compare_pcm16},
7209 {.length = mp3dec_block_size, .compare = compare_pcm16},
7211 const struct attribute_desc output_sample_attributes[] =
7213 ATTR_UINT32(mft_output_sample_incomplete, 1),
7214 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
7215 {0},
7217 const struct sample_desc output_sample_desc[] =
7220 .attributes = output_sample_attributes + 0,
7221 .sample_time = 0, .sample_duration = 282993,
7222 .buffer_count = 1, .buffers = output_buffer_desc + 0,
7225 .attributes = output_sample_attributes + 0,
7226 .sample_time = 282993, .sample_duration = 522449,
7227 .buffer_count = 1, .buffers = output_buffer_desc + 1, .repeat_count = 18,
7230 .attributes = output_sample_attributes + 1, /* not MFT_OUTPUT_DATA_BUFFER_INCOMPLETE */
7231 .sample_time = 10209524, .sample_duration = 522449,
7232 .buffer_count = 1, .buffers = output_buffer_desc + 1,
7236 MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_PCM};
7237 MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_MP3};
7238 IMFSample *input_sample, *output_sample;
7239 IMFCollection *output_samples;
7240 DWORD length, output_status;
7241 IMFMediaType *media_type;
7242 IMFTransform *transform;
7243 const BYTE *mp3enc_data;
7244 ULONG mp3enc_data_len;
7245 ULONG i, ret, ref;
7246 HRESULT hr;
7248 hr = CoInitialize(NULL);
7249 ok(hr == S_OK, "Failed to initialize, hr %#lx.\n", hr);
7251 winetest_push_context("mp3dec");
7253 if (!check_mft_enum(MFT_CATEGORY_AUDIO_DECODER, &input_type, &output_type, class_id))
7254 goto failed;
7255 check_mft_get_info(class_id, &expect_mft_info);
7256 check_dmo_get_info(class_id, &expect_dmo_info);
7258 if (FAILED(hr = CoCreateInstance(class_id, NULL, CLSCTX_INPROC_SERVER,
7259 &IID_IMFTransform, (void **)&transform)))
7260 goto failed;
7262 check_interface(transform, &IID_IMFTransform, TRUE);
7263 check_interface(transform, &IID_IMediaObject, TRUE);
7264 todo_wine
7265 check_interface(transform, &IID_IPropertyStore, TRUE);
7266 check_interface(transform, &IID_IPropertyBag, FALSE);
7268 check_mft_optional_methods(transform, 1);
7269 check_mft_get_attributes(transform, NULL, FALSE);
7270 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
7271 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
7273 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type);
7274 ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
7276 i = -1;
7277 while (SUCCEEDED(hr = IMFTransform_GetInputAvailableType(transform, 0, ++i, &media_type)))
7279 winetest_push_context("in %lu", i);
7280 ok(hr == S_OK, "GetInputAvailableType returned %#lx\n", hr);
7281 check_media_type(media_type, expect_available_inputs[i], -1);
7282 ret = IMFMediaType_Release(media_type);
7283 ok(ret == 0, "Release returned %lu\n", ret);
7284 winetest_pop_context();
7286 todo_wine
7287 ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr);
7288 todo_wine
7289 ok(i == ARRAY_SIZE(expect_available_inputs), "%lu input media types\n", i);
7291 /* setting output media type first doesn't work */
7292 check_mft_set_output_type(transform, output_type_desc, MF_E_TRANSFORM_TYPE_NOT_SET);
7293 check_mft_get_output_current_type(transform, NULL);
7295 check_mft_set_input_type_required(transform, input_type_desc);
7296 check_mft_set_input_type(transform, input_type_desc);
7297 check_mft_get_input_current_type(transform, expect_input_type_desc);
7299 check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
7300 check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL);
7302 /* check new output media types */
7304 i = -1;
7305 while (SUCCEEDED(hr = IMFTransform_GetOutputAvailableType(transform, 0, ++i, &media_type)))
7307 winetest_push_context("out %lu", i);
7308 ok(hr == S_OK, "GetOutputAvailableType returned %#lx\n", hr);
7309 check_media_type(media_type, expect_available_outputs[i], -1);
7310 ret = IMFMediaType_Release(media_type);
7311 ok(ret == 0, "Release returned %lu\n", ret);
7312 winetest_pop_context();
7314 ok(hr == MF_E_NO_MORE_TYPES, "GetOutputAvailableType returned %#lx\n", hr);
7315 ok(i == ARRAY_SIZE(expect_available_outputs), "%lu output media types\n", i);
7317 check_mft_set_output_type_required(transform, output_type_desc);
7318 check_mft_set_output_type(transform, output_type_desc, S_OK);
7319 check_mft_get_output_current_type(transform, expect_output_type_desc);
7321 check_mft_get_input_stream_info(transform, S_OK, &input_info);
7322 check_mft_get_output_stream_info(transform, S_OK, &output_info);
7324 load_resource(L"mp3encdata.bin", &mp3enc_data, &mp3enc_data_len);
7325 ok(mp3enc_data_len == 6295, "got length %lu\n", mp3enc_data_len);
7327 input_sample = create_sample(mp3enc_data, mp3enc_data_len);
7328 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
7329 ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
7330 ret = IMFSample_Release(input_sample);
7331 ok(ret == 1, "Release returned %lu\n", ret);
7333 input_sample = create_sample(mp3enc_data, mp3enc_data_len);
7334 hr = IMFTransform_ProcessInput(transform, 0, input_sample, 0);
7335 ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr);
7336 ret = IMFSample_Release(input_sample);
7337 ok(ret == 0, "Release returned %lu\n", ret);
7339 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
7340 ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
7342 hr = MFCreateCollection(&output_samples);
7343 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
7345 /* first sample is broken */
7346 output_sample = create_sample(NULL, output_info.cbSize);
7347 hr = check_mft_process_output(transform, output_sample, &output_status);
7348 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
7349 ok(output_status == MFT_OUTPUT_DATA_BUFFER_INCOMPLETE, "got output[0].dwStatus %#lx\n", output_status);
7350 hr = IMFSample_GetTotalLength(output_sample, &length);
7351 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7352 ok(length == mp3dec_block_size /* Win8 */ || length == 0x9c0 /* Win10 */ || length == 0x900 /* Win7 */,
7353 "got length %lu\n", length);
7354 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
7355 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
7356 ref = IMFSample_Release(output_sample);
7357 ok(ref == 1, "Release returned %ld\n", ref);
7359 output_sample = create_sample(NULL, output_info.cbSize);
7360 for (i = 0; SUCCEEDED(hr = check_mft_process_output(transform, output_sample, &output_status)); i++)
7362 winetest_push_context("%lu", i);
7363 ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
7364 ok(!(output_status & ~MFT_OUTPUT_DATA_BUFFER_INCOMPLETE), "got output[0].dwStatus %#lx\n", output_status);
7365 hr = IMFCollection_AddElement(output_samples, (IUnknown *)output_sample);
7366 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
7367 ref = IMFSample_Release(output_sample);
7368 ok(ref == 1, "Release returned %ld\n", ref);
7369 output_sample = create_sample(NULL, output_info.cbSize);
7370 winetest_pop_context();
7372 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
7373 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
7374 ret = IMFSample_Release(output_sample);
7375 ok(ret == 0, "Release returned %lu\n", ret);
7376 ok(i == 20 || broken(i == 41) /* Win7 */, "got %lu output samples\n", i);
7378 if (broken(length != 0x9c0))
7379 win_skip("Skipping MP3 decoder output sample checks on Win7 / Win8\n");
7380 else
7382 ret = check_mf_sample_collection(output_samples, output_sample_desc, L"mp3decdata.bin");
7383 ok(ret == 0, "got %lu%% diff\n", ret);
7385 IMFCollection_Release(output_samples);
7387 output_sample = create_sample(NULL, mp3dec_block_size);
7388 hr = check_mft_process_output(transform, output_sample, &output_status);
7389 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
7390 ok(output_status == 0, "got output[0].dwStatus %#lx\n", output_status);
7391 hr = IMFSample_GetTotalLength(output_sample, &length);
7392 ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
7393 ok(length == 0, "got length %lu\n", length);
7394 ret = IMFSample_Release(output_sample);
7395 ok(ret == 0, "Release returned %lu\n", ret);
7397 ret = IMFTransform_Release(transform);
7398 ok(ret == 0, "Release returned %lu\n", ret);
7400 failed:
7401 winetest_pop_context();
7402 CoUninitialize();
7405 static HRESULT get_next_h264_output_sample(IMFTransform *transform, IMFSample **input_sample,
7406 IMFSample *output_sample, MFT_OUTPUT_DATA_BUFFER *output, const BYTE **data, ULONG *data_len)
7408 DWORD status;
7409 HRESULT hr;
7411 while (1)
7413 status = 0;
7414 memset(output, 0, sizeof(*output));
7415 output[0].pSample = output_sample;
7416 hr = IMFTransform_ProcessOutput(transform, 0, 1, output, &status);
7417 if (hr != S_OK)
7418 ok(output[0].pSample == output_sample, "got %p.\n", output[0].pSample);
7419 if (hr != MF_E_TRANSFORM_NEED_MORE_INPUT)
7420 return hr;
7422 ok(status == 0, "got output[0].dwStatus %#lx\n", status);
7423 hr = IMFTransform_ProcessInput(transform, 0, *input_sample, 0);
7424 ok(hr == S_OK, "got %#lx\n", hr);
7425 IMFSample_Release(*input_sample);
7426 *input_sample = next_h264_sample(data, data_len);
7430 static void test_h264_with_dxgi_manager(void)
7432 static const unsigned int set_width = 82, set_height = 84, aligned_width = 96, aligned_height = 96;
7433 const struct attribute_desc output_sample_attributes[] =
7435 ATTR_UINT32(MFSampleExtension_CleanPoint, 1),
7436 {0},
7438 const struct buffer_desc output_buffer_desc_nv12 =
7440 .length = aligned_width * aligned_height * 3 / 2,
7441 .compare = compare_nv12, .dump = dump_nv12, .rect = {.top=0, .left=0, .right = set_width, .bottom = set_height},
7443 const struct sample_desc output_sample_desc_nv12 =
7445 .attributes = output_sample_attributes,
7446 .sample_time = 333667, .sample_duration = 333667,
7447 .buffer_count = 1, .buffers = &output_buffer_desc_nv12,
7450 IMFDXGIDeviceManager *manager = NULL;
7451 IMFTrackedSample *tracked_sample;
7452 IMFSample *input_sample, *sample;
7453 MFT_OUTPUT_DATA_BUFFER output[1];
7454 IMFTransform *transform = NULL;
7455 ID3D11Multithread *multithread;
7456 IMFCollection *output_samples;
7457 MFT_OUTPUT_STREAM_INFO info;
7458 IMFDXGIBuffer *dxgi_buffer;
7459 unsigned int width, height;
7460 D3D11_TEXTURE2D_DESC desc;
7461 IMFMediaBuffer *buffer;
7462 IMFAttributes *attribs;
7463 ID3D11Texture2D *tex2d;
7464 IMF2DBuffer2 *buffer2d;
7465 ID3D11Device *d3d11;
7466 IMFMediaType *type;
7467 DWORD status, val;
7468 UINT64 frame_size;
7469 MFVideoArea area;
7470 const BYTE *data;
7471 ULONG data_len;
7472 UINT32 value;
7473 HRESULT hr;
7474 UINT token;
7475 GUID guid;
7476 DWORD ret;
7478 if (!pMFCreateDXGIDeviceManager)
7480 win_skip("MFCreateDXGIDeviceManager() is not available, skipping tests.\n");
7481 return;
7484 hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_VIDEO_SUPPORT, NULL, 0,
7485 D3D11_SDK_VERSION, &d3d11, NULL, NULL);
7486 if (FAILED(hr))
7488 skip("D3D11 device creation failed, skipping tests.\n");
7489 return;
7492 hr = MFStartup(MF_VERSION, 0);
7493 ok(hr == S_OK, "got %#lx\n", hr);
7495 hr = CoInitialize(NULL);
7496 ok(hr == S_OK, "got %#lx\n", hr);
7498 hr = ID3D11Device_QueryInterface(d3d11, &IID_ID3D11Multithread, (void **)&multithread);
7499 ok(hr == S_OK, "got %#lx\n", hr);
7500 ID3D11Multithread_SetMultithreadProtected(multithread, TRUE);
7501 ID3D11Multithread_Release(multithread);
7503 hr = pMFCreateDXGIDeviceManager(&token, &manager);
7504 ok(hr == S_OK, "got %#lx\n", hr);
7505 hr = IMFDXGIDeviceManager_ResetDevice(manager, (IUnknown *)d3d11, token);
7506 ok(hr == S_OK, "got %#lx\n", hr);
7507 ID3D11Device_Release(d3d11);
7509 if (FAILED(hr = CoCreateInstance(&CLSID_MSH264DecoderMFT, NULL, CLSCTX_INPROC_SERVER,
7510 &IID_IMFTransform, (void **)&transform)))
7511 goto failed;
7513 hr = IMFTransform_GetAttributes(transform, &attribs);
7514 ok(hr == S_OK, "got %#lx\n", hr);
7516 hr = IMFAttributes_GetUINT32(attribs, &MF_SA_D3D11_AWARE, &value);
7517 ok(hr == S_OK, "got %#lx\n", hr);
7518 ok(value == 1, "got %u.\n", value);
7519 IMFAttributes_Release(attribs);
7521 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)transform);
7522 ok(hr == E_NOINTERFACE, "got %#lx\n", hr);
7524 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_SET_D3D_MANAGER, (ULONG_PTR)manager);
7525 ok(hr == S_OK || broken(hr == E_NOINTERFACE), "got %#lx\n", hr);
7526 if (hr == E_NOINTERFACE)
7528 win_skip("No hardware video decoding support.\n");
7529 goto failed;
7532 hr = MFCreateMediaType(&type);
7533 ok(hr == S_OK, "got %#lx\n", hr);
7534 hr = IMFMediaType_SetGUID(type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
7535 ok(hr == S_OK, "got %#lx\n", hr);
7536 hr = IMFMediaType_SetGUID(type, &MF_MT_SUBTYPE, &MFVideoFormat_H264);
7537 ok(hr == S_OK, "got %#lx\n", hr);
7538 hr = IMFMediaType_SetUINT64(type, &MF_MT_FRAME_SIZE, 1088 | (1920ull << 32));
7539 ok(hr == S_OK, "got %#lx\n", hr);
7540 hr = IMFTransform_SetInputType(transform, 0, type, 0);
7541 ok(hr == S_OK, "got %#lx\n", hr);
7542 IMFMediaType_Release(type);
7544 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &type);
7545 ok(hr == S_OK, "got %#lx\n", hr);
7546 hr = IMFMediaType_SetGUID(type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video);
7547 ok(hr == S_OK, "got %#lx\n", hr);
7548 hr = IMFMediaType_SetGUID(type, &MF_MT_SUBTYPE, &MFVideoFormat_NV12);
7549 ok(hr == S_OK, "got %#lx\n", hr);
7550 hr = IMFTransform_SetOutputType(transform, 0, type, 0);
7551 ok(hr == S_OK, "got %#lx\n", hr);
7552 IMFMediaType_Release(type);
7554 status = 0;
7555 memset(output, 0, sizeof(output));
7556 hr = IMFTransform_ProcessOutput(transform, 0, 1, output, &status);
7557 ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "got %#lx\n", hr);
7559 hr = IMFTransform_GetAttributes(transform, &attribs);
7560 ok(hr == S_OK, "got %#lx\n", hr);
7561 hr = IMFAttributes_GetUINT32(attribs, &MF_SA_D3D11_AWARE, &value);
7562 ok(hr == S_OK, "got %#lx\n", hr);
7563 ok(value == 1, "got %u.\n", value);
7564 IMFAttributes_Release(attribs);
7566 load_resource(L"h264data.bin", &data, &data_len);
7568 input_sample = next_h264_sample(&data, &data_len);
7569 hr = get_next_h264_output_sample(transform, &input_sample, NULL, output, &data, &data_len);
7570 ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "got %#lx\n", hr);
7571 ok(!output[0].pSample, "got %p.\n", output[0].pSample);
7573 hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &type);
7574 ok(hr == S_OK, "got %#lx\n", hr);
7575 IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size);
7576 ok(hr == S_OK, "got %#lx\n", hr);
7577 width = frame_size >> 32;
7578 height = frame_size & 0xffffffff;
7579 ok(width == aligned_width, "got %u.\n", width);
7580 ok(height == aligned_height, "got %u.\n", height);
7581 memset(&area, 0xcc, sizeof(area));
7582 hr = IMFMediaType_GetBlob(type, &MF_MT_MINIMUM_DISPLAY_APERTURE, (BYTE *)&area, sizeof(area), NULL);
7583 ok(hr == S_OK, "got %#lx\n", hr);
7584 ok(!area.OffsetX.value && !area.OffsetX.fract, "got %d.%d.\n", area.OffsetX.value, area.OffsetX.fract);
7585 ok(!area.OffsetY.value && !area.OffsetY.fract, "got %d.%d.\n", area.OffsetY.value, area.OffsetY.fract);
7586 ok(area.Area.cx == set_width, "got %ld.\n", area.Area.cx);
7587 ok(area.Area.cy == set_height, "got %ld.\n", area.Area.cy);
7589 hr = IMFMediaType_GetGUID(type, &MF_MT_SUBTYPE, &guid);
7590 ok(hr == S_OK, "Failed to get subtype, hr %#lx.\n", hr);
7591 ok(IsEqualIID(&guid, &MEDIASUBTYPE_NV12), "got guid %s.\n", debugstr_guid(&guid));
7593 hr = IMFTransform_SetOutputType(transform, 0, type, 0);
7594 ok(hr == S_OK, "got %#lx\n", hr);
7595 IMFMediaType_Release(type);
7597 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &info);
7598 ok(hr == S_OK, "got %#lx\n", hr);
7599 ok(info.dwFlags == (MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
7600 | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE | MFT_OUTPUT_STREAM_PROVIDES_SAMPLES), "got %#lx.\n", info.dwFlags);
7602 hr = get_next_h264_output_sample(transform, &input_sample, NULL, output, &data, &data_len);
7603 ok(hr == S_OK, "got %#lx\n", hr);
7604 ok(output[0].dwStatus == 0, "got %#lx.\n", status);
7605 sample = output[0].pSample;
7607 hr = IMFSample_QueryInterface(sample, &IID_IMFTrackedSample, (void **)&tracked_sample);
7608 ok(hr == S_OK, "got %#lx\n", hr);
7609 IMFTrackedSample_Release(tracked_sample);
7611 hr = IMFSample_GetBufferCount(sample, &val);
7612 ok(hr == S_OK, "got %#lx\n", hr);
7613 ok(val == 1, "got %lu.\n", val);
7614 hr = IMFSample_GetBufferByIndex(sample, 0, &buffer);
7615 ok(hr == S_OK, "got %#lx\n", hr);
7616 hr = IMFMediaBuffer_QueryInterface(buffer, &IID_IMFDXGIBuffer, (void **)&dxgi_buffer);
7617 ok(hr == S_OK, "got %#lx\n", hr);
7618 hr = IMFMediaBuffer_QueryInterface(buffer, &IID_IMF2DBuffer2, (void **)&buffer2d);
7619 ok(hr == S_OK, "got %#lx\n", hr);
7621 hr = IMFDXGIBuffer_GetResource(dxgi_buffer, &IID_ID3D11Texture2D, (void **)&tex2d);
7622 ok(hr == S_OK, "got %#lx\n", hr);
7623 memset(&desc, 0xcc, sizeof(desc));
7624 ID3D11Texture2D_GetDesc(tex2d, &desc);
7625 ok(desc.Format == DXGI_FORMAT_NV12, "got %u.\n", desc.Format);
7626 ok(!desc.Usage, "got %u.\n", desc.Usage);
7627 todo_wine ok(desc.BindFlags == D3D11_BIND_DECODER, "got %#x.\n", desc.BindFlags);
7628 ok(!desc.CPUAccessFlags, "got %#x.\n", desc.CPUAccessFlags);
7629 ok(!desc.MiscFlags, "got %#x.\n", desc.MiscFlags);
7630 ok(desc.MipLevels == 1, "git %u.\n", desc.MipLevels);
7631 ok(desc.Width == aligned_width, "got %u.\n", desc.Width);
7632 ok(desc.Height == aligned_height, "got %u.\n", desc.Height);
7634 ID3D11Texture2D_Release(tex2d);
7635 IMFDXGIBuffer_Release(dxgi_buffer);
7636 IMF2DBuffer2_Release(buffer2d);
7637 IMFMediaBuffer_Release(buffer);
7638 IMFSample_Release(sample);
7640 status = 0;
7641 hr = get_next_h264_output_sample(transform, &input_sample, NULL, output, &data, &data_len);
7642 ok(hr == S_OK, "got %#lx\n", hr);
7643 ok(sample != output[0].pSample, "got %p.\n", output[0].pSample);
7644 sample = output[0].pSample;
7646 hr = MFCreateCollection(&output_samples);
7647 ok(hr == S_OK, "MFCreateCollection returned %#lx\n", hr);
7649 hr = IMFCollection_AddElement(output_samples, (IUnknown *)sample);
7650 ok(hr == S_OK, "AddElement returned %#lx\n", hr);
7651 IMFSample_Release(sample);
7653 ret = check_mf_sample_collection(output_samples, &output_sample_desc_nv12, L"nv12frame.bmp");
7654 ok(ret == 0, "got %lu%% diff\n", ret);
7655 IMFCollection_Release(output_samples);
7657 memset(&info, 0xcc, sizeof(info));
7658 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &info);
7659 ok(hr == S_OK, "got %#lx\n", hr);
7660 ok(info.dwFlags == (MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
7661 | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE | MFT_OUTPUT_STREAM_PROVIDES_SAMPLES), "got %#lx.\n", info.dwFlags);
7662 ok(info.cbSize == aligned_width * aligned_height * 2, "got %lu.\n", info.cbSize);
7663 ok(!info.cbAlignment, "got %lu.\n", info.cbAlignment);
7665 hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_SET_D3D_MANAGER, 0);
7666 ok(hr == S_OK, "got %#lx\n", hr);
7668 memset(&info, 0xcc, sizeof(info));
7669 hr = IMFTransform_GetOutputStreamInfo(transform, 0, &info);
7670 ok(hr == S_OK, "got %#lx\n", hr);
7671 ok(info.dwFlags == (MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
7672 | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE), "got %#lx.\n", info.dwFlags);
7673 if (0)
7675 /* hangs on Windows. */
7676 get_next_h264_output_sample(transform, &input_sample, NULL, output, &data, &data_len);
7679 IMFSample_Release(input_sample);
7681 failed:
7682 if (manager)
7683 IMFDXGIDeviceManager_Release(manager);
7684 if (transform)
7685 IMFTransform_Release(transform);
7686 CoUninitialize();
7689 static void test_iv50_encoder(void)
7691 static const BITMAPINFOHEADER expect_iv50 =
7693 .biSize = sizeof(BITMAPINFOHEADER),
7694 .biWidth = 0x60, .biHeight = 0x60,
7695 .biPlanes = 1, .biBitCount = 0x18,
7696 .biCompression = mmioFOURCC('I','V','5','0'),
7697 .biSizeImage = 0x5100,
7699 const struct buffer_desc iv50_buffer_desc =
7701 .length = 0x2e8,
7703 const struct sample_desc iv50_sample_desc =
7705 .buffer_count = 1, .buffers = &iv50_buffer_desc,
7707 const BYTE *res_data;
7708 BYTE rgb_data[0x6c00], iv50_data[0x5100];
7709 BITMAPINFO rgb_info, iv50_info;
7710 IMFCollection *collection;
7711 DWORD flags, res_len, ret;
7712 IMFSample *sample;
7713 LRESULT res;
7714 HRESULT hr;
7715 HIC hic;
7717 load_resource(L"rgb555frame.bmp", (const BYTE **)&res_data, &res_len);
7718 res_data += 2 + 3 * sizeof(DWORD);
7719 res_len -= 2 + 3 * sizeof(DWORD);
7720 rgb_info.bmiHeader = *(BITMAPINFOHEADER *)res_data;
7721 memcpy(rgb_data, res_data + sizeof(BITMAPINFOHEADER), res_len - sizeof(BITMAPINFOHEADER));
7723 hic = ICOpen(ICTYPE_VIDEO, expect_iv50.biCompression, ICMODE_COMPRESS);
7724 if (!hic)
7726 todo_wine
7727 win_skip("ICOpen failed to created IV50 compressor.\n");
7728 return;
7731 res = ICCompressQuery(hic, &rgb_info, NULL);
7732 todo_wine
7733 ok(!res, "got res %#Ix\n", res);
7734 if (res)
7735 goto done;
7737 res = ICCompressGetSize(hic, &rgb_info, NULL);
7738 ok(res == expect_iv50.biSizeImage, "got res %#Ix\n", res);
7740 res = ICCompressGetFormatSize(hic, &rgb_info);
7741 ok(res == sizeof(BITMAPINFOHEADER), "got res %#Ix\n", res);
7742 res = ICCompressGetFormat(hic, &rgb_info, &iv50_info);
7743 ok(!res, "got res %#Ix\n", res);
7744 check_member(iv50_info.bmiHeader, expect_iv50, "%#lx", biSize);
7745 check_member(iv50_info.bmiHeader, expect_iv50, "%#lx", biWidth);
7746 check_member(iv50_info.bmiHeader, expect_iv50, "%#lx", biHeight);
7747 check_member(iv50_info.bmiHeader, expect_iv50, "%#x", biPlanes);
7748 check_member(iv50_info.bmiHeader, expect_iv50, "%#x", biBitCount);
7749 check_member(iv50_info.bmiHeader, expect_iv50, "%#lx", biCompression);
7750 check_member(iv50_info.bmiHeader, expect_iv50, "%#lx", biSizeImage);
7751 check_member(iv50_info.bmiHeader, expect_iv50, "%#lx", biXPelsPerMeter);
7752 check_member(iv50_info.bmiHeader, expect_iv50, "%#lx", biYPelsPerMeter);
7753 check_member(iv50_info.bmiHeader, expect_iv50, "%#lx", biClrUsed);
7754 check_member(iv50_info.bmiHeader, expect_iv50, "%#lx", biClrImportant);
7755 res = ICCompressQuery(hic, &rgb_info, &iv50_info);
7756 ok(!res, "got res %#Ix\n", res);
7758 res = ICCompressBegin(hic, &rgb_info, &iv50_info);
7759 ok(!res, "got res %#Ix\n", res);
7760 memset(iv50_data, 0xcd, sizeof(iv50_data));
7761 res = ICCompress(hic, ICCOMPRESS_KEYFRAME, &iv50_info.bmiHeader, iv50_data, &rgb_info.bmiHeader, rgb_data,
7762 NULL, &flags, 1, 0, 0, NULL, NULL);
7763 ok(!res, "got res %#Ix\n", res);
7764 ok(flags == 0x10, "got flags %#lx\n", flags);
7765 ok(iv50_info.bmiHeader.biSizeImage == 0x2e8, "got res %#Ix\n", res);
7766 res = ICCompressEnd(hic);
7767 ok(!res, "got res %#Ix\n", res);
7769 hr = MFCreateCollection(&collection);
7770 ok(hr == S_OK, "got hr %#lx\n", hr);
7771 sample = create_sample(iv50_data, iv50_info.bmiHeader.biSizeImage);
7772 ok(!!sample, "got sample %p\n", sample);
7773 hr = IMFSample_SetSampleTime(sample, 0);
7774 ok(hr == S_OK, "got hr %#lx\n", hr);
7775 hr = IMFSample_SetSampleDuration(sample, 0);
7776 ok(hr == S_OK, "got hr %#lx\n", hr);
7777 hr = IMFCollection_AddElement(collection, (IUnknown *)sample);
7778 ok(hr == S_OK, "got hr %#lx\n", hr);
7779 ret = check_mf_sample_collection(collection, &iv50_sample_desc, L"iv50frame.bin");
7780 ok(ret == 0, "got %lu%% diff\n", ret);
7781 IMFCollection_Release(collection);
7783 done:
7784 res = ICClose(hic);
7785 ok(!res, "got res %#Ix\n", res);
7788 static void test_iv50_decoder(void)
7790 static const BITMAPINFOHEADER expect_iv50 =
7792 .biSize = sizeof(BITMAPINFOHEADER),
7793 .biWidth = 0x60, .biHeight = 0x60,
7794 .biPlanes = 1, .biBitCount = 24,
7795 .biCompression = mmioFOURCC('I','V','5','0'),
7796 .biSizeImage = 0x2e8,
7798 static const BITMAPINFOHEADER expect_rgb =
7800 .biSize = sizeof(BITMAPINFOHEADER),
7801 .biWidth = 0x60, .biHeight = 0x60,
7802 .biPlanes = 1, .biBitCount = 24,
7803 .biCompression = BI_RGB,
7804 .biSizeImage = 96 * 96 * 3,
7806 const struct buffer_desc rgb_buffer_desc =
7808 .length = 96 * 96 * 3, .compare = compare_rgb24, .dump = dump_rgb24,
7809 .rect = {.right = 82, .bottom = 84},
7811 const struct sample_desc rgb_sample_desc =
7813 .buffer_count = 1, .buffers = &rgb_buffer_desc,
7815 const BYTE *res_data;
7816 BYTE rgb_data[0x6c00], iv50_data[0x5100];
7817 BITMAPINFO rgb_info, iv50_info;
7818 IMFCollection *collection;
7819 DWORD res_len, ret;
7820 IMFSample *sample;
7821 LRESULT res;
7822 HRESULT hr;
7823 HIC hic;
7825 load_resource(L"iv50frame.bin", (const BYTE **)&res_data, &res_len);
7826 memcpy(iv50_data, res_data, res_len);
7828 iv50_info.bmiHeader = expect_iv50;
7829 hic = ICOpen(ICTYPE_VIDEO, expect_iv50.biCompression, ICMODE_DECOMPRESS);
7830 if (!hic)
7832 todo_wine
7833 win_skip("ICOpen failed to created IV50 decompressor.\n");
7834 return;
7837 res = ICDecompressGetFormat(hic, &iv50_info, &rgb_info);
7838 ok(!res, "got res %#Ix\n", res);
7839 check_member(rgb_info.bmiHeader, expect_rgb, "%#lx", biSize);
7840 check_member(rgb_info.bmiHeader, expect_rgb, "%#lx", biWidth);
7841 check_member(rgb_info.bmiHeader, expect_rgb, "%#lx", biHeight);
7842 check_member(rgb_info.bmiHeader, expect_rgb, "%#x", biPlanes);
7843 todo_wine
7844 check_member(rgb_info.bmiHeader, expect_rgb, "%#x", biBitCount);
7845 check_member(rgb_info.bmiHeader, expect_rgb, "%#lx", biCompression);
7846 todo_wine
7847 check_member(rgb_info.bmiHeader, expect_rgb, "%#lx", biSizeImage);
7848 check_member(rgb_info.bmiHeader, expect_rgb, "%#lx", biXPelsPerMeter);
7849 check_member(rgb_info.bmiHeader, expect_rgb, "%#lx", biYPelsPerMeter);
7850 check_member(rgb_info.bmiHeader, expect_rgb, "%#lx", biClrUsed);
7851 check_member(rgb_info.bmiHeader, expect_rgb, "%#lx", biClrImportant);
7852 rgb_info.bmiHeader = expect_rgb;
7854 res = ICDecompressBegin(hic, &iv50_info, &rgb_info);
7855 ok(!res, "got res %#Ix\n", res);
7856 res = ICDecompress(hic, 0, &iv50_info.bmiHeader, iv50_data, &rgb_info.bmiHeader, rgb_data);
7857 ok(!res, "got res %#Ix\n", res);
7858 res = ICDecompressEnd(hic);
7859 todo_wine
7860 ok(!res, "got res %#Ix\n", res);
7862 res = ICClose(hic);
7863 ok(!res, "got res %#Ix\n", res);
7866 hr = MFCreateCollection(&collection);
7867 ok(hr == S_OK, "got hr %#lx\n", hr);
7868 sample = create_sample(rgb_data, rgb_info.bmiHeader.biSizeImage);
7869 ok(!!sample, "got sample %p\n", sample);
7870 hr = IMFSample_SetSampleTime(sample, 0);
7871 ok(hr == S_OK, "got hr %#lx\n", hr);
7872 hr = IMFSample_SetSampleDuration(sample, 0);
7873 ok(hr == S_OK, "got hr %#lx\n", hr);
7874 hr = IMFCollection_AddElement(collection, (IUnknown *)sample);
7875 ok(hr == S_OK, "got hr %#lx\n", hr);
7876 ret = check_mf_sample_collection(collection, &rgb_sample_desc, L"rgb24frame.bmp");
7877 ok(ret <= 4, "got %lu%% diff\n", ret);
7878 IMFCollection_Release(collection);
7881 START_TEST(transform)
7883 init_functions();
7885 test_sample_copier();
7886 test_sample_copier_output_processing();
7887 test_aac_encoder();
7888 test_aac_decoder();
7889 test_wma_encoder();
7890 test_wma_decoder();
7891 test_h264_decoder();
7892 test_wmv_encoder();
7893 test_wmv_decoder();
7894 test_wmv_decoder_media_object();
7895 test_audio_convert();
7896 test_color_convert();
7897 test_video_processor();
7898 test_mp3_decoder();
7899 test_iv50_encoder();
7900 test_iv50_decoder();
7902 test_h264_with_dxgi_manager();
7903 test_h264_decoder_concat_streams();