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