2 * Copyright 2019 Jactry Zeng for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "mfmediaengine.h"
34 #include "mmdeviceapi.h"
35 #include "audiosessiontypes.h"
37 #include "wine/test.h"
39 static HRESULT (WINAPI
*pMFCreateDXGIDeviceManager
)(UINT
*token
, IMFDXGIDeviceManager
**manager
);
40 static HRESULT (WINAPI
*pD3D11CreateDevice
)(IDXGIAdapter
*adapter
, D3D_DRIVER_TYPE driver_type
, HMODULE swrast
, UINT flags
,
41 const D3D_FEATURE_LEVEL
*feature_levels
, UINT levels
, UINT sdk_version
, ID3D11Device
**device_out
,
42 D3D_FEATURE_LEVEL
*obtained_feature_level
, ID3D11DeviceContext
**immediate_context
);
44 static IMFMediaEngineClassFactory
*factory
;
46 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
47 static void _expect_ref(IUnknown
*obj
, ULONG ref
, int line
)
51 rc
= IUnknown_Release(obj
);
52 ok_(__FILE__
,line
)(rc
== ref
, "Unexpected refcount %ld, expected %ld.\n", rc
, ref
);
55 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
56 static void check_interface_(unsigned int line
, void *iface_ptr
, REFIID iid
, BOOL supported
)
58 IUnknown
*iface
= iface_ptr
;
59 HRESULT hr
, expected_hr
;
62 expected_hr
= supported
? S_OK
: E_NOINTERFACE
;
64 hr
= IUnknown_QueryInterface(iface
, iid
, (void **)&unk
);
65 ok_(__FILE__
, line
)(hr
== expected_hr
, "Got hr %#lx, expected %#lx.\n", hr
, expected_hr
);
67 IUnknown_Release(unk
);
70 static BOOL
compare_double(double a
, double b
, double allowed_error
)
72 return fabs(a
- b
) <= allowed_error
;
75 static DWORD
compare_rgb32(const BYTE
*data
, DWORD
*length
, const RECT
*rect
, const BYTE
*expect
)
77 DWORD x
, y
, size
, diff
= 0, width
= (rect
->right
+ 0xf) & ~0xf, height
= (rect
->bottom
+ 0xf) & ~0xf;
79 /* skip BMP header from the dump */
80 size
= *(DWORD
*)(expect
+ 2 + 2 * sizeof(DWORD
));
81 *length
= *length
+ size
;
82 expect
= expect
+ size
;
84 for (y
= 0; y
< height
; y
++, data
+= width
* 4, expect
+= width
* 4)
86 if (y
< rect
->top
|| y
>= rect
->bottom
) continue;
87 for (x
= 0; x
< width
; x
++)
89 if (x
< rect
->left
|| x
>= rect
->right
) continue;
90 diff
+= abs((int)expect
[4 * x
+ 0] - (int)data
[4 * x
+ 0]);
91 diff
+= abs((int)expect
[4 * x
+ 1] - (int)data
[4 * x
+ 1]);
92 diff
+= abs((int)expect
[4 * x
+ 2] - (int)data
[4 * x
+ 2]);
96 size
= (rect
->right
- rect
->left
) * (rect
->bottom
- rect
->top
) * 3;
97 return diff
* 100 / 256 / size
;
100 static void dump_rgb32(const BYTE
*data
, DWORD length
, const RECT
*rect
, HANDLE output
)
102 DWORD width
= (rect
->right
+ 0xf) & ~0xf, height
= (rect
->bottom
+ 0xf) & ~0xf;
103 static const char magic
[2] = "BM";
109 BITMAPINFOHEADER biHeader
;
112 .length
= length
+ sizeof(header
) + 2, .offset
= sizeof(header
) + 2,
115 .biSize
= sizeof(BITMAPINFOHEADER
), .biWidth
= width
, .biHeight
= height
, .biPlanes
= 1,
116 .biBitCount
= 32, .biCompression
= BI_RGB
, .biSizeImage
= width
* height
* 4,
122 ret
= WriteFile(output
, magic
, sizeof(magic
), &written
, NULL
);
123 ok(ret
, "WriteFile failed, error %lu\n", GetLastError());
124 ok(written
== sizeof(magic
), "written %lu bytes\n", written
);
125 ret
= WriteFile(output
, &header
, sizeof(header
), &written
, NULL
);
126 ok(ret
, "WriteFile failed, error %lu\n", GetLastError());
127 ok(written
== sizeof(header
), "written %lu bytes\n", written
);
128 ret
= WriteFile(output
, data
, length
, &written
, NULL
);
129 ok(ret
, "WriteFile failed, error %lu\n", GetLastError());
130 ok(written
== length
, "written %lu bytes\n", written
);
133 #define check_rgb32_data(a, b, c, d) check_rgb32_data_(__LINE__, a, b, c, d)
134 static void check_rgb32_data_(int line
, const WCHAR
*filename
, const BYTE
*data
, DWORD length
, const RECT
*rect
)
136 WCHAR output_path
[MAX_PATH
];
137 const BYTE
*expect_data
;
142 GetTempPathW(ARRAY_SIZE(output_path
), output_path
);
143 lstrcatW(output_path
, filename
);
144 output
= CreateFileW(output_path
, GENERIC_READ
|GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, 0);
145 ok(output
!= INVALID_HANDLE_VALUE
, "CreateFileW failed, error %lu\n", GetLastError());
146 dump_rgb32(data
, length
, rect
, output
);
147 trace("created %s\n", debugstr_w(output_path
));
150 resource
= FindResourceW(NULL
, filename
, (const WCHAR
*)RT_RCDATA
);
151 ok(resource
!= 0, "FindResourceW failed, error %lu\n", GetLastError());
152 expect_data
= LockResource(LoadResource(GetModuleHandleW(NULL
), resource
));
154 diff
= compare_rgb32(data
, &length
, rect
, expect_data
);
155 ok_(__FILE__
, line
)(diff
== 0, "Unexpected %lu%% diff\n", diff
);
158 static void init_functions(void)
162 #define X(f) p##f = (void*)GetProcAddress(mod, #f)
163 if ((mod
= GetModuleHandleA("mfplat.dll")))
165 X(MFCreateDXGIDeviceManager
);
168 if ((mod
= LoadLibraryA("d3d11.dll")))
170 X(D3D11CreateDevice
);
175 struct media_engine_notify
177 IMFMediaEngineNotify IMFMediaEngineNotify_iface
;
181 static inline struct media_engine_notify
*impl_from_IMFMediaEngineNotify(IMFMediaEngineNotify
*iface
)
183 return CONTAINING_RECORD(iface
, struct media_engine_notify
, IMFMediaEngineNotify_iface
);
186 static HRESULT WINAPI
media_engine_notify_QueryInterface(IMFMediaEngineNotify
*iface
, REFIID riid
, void **obj
)
188 if (IsEqualIID(riid
, &IID_IMFMediaEngineNotify
) ||
189 IsEqualIID(riid
, &IID_IUnknown
))
192 IMFMediaEngineNotify_AddRef(iface
);
197 return E_NOINTERFACE
;
200 static ULONG WINAPI
media_engine_notify_AddRef(IMFMediaEngineNotify
*iface
)
202 struct media_engine_notify
*notify
= impl_from_IMFMediaEngineNotify(iface
);
203 return InterlockedIncrement(¬ify
->refcount
);
206 static ULONG WINAPI
media_engine_notify_Release(IMFMediaEngineNotify
*iface
)
208 struct media_engine_notify
*notify
= impl_from_IMFMediaEngineNotify(iface
);
209 ULONG refcount
= InterlockedDecrement(¬ify
->refcount
);
217 static HRESULT WINAPI
media_engine_notify_EventNotify(IMFMediaEngineNotify
*iface
, DWORD event
, DWORD_PTR param1
, DWORD param2
)
222 static IMFMediaEngineNotifyVtbl media_engine_notify_vtbl
=
224 media_engine_notify_QueryInterface
,
225 media_engine_notify_AddRef
,
226 media_engine_notify_Release
,
227 media_engine_notify_EventNotify
,
230 static struct media_engine_notify
*create_callback(void)
232 struct media_engine_notify
*object
;
234 object
= calloc(1, sizeof(*object
));
236 object
->IMFMediaEngineNotify_iface
.lpVtbl
= &media_engine_notify_vtbl
;
237 object
->refcount
= 1;
242 static ID3D11Device
*create_d3d11_device(void)
244 static const D3D_FEATURE_LEVEL default_feature_level
[] =
246 D3D_FEATURE_LEVEL_11_0
,
247 D3D_FEATURE_LEVEL_10_1
,
248 D3D_FEATURE_LEVEL_10_0
,
250 const D3D_FEATURE_LEVEL
*feature_level
;
251 unsigned int feature_level_count
;
252 ID3D11Device
*device
;
254 feature_level
= default_feature_level
;
255 feature_level_count
= ARRAY_SIZE(default_feature_level
);
257 if (SUCCEEDED(pD3D11CreateDevice(NULL
, D3D_DRIVER_TYPE_HARDWARE
, NULL
, 0,
258 feature_level
, feature_level_count
, D3D11_SDK_VERSION
, &device
, NULL
, NULL
)))
260 if (SUCCEEDED(pD3D11CreateDevice(NULL
, D3D_DRIVER_TYPE_WARP
, NULL
, 0,
261 feature_level
, feature_level_count
, D3D11_SDK_VERSION
, &device
, NULL
, NULL
)))
263 if (SUCCEEDED(pD3D11CreateDevice(NULL
, D3D_DRIVER_TYPE_REFERENCE
, NULL
, 0,
264 feature_level
, feature_level_count
, D3D11_SDK_VERSION
, &device
, NULL
, NULL
)))
270 static IMFMediaEngine
*create_media_engine(IMFMediaEngineNotify
*callback
, IMFDXGIDeviceManager
*manager
, UINT32 output_format
)
272 IMFMediaEngine
*media_engine
;
273 IMFAttributes
*attributes
;
276 hr
= MFCreateAttributes(&attributes
, 3);
277 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
281 hr
= IMFAttributes_SetUnknown(attributes
, &MF_MEDIA_ENGINE_DXGI_MANAGER
, (IUnknown
*)manager
);
282 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
285 hr
= IMFAttributes_SetUnknown(attributes
, &MF_MEDIA_ENGINE_CALLBACK
, (IUnknown
*)callback
);
286 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
287 hr
= IMFAttributes_SetUINT32(attributes
, &MF_MEDIA_ENGINE_VIDEO_OUTPUT_FORMAT
, output_format
);
288 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
290 hr
= IMFMediaEngineClassFactory_CreateInstance(factory
, 0, attributes
, &media_engine
);
291 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
293 IMFAttributes_Release(attributes
);
298 static IMFMediaEngineEx
*create_media_engine_ex(IMFMediaEngineNotify
*callback
, IMFDXGIDeviceManager
*manager
, UINT32 output_format
)
300 IMFMediaEngine
*engine
= create_media_engine(callback
, manager
, output_format
);
301 IMFMediaEngineEx
*engine_ex
= NULL
;
305 IMFMediaEngine_QueryInterface(engine
, &IID_IMFMediaEngineEx
, (void **)&engine_ex
);
306 IMFMediaEngine_Release(engine
);
312 static void test_factory(void)
314 IMFMediaEngineClassFactory
*factory
, *factory2
;
315 struct media_engine_notify
*notify
;
316 IMFDXGIDeviceManager
*manager
;
317 IMFMediaEngine
*media_engine
;
318 IMFAttributes
*attributes
;
322 hr
= CoCreateInstance(&CLSID_MFMediaEngineClassFactory
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IMFMediaEngineClassFactory
,
324 ok(hr
== S_OK
|| broken(hr
== REGDB_E_CLASSNOTREG
) /* pre-win8 */, "Failed to create class factory, hr %#lx.\n", hr
);
327 win_skip("Media Engine is not supported.\n");
331 notify
= create_callback();
333 /* Aggregation is not supported. */
334 hr
= CoCreateInstance(&CLSID_MFMediaEngineClassFactory
, (IUnknown
*)factory
, CLSCTX_INPROC_SERVER
,
335 &IID_IMFMediaEngineClassFactory
, (void **)&factory2
);
336 ok(hr
== CLASS_E_NOAGGREGATION
, "Unexpected hr %#lx.\n", hr
);
338 hr
= pMFCreateDXGIDeviceManager(&token
, &manager
);
339 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
340 hr
= MFCreateAttributes(&attributes
, 3);
341 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
343 hr
= IMFMediaEngineClassFactory_CreateInstance(factory
, MF_MEDIA_ENGINE_WAITFORSTABLE_STATE
, attributes
, &media_engine
);
344 ok(hr
== MF_E_ATTRIBUTENOTFOUND
, "Unexpected hr %#lx.\n", hr
);
346 hr
= IMFAttributes_SetUnknown(attributes
, &MF_MEDIA_ENGINE_OPM_HWND
, NULL
);
347 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
348 hr
= IMFMediaEngineClassFactory_CreateInstance(factory
, MF_MEDIA_ENGINE_WAITFORSTABLE_STATE
, attributes
, &media_engine
);
349 ok(hr
== MF_E_ATTRIBUTENOTFOUND
, "Unexpected hr %#lx.\n", hr
);
351 IMFAttributes_DeleteAllItems(attributes
);
352 hr
= IMFAttributes_SetUnknown(attributes
, &MF_MEDIA_ENGINE_CALLBACK
, (IUnknown
*)¬ify
->IMFMediaEngineNotify_iface
);
353 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
354 hr
= IMFAttributes_SetUINT32(attributes
, &MF_MEDIA_ENGINE_VIDEO_OUTPUT_FORMAT
, DXGI_FORMAT_UNKNOWN
);
355 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
356 EXPECT_REF(factory
, 1);
357 hr
= IMFMediaEngineClassFactory_CreateInstance(factory
, MF_MEDIA_ENGINE_WAITFORSTABLE_STATE
, attributes
, &media_engine
);
358 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
359 EXPECT_REF(factory
, 1);
361 IMFMediaEngine_Release(media_engine
);
362 IMFAttributes_Release(attributes
);
363 IMFDXGIDeviceManager_Release(manager
);
364 IMFMediaEngineClassFactory_Release(factory
);
365 IMFMediaEngineNotify_Release(¬ify
->IMFMediaEngineNotify_iface
);
368 static void test_CreateInstance(void)
370 struct media_engine_notify
*notify
;
371 IMFMediaEngineEx
*media_engine_ex
;
372 IMFDXGIDeviceManager
*manager
;
373 IMFMediaEngine
*media_engine
;
374 IMFAttributes
*attributes
;
380 notify
= create_callback();
382 hr
= pMFCreateDXGIDeviceManager(&token
, &manager
);
383 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
385 hr
= MFCreateAttributes(&attributes
, 3);
386 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
388 hr
= IMFMediaEngineClassFactory_CreateInstance(factory
, MF_MEDIA_ENGINE_WAITFORSTABLE_STATE
,
389 attributes
, &media_engine
);
390 ok(hr
== MF_E_ATTRIBUTENOTFOUND
, "Unexpected hr %#lx.\n", hr
);
392 hr
= IMFAttributes_SetUnknown(attributes
, &MF_MEDIA_ENGINE_OPM_HWND
, NULL
);
393 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
395 hr
= IMFMediaEngineClassFactory_CreateInstance(factory
, MF_MEDIA_ENGINE_WAITFORSTABLE_STATE
,
396 attributes
, &media_engine
);
397 ok(hr
== MF_E_ATTRIBUTENOTFOUND
, "Unexpected hr %#lx.\n", hr
);
399 IMFAttributes_DeleteAllItems(attributes
);
401 hr
= IMFAttributes_SetUnknown(attributes
, &MF_MEDIA_ENGINE_CALLBACK
, (IUnknown
*)¬ify
->IMFMediaEngineNotify_iface
);
402 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
403 hr
= IMFAttributes_SetUINT32(attributes
, &MF_MEDIA_ENGINE_VIDEO_OUTPUT_FORMAT
, DXGI_FORMAT_UNKNOWN
);
404 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
406 hr
= IMFMediaEngineClassFactory_CreateInstance(factory
, MF_MEDIA_ENGINE_REAL_TIME_MODE
407 | MF_MEDIA_ENGINE_WAITFORSTABLE_STATE
, attributes
, &media_engine
);
408 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
410 check_interface(media_engine
, &IID_IMFMediaEngine
, TRUE
);
412 hr
= IMFMediaEngine_QueryInterface(media_engine
, &IID_IMFGetService
, (void **)&unk
);
413 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* supported since win10 */, "Unexpected hr %#lx.\n", hr
);
415 IUnknown_Release(unk
);
417 if (SUCCEEDED(IMFMediaEngine_QueryInterface(media_engine
, &IID_IMFMediaEngineEx
, (void **)&media_engine_ex
)))
419 hr
= IMFMediaEngineEx_GetRealTimeMode(media_engine_ex
, &ret
);
420 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
421 ok(ret
, "Unexpected value.\n");
423 hr
= IMFMediaEngineEx_SetRealTimeMode(media_engine_ex
, FALSE
);
424 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
426 hr
= IMFMediaEngineEx_GetRealTimeMode(media_engine_ex
, &ret
);
427 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
428 ok(!ret
, "Unexpected value.\n");
430 hr
= IMFMediaEngineEx_SetRealTimeMode(media_engine_ex
, TRUE
);
431 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
433 hr
= IMFMediaEngineEx_GetRealTimeMode(media_engine_ex
, &ret
);
434 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
435 ok(ret
, "Unexpected value.\n");
437 IMFMediaEngineEx_Release(media_engine_ex
);
440 IMFMediaEngine_Release(media_engine
);
441 IMFAttributes_Release(attributes
);
442 IMFDXGIDeviceManager_Release(manager
);
443 IMFMediaEngineNotify_Release(¬ify
->IMFMediaEngineNotify_iface
);
446 static void test_Shutdown(void)
448 struct media_engine_notify
*notify
;
449 IMFMediaEngineEx
*media_engine_ex
;
450 IMFMediaTimeRange
*time_range
;
451 IMFMediaEngine
*media_engine
;
461 notify
= create_callback();
463 media_engine
= create_media_engine(¬ify
->IMFMediaEngineNotify_iface
, NULL
, DXGI_FORMAT_UNKNOWN
);
465 hr
= IMFMediaEngine_Shutdown(media_engine
);
466 ok(hr
== S_OK
, "Failed to shut down, hr %#lx.\n", hr
);
468 hr
= IMFMediaEngine_Shutdown(media_engine
);
469 ok(hr
== MF_E_SHUTDOWN
|| broken(hr
== S_OK
) /* before win10 */, "Unexpected hr %#lx.\n", hr
);
471 hr
= IMFMediaEngine_SetSource(media_engine
, NULL
);
472 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
474 hr
= IMFMediaEngine_GetCurrentSource(media_engine
, &str
);
475 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
477 state
= IMFMediaEngine_GetNetworkState(media_engine
);
478 ok(!state
, "Unexpected state %d.\n", state
);
480 /* Preload mode is still accessible. */
481 state
= IMFMediaEngine_GetPreload(media_engine
);
482 ok(!state
, "Unexpected state %d.\n", state
);
484 hr
= IMFMediaEngine_SetPreload(media_engine
, MF_MEDIA_ENGINE_PRELOAD_AUTOMATIC
);
485 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
487 state
= IMFMediaEngine_GetPreload(media_engine
);
488 ok(state
== MF_MEDIA_ENGINE_PRELOAD_AUTOMATIC
, "Unexpected state %d.\n", state
);
490 hr
= IMFMediaEngine_SetPreload(media_engine
, 100);
491 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
493 state
= IMFMediaEngine_GetPreload(media_engine
);
494 ok(state
== 100, "Unexpected state %d.\n", state
);
496 hr
= IMFMediaEngine_GetBuffered(media_engine
, &time_range
);
497 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
499 hr
= IMFMediaEngine_Load(media_engine
);
500 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
502 str
= SysAllocString(L
"video/mp4");
503 hr
= IMFMediaEngine_CanPlayType(media_engine
, str
, &state
);
504 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
507 state
= IMFMediaEngine_GetReadyState(media_engine
);
508 ok(!state
, "Unexpected state %d.\n", state
);
510 state
= IMFMediaEngine_IsSeeking(media_engine
);
511 ok(!state
, "Unexpected state %d.\n", state
);
513 val
= IMFMediaEngine_GetCurrentTime(media_engine
);
514 ok(val
== 0.0, "Unexpected time %f.\n", val
);
516 hr
= IMFMediaEngine_SetCurrentTime(media_engine
, 1.0);
517 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
519 val
= IMFMediaEngine_GetStartTime(media_engine
);
520 ok(val
== 0.0, "Unexpected time %f.\n", val
);
522 state
= IMFMediaEngine_IsPaused(media_engine
);
523 ok(!!state
, "Unexpected state %d.\n", state
);
525 val
= IMFMediaEngine_GetDefaultPlaybackRate(media_engine
);
526 ok(val
== 1.0, "Unexpected rate %f.\n", val
);
528 hr
= IMFMediaEngine_SetDefaultPlaybackRate(media_engine
, 2.0);
529 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
531 val
= IMFMediaEngine_GetPlaybackRate(media_engine
);
532 ok(val
== 1.0, "Unexpected rate %f.\n", val
);
534 hr
= IMFMediaEngine_GetPlayed(media_engine
, &time_range
);
535 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
537 hr
= IMFMediaEngine_GetSeekable(media_engine
, &time_range
);
538 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
540 state
= IMFMediaEngine_IsEnded(media_engine
);
541 ok(!state
, "Unexpected state %d.\n", state
);
543 /* Autoplay mode is still accessible. */
544 state
= IMFMediaEngine_GetAutoPlay(media_engine
);
545 ok(!state
, "Unexpected state.\n");
547 hr
= IMFMediaEngine_SetAutoPlay(media_engine
, TRUE
);
548 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
550 state
= IMFMediaEngine_GetAutoPlay(media_engine
);
551 ok(!!state
, "Unexpected state.\n");
553 /* Loop mode is still accessible. */
554 state
= IMFMediaEngine_GetLoop(media_engine
);
555 ok(!state
, "Unexpected state.\n");
557 hr
= IMFMediaEngine_SetLoop(media_engine
, TRUE
);
558 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
560 state
= IMFMediaEngine_GetLoop(media_engine
);
561 ok(!!state
, "Unexpected state.\n");
563 hr
= IMFMediaEngine_Play(media_engine
);
564 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
566 hr
= IMFMediaEngine_Pause(media_engine
);
567 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
569 state
= IMFMediaEngine_GetMuted(media_engine
);
570 ok(!state
, "Unexpected state.\n");
572 hr
= IMFMediaEngine_SetMuted(media_engine
, TRUE
);
573 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
575 val
= IMFMediaEngine_GetVolume(media_engine
);
576 ok(val
== 1.0, "Unexpected value %f.\n", val
);
578 hr
= IMFMediaEngine_SetVolume(media_engine
, 2.0);
579 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
581 state
= IMFMediaEngine_HasVideo(media_engine
);
582 ok(!state
, "Unexpected state.\n");
584 state
= IMFMediaEngine_HasAudio(media_engine
);
585 ok(!state
, "Unexpected state.\n");
587 hr
= IMFMediaEngine_GetNativeVideoSize(media_engine
, &cx
, &cy
);
588 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
590 hr
= IMFMediaEngine_GetVideoAspectRatio(media_engine
, &cx
, &cy
);
591 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
593 if (SUCCEEDED(IMFMediaEngine_QueryInterface(media_engine
, &IID_IMFMediaEngineEx
, (void **)&media_engine_ex
)))
595 hr
= IMFMediaEngineEx_SetSourceFromByteStream(media_engine_ex
, NULL
, NULL
);
596 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
598 hr
= IMFMediaEngineEx_GetAudioStreamCategory(media_engine_ex
, &value
);
599 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
601 hr
= IMFMediaEngineEx_GetAudioEndpointRole(media_engine_ex
, &value
);
602 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
604 hr
= IMFMediaEngineEx_SetAudioStreamCategory(media_engine_ex
, AudioCategory_ForegroundOnlyMedia
);
605 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
607 hr
= IMFMediaEngineEx_SetAudioEndpointRole(media_engine_ex
, eConsole
);
608 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
610 hr
= IMFMediaEngineEx_GetResourceCharacteristics(media_engine_ex
, NULL
);
611 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
613 hr
= IMFMediaEngineEx_GetResourceCharacteristics(media_engine_ex
, &flags
);
614 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
616 hr
= IMFMediaEngineEx_GetRealTimeMode(media_engine_ex
, NULL
);
617 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
619 hr
= IMFMediaEngineEx_GetRealTimeMode(media_engine_ex
, &ret
);
620 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
622 hr
= IMFMediaEngineEx_SetRealTimeMode(media_engine_ex
, TRUE
);
623 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
625 hr
= IMFMediaEngineEx_GetPresentationAttribute(media_engine_ex
, &MF_PD_DURATION
, &propvar
);
626 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
628 hr
= IMFMediaEngineEx_GetStreamAttribute(media_engine_ex
, 0, &MF_SD_PROTECTED
, &propvar
);
629 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
631 IMFMediaEngineEx_Release(media_engine_ex
);
634 IMFMediaEngine_Release(media_engine
);
635 IMFMediaEngineNotify_Release(¬ify
->IMFMediaEngineNotify_iface
);
638 static void test_Play(void)
640 struct media_engine_notify
*notify
;
641 IMFMediaTimeRange
*range
, *range1
;
642 IMFMediaEngine
*media_engine
;
648 notify
= create_callback();
650 media_engine
= create_media_engine(¬ify
->IMFMediaEngineNotify_iface
, NULL
, DXGI_FORMAT_UNKNOWN
);
652 hr
= IMFMediaEngine_GetBuffered(media_engine
, &range
);
653 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
654 hr
= IMFMediaEngine_GetBuffered(media_engine
, &range1
);
655 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
656 ok(range
!= range1
, "Unexpected pointer.\n");
658 count
= IMFMediaTimeRange_GetLength(range
);
659 ok(!count
, "Unexpected count %lu.\n", count
);
661 IMFMediaTimeRange_Release(range
);
662 IMFMediaTimeRange_Release(range1
);
664 ret
= IMFMediaEngine_IsPaused(media_engine
);
665 ok(ret
, "Unexpected state %d.\n", ret
);
667 hr
= IMFMediaEngine_OnVideoStreamTick(media_engine
, NULL
);
668 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
671 hr
= IMFMediaEngine_OnVideoStreamTick(media_engine
, &pts
);
672 ok(hr
== S_FALSE
, "Unexpected hr %#lx.\n", hr
);
673 ok(pts
== MINLONGLONG
, "Unexpected timestamp.\n");
675 hr
= IMFMediaEngine_Play(media_engine
);
676 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
678 ret
= IMFMediaEngine_IsPaused(media_engine
);
679 ok(!ret
, "Unexpected state %d.\n", ret
);
681 hr
= IMFMediaEngine_Play(media_engine
);
682 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
684 hr
= IMFMediaEngine_Shutdown(media_engine
);
685 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
687 hr
= IMFMediaEngine_OnVideoStreamTick(media_engine
, NULL
);
688 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
690 hr
= IMFMediaEngine_OnVideoStreamTick(media_engine
, &pts
);
691 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
693 ret
= IMFMediaEngine_IsPaused(media_engine
);
694 ok(!ret
, "Unexpected state %d.\n", ret
);
696 IMFMediaEngine_Release(media_engine
);
699 media_engine
= create_media_engine(¬ify
->IMFMediaEngineNotify_iface
, NULL
, DXGI_FORMAT_UNKNOWN
);
701 hr
= IMFMediaEngine_Play(media_engine
);
702 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
704 ret
= IMFMediaEngine_IsPaused(media_engine
);
705 ok(!ret
, "Unexpected state %d.\n", ret
);
707 hr
= IMFMediaEngine_Pause(media_engine
);
708 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
710 ret
= IMFMediaEngine_IsPaused(media_engine
);
711 ok(!!ret
, "Unexpected state %d.\n", ret
);
713 IMFMediaEngine_Release(media_engine
);
714 IMFMediaEngineNotify_Release(¬ify
->IMFMediaEngineNotify_iface
);
717 static void test_playback_rate(void)
719 struct media_engine_notify
*notify
;
720 IMFMediaEngine
*media_engine
;
724 notify
= create_callback();
726 media_engine
= create_media_engine(¬ify
->IMFMediaEngineNotify_iface
, NULL
, DXGI_FORMAT_UNKNOWN
);
728 rate
= IMFMediaEngine_GetDefaultPlaybackRate(media_engine
);
729 ok(rate
== 1.0, "Unexpected default rate.\n");
731 rate
= IMFMediaEngine_GetPlaybackRate(media_engine
);
732 ok(rate
== 1.0, "Unexpected default rate.\n");
734 hr
= IMFMediaEngine_SetPlaybackRate(media_engine
, 0.0);
735 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
737 rate
= IMFMediaEngine_GetPlaybackRate(media_engine
);
738 ok(rate
== 0.0, "Unexpected default rate.\n");
740 hr
= IMFMediaEngine_SetDefaultPlaybackRate(media_engine
, 0.0);
741 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
743 IMFMediaEngine_Release(media_engine
);
744 IMFMediaEngineNotify_Release(¬ify
->IMFMediaEngineNotify_iface
);
747 static void test_mute(void)
749 struct media_engine_notify
*notify
;
750 IMFMediaEngine
*media_engine
;
754 notify
= create_callback();
756 media_engine
= create_media_engine(¬ify
->IMFMediaEngineNotify_iface
, NULL
, DXGI_FORMAT_UNKNOWN
);
758 ret
= IMFMediaEngine_GetMuted(media_engine
);
759 ok(!ret
, "Unexpected state.\n");
761 hr
= IMFMediaEngine_SetMuted(media_engine
, TRUE
);
762 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
764 ret
= IMFMediaEngine_GetMuted(media_engine
);
765 ok(ret
, "Unexpected state.\n");
767 hr
= IMFMediaEngine_Shutdown(media_engine
);
768 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
770 ret
= IMFMediaEngine_GetMuted(media_engine
);
771 ok(ret
, "Unexpected state.\n");
773 IMFMediaEngine_Release(media_engine
);
774 IMFMediaEngineNotify_Release(¬ify
->IMFMediaEngineNotify_iface
);
777 static void test_error(void)
779 struct media_engine_notify
*notify
;
780 IMFMediaEngine
*media_engine
;
781 IMFMediaError
*eo
, *eo2
;
785 notify
= create_callback();
787 media_engine
= create_media_engine(¬ify
->IMFMediaEngineNotify_iface
, NULL
, DXGI_FORMAT_UNKNOWN
);
789 eo
= (void *)0xdeadbeef;
790 hr
= IMFMediaEngine_GetError(media_engine
, &eo
);
791 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
792 ok(!eo
, "Unexpected instance.\n");
794 hr
= IMFMediaEngine_SetErrorCode(media_engine
, MF_MEDIA_ENGINE_ERR_ENCRYPTED
+ 1);
795 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
797 hr
= IMFMediaEngine_SetErrorCode(media_engine
, MF_MEDIA_ENGINE_ERR_ABORTED
);
798 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
801 hr
= IMFMediaEngine_GetError(media_engine
, &eo
);
802 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
803 ok(!!eo
, "Unexpected instance.\n");
806 hr
= IMFMediaEngine_GetError(media_engine
, &eo2
);
807 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
808 ok(eo2
!= eo
, "Unexpected instance.\n");
810 IMFMediaError_Release(eo2
);
811 IMFMediaError_Release(eo
);
813 hr
= IMFMediaEngine_SetErrorCode(media_engine
, MF_MEDIA_ENGINE_ERR_NOERROR
);
814 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
816 eo
= (void *)0xdeadbeef;
817 hr
= IMFMediaEngine_GetError(media_engine
, &eo
);
818 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
819 ok(!eo
, "Unexpected instance.\n");
821 hr
= IMFMediaEngine_Shutdown(media_engine
);
822 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
824 eo
= (void *)0xdeadbeef;
825 hr
= IMFMediaEngine_GetError(media_engine
, &eo
);
826 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
827 ok(!eo
, "Unexpected instance.\n");
829 hr
= IMFMediaEngine_SetErrorCode(media_engine
, MF_MEDIA_ENGINE_ERR_NOERROR
);
830 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
832 IMFMediaEngine_Release(media_engine
);
835 hr
= IMFMediaEngineClassFactory_CreateError(factory
, &eo
);
836 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
838 code
= IMFMediaError_GetErrorCode(eo
);
839 ok(code
== MF_MEDIA_ENGINE_ERR_NOERROR
, "Unexpected code %u.\n", code
);
841 hr
= IMFMediaError_GetExtendedErrorCode(eo
);
842 ok(hr
== S_OK
, "Unexpected code %#lx.\n", hr
);
844 hr
= IMFMediaError_SetErrorCode(eo
, MF_MEDIA_ENGINE_ERR_ENCRYPTED
+ 1);
845 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
847 hr
= IMFMediaError_SetErrorCode(eo
, MF_MEDIA_ENGINE_ERR_ABORTED
);
848 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
850 code
= IMFMediaError_GetErrorCode(eo
);
851 ok(code
== MF_MEDIA_ENGINE_ERR_ABORTED
, "Unexpected code %u.\n", code
);
853 hr
= IMFMediaError_SetExtendedErrorCode(eo
, E_FAIL
);
854 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
856 hr
= IMFMediaError_GetExtendedErrorCode(eo
);
857 ok(hr
== E_FAIL
, "Unexpected code %#lx.\n", hr
);
859 IMFMediaError_Release(eo
);
860 IMFMediaEngineNotify_Release(¬ify
->IMFMediaEngineNotify_iface
);
863 static void test_time_range(void)
865 IMFMediaTimeRange
*range
;
871 hr
= IMFMediaEngineClassFactory_CreateTimeRange(factory
, &range
);
872 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
875 hr
= IMFMediaTimeRange_Clear(range
);
876 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
878 ret
= IMFMediaTimeRange_ContainsTime(range
, 10.0);
879 ok(!ret
, "Unexpected return value %d.\n", ret
);
881 count
= IMFMediaTimeRange_GetLength(range
);
882 ok(!count
, "Unexpected range count.\n");
884 hr
= IMFMediaTimeRange_GetStart(range
, 0, &start
);
885 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
887 hr
= IMFMediaTimeRange_GetEnd(range
, 0, &end
);
888 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
891 hr
= IMFMediaTimeRange_AddRange(range
, 10.0, 1.0);
892 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
894 count
= IMFMediaTimeRange_GetLength(range
);
895 ok(count
== 1, "Unexpected range count.\n");
897 hr
= IMFMediaTimeRange_GetStart(range
, 0, &start
);
898 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
899 ok(start
== 10.0, "Unexpected start %.e.\n", start
);
901 hr
= IMFMediaTimeRange_GetEnd(range
, 0, &end
);
902 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
903 ok(end
== 1.0, "Unexpected end %.e.\n", end
);
905 hr
= IMFMediaTimeRange_AddRange(range
, 2.0, 3.0);
906 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
908 count
= IMFMediaTimeRange_GetLength(range
);
909 ok(count
== 1, "Unexpected range count.\n");
911 hr
= IMFMediaTimeRange_GetStart(range
, 0, &start
);
912 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
913 ok(start
== 2.0, "Unexpected start %.8e.\n", start
);
915 hr
= IMFMediaTimeRange_GetEnd(range
, 0, &end
);
916 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
917 ok(end
== 3.0, "Unexpected end %.8e.\n", end
);
919 hr
= IMFMediaTimeRange_AddRange(range
, 10.0, 9.0);
920 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
922 count
= IMFMediaTimeRange_GetLength(range
);
923 ok(count
== 2, "Unexpected range count.\n");
925 hr
= IMFMediaTimeRange_GetStart(range
, 0, &start
);
926 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
927 ok(start
== 2.0, "Unexpected start %.8e.\n", start
);
929 hr
= IMFMediaTimeRange_GetEnd(range
, 0, &end
);
930 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
931 ok(end
== 3.0, "Unexpected end %.8e.\n", end
);
934 hr
= IMFMediaTimeRange_GetStart(range
, 1, &start
);
935 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
936 ok(start
== 10.0, "Unexpected start %.8e.\n", start
);
938 hr
= IMFMediaTimeRange_GetEnd(range
, 1, &end
);
939 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
940 ok(end
== 9.0, "Unexpected end %.8e.\n", end
);
942 hr
= IMFMediaTimeRange_AddRange(range
, 2.0, 9.1);
943 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
945 count
= IMFMediaTimeRange_GetLength(range
);
946 ok(count
== 2, "Unexpected range count.\n");
948 hr
= IMFMediaTimeRange_GetStart(range
, 0, &start
);
949 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
950 ok(start
== 2.0, "Unexpected start %.8e.\n", start
);
952 hr
= IMFMediaTimeRange_GetEnd(range
, 0, &end
);
953 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
954 ok(end
== 9.1, "Unexpected end %.8e.\n", end
);
956 hr
= IMFMediaTimeRange_GetStart(range
, 1, &start
);
957 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
958 ok(start
== 10.0, "Unexpected start %.8e.\n", start
);
960 hr
= IMFMediaTimeRange_GetEnd(range
, 1, &end
);
961 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
962 ok(end
== 9.0, "Unexpected end %.8e.\n", end
);
964 hr
= IMFMediaTimeRange_AddRange(range
, 8.5, 2.5);
965 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
967 count
= IMFMediaTimeRange_GetLength(range
);
968 ok(count
== 2, "Unexpected range count.\n");
970 hr
= IMFMediaTimeRange_GetStart(range
, 0, &start
);
971 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
972 ok(start
== 2.0, "Unexpected start %.8e.\n", start
);
974 hr
= IMFMediaTimeRange_GetEnd(range
, 0, &end
);
975 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
976 ok(end
== 9.1, "Unexpected end %.8e.\n", end
);
978 hr
= IMFMediaTimeRange_AddRange(range
, 20.0, 20.0);
979 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
981 count
= IMFMediaTimeRange_GetLength(range
);
982 ok(count
== 3, "Unexpected range count.\n");
984 hr
= IMFMediaTimeRange_Clear(range
);
985 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
987 count
= IMFMediaTimeRange_GetLength(range
);
988 ok(!count
, "Unexpected range count.\n");
991 hr
= IMFMediaTimeRange_AddRange(range
, 5.0, 10.0);
992 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
994 hr
= IMFMediaTimeRange_AddRange(range
, 6.0, 12.0);
995 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
997 hr
= IMFMediaTimeRange_GetStart(range
, 0, &start
);
998 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
999 ok(start
== 5.0, "Unexpected start %.8e.\n", start
);
1001 hr
= IMFMediaTimeRange_GetEnd(range
, 0, &end
);
1002 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1003 ok(end
== 12.0, "Unexpected end %.8e.\n", end
);
1005 count
= IMFMediaTimeRange_GetLength(range
);
1006 ok(count
== 1, "Unexpected range count.\n");
1008 hr
= IMFMediaTimeRange_AddRange(range
, 4.0, 6.0);
1009 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1011 count
= IMFMediaTimeRange_GetLength(range
);
1012 ok(count
== 1, "Unexpected range count.\n");
1014 hr
= IMFMediaTimeRange_GetStart(range
, 0, &start
);
1015 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1016 ok(start
== 4.0, "Unexpected start %.8e.\n", start
);
1018 hr
= IMFMediaTimeRange_GetEnd(range
, 0, &end
);
1019 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1020 ok(end
== 12.0, "Unexpected end %.8e.\n", end
);
1022 hr
= IMFMediaTimeRange_AddRange(range
, 5.0, 3.0);
1023 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1025 count
= IMFMediaTimeRange_GetLength(range
);
1026 ok(count
== 1, "Unexpected range count.\n");
1028 hr
= IMFMediaTimeRange_GetStart(range
, 0, &start
);
1029 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1030 ok(start
== 4.0, "Unexpected start %.8e.\n", start
);
1032 hr
= IMFMediaTimeRange_GetEnd(range
, 0, &end
);
1033 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1034 ok(end
== 12.0, "Unexpected end %.8e.\n", end
);
1036 IMFMediaTimeRange_Release(range
);
1039 static void test_SetSourceFromByteStream(void)
1041 struct media_engine_notify
*notify
;
1042 IMFMediaEngineEx
*media_engine
;
1043 PROPVARIANT propvar
;
1047 notify
= create_callback();
1049 media_engine
= create_media_engine_ex(¬ify
->IMFMediaEngineNotify_iface
, NULL
, DXGI_FORMAT_UNKNOWN
);
1052 win_skip("IMFMediaEngineEx is not supported.\n");
1053 IMFMediaEngineNotify_Release(¬ify
->IMFMediaEngineNotify_iface
);
1057 hr
= IMFMediaEngineEx_SetSourceFromByteStream(media_engine
, NULL
, NULL
);
1058 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
1060 hr
= IMFMediaEngineEx_GetResourceCharacteristics(media_engine
, NULL
);
1061 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
1063 hr
= IMFMediaEngineEx_GetResourceCharacteristics(media_engine
, &flags
);
1064 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
1066 hr
= IMFMediaEngineEx_GetPresentationAttribute(media_engine
, &MF_PD_DURATION
, &propvar
);
1067 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
1069 hr
= IMFMediaEngineEx_GetStreamAttribute(media_engine
, 0, &MF_SD_PROTECTED
, &propvar
);
1070 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
1072 hr
= IMFMediaEngineEx_GetNumberOfStreams(media_engine
, NULL
);
1073 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
1076 hr
= IMFMediaEngineEx_GetNumberOfStreams(media_engine
, &count
);
1077 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
1078 ok(count
== 123, "Unexpected value %lu.\n", count
);
1080 IMFMediaEngineEx_Release(media_engine
);
1081 IMFMediaEngineNotify_Release(¬ify
->IMFMediaEngineNotify_iface
);
1084 static void test_audio_configuration(void)
1086 struct media_engine_notify
*notify
;
1087 IMFMediaEngineEx
*media_engine
;
1091 notify
= create_callback();
1093 media_engine
= create_media_engine_ex(¬ify
->IMFMediaEngineNotify_iface
, NULL
, DXGI_FORMAT_UNKNOWN
);
1096 IMFMediaEngineNotify_Release(¬ify
->IMFMediaEngineNotify_iface
);
1100 hr
= IMFMediaEngineEx_GetAudioStreamCategory(media_engine
, &value
);
1101 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1102 ok(value
== AudioCategory_Other
, "Unexpected value %u.\n", value
);
1104 hr
= IMFMediaEngineEx_GetAudioEndpointRole(media_engine
, &value
);
1105 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1106 ok(value
== eMultimedia
, "Unexpected value %u.\n", value
);
1108 IMFMediaEngineEx_Release(media_engine
);
1109 IMFMediaEngineNotify_Release(¬ify
->IMFMediaEngineNotify_iface
);
1112 static IMFByteStream
*load_resource(const WCHAR
*name
, const WCHAR
*mime
)
1114 IMFAttributes
*attributes
;
1115 const BYTE
*resource_data
;
1116 IMFByteStream
*stream
;
1121 resource
= FindResourceW(NULL
, name
, (const WCHAR
*)RT_RCDATA
);
1122 ok(resource
!= 0, "FindResourceW %s failed, error %lu\n", debugstr_w(name
), GetLastError());
1123 resource_data
= LockResource(LoadResource(GetModuleHandleW(NULL
), resource
));
1124 resource_len
= SizeofResource(GetModuleHandleW(NULL
), resource
);
1126 hr
= MFCreateTempFile(MF_ACCESSMODE_READWRITE
, MF_OPENMODE_DELETE_IF_EXIST
, MF_FILEFLAGS_NONE
, &stream
);
1127 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1128 hr
= IMFByteStream_Write(stream
, resource_data
, resource_len
, &resource_len
);
1129 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1130 hr
= IMFByteStream_SetCurrentPosition(stream
, 0);
1131 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1133 hr
= IMFByteStream_QueryInterface(stream
, &IID_IMFAttributes
, (void **)&attributes
);
1134 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1135 hr
= IMFAttributes_SetString(attributes
, &MF_BYTESTREAM_CONTENT_TYPE
, mime
);
1136 ok(hr
== S_OK
, "Failed to set string value, hr %#lx.\n", hr
);
1137 IMFAttributes_Release(attributes
);
1142 struct test_transfer_notify
1144 IMFMediaEngineNotify IMFMediaEngineNotify_iface
;
1147 IMFMediaEngineEx
*media_engine
;
1148 HANDLE ready_event
, frame_ready_event
;
1152 static struct test_transfer_notify
*impl_from_test_transfer_notify(IMFMediaEngineNotify
*iface
)
1154 return CONTAINING_RECORD(iface
, struct test_transfer_notify
, IMFMediaEngineNotify_iface
);
1157 static HRESULT WINAPI
test_transfer_notify_QueryInterface(IMFMediaEngineNotify
*iface
, REFIID riid
, void **obj
)
1159 if (IsEqualIID(riid
, &IID_IUnknown
)
1160 || IsEqualIID(riid
, &IID_IMFMediaEngineNotify
))
1163 IMFMediaEngineNotify_AddRef(iface
);
1168 return E_NOINTERFACE
;
1171 static ULONG WINAPI
test_transfer_notify_AddRef(IMFMediaEngineNotify
*iface
)
1173 struct test_transfer_notify
*notify
= impl_from_test_transfer_notify(iface
);
1174 return InterlockedIncrement(¬ify
->refcount
);
1177 static ULONG WINAPI
test_transfer_notify_Release(IMFMediaEngineNotify
*iface
)
1179 struct test_transfer_notify
*notify
= impl_from_test_transfer_notify(iface
);
1180 ULONG refcount
= InterlockedDecrement(¬ify
->refcount
);
1184 CloseHandle(notify
->frame_ready_event
);
1185 CloseHandle(notify
->ready_event
);
1192 static HRESULT WINAPI
test_transfer_notify_EventNotify(IMFMediaEngineNotify
*iface
, DWORD event
, DWORD_PTR param1
, DWORD param2
)
1194 struct test_transfer_notify
*notify
= impl_from_test_transfer_notify(iface
);
1195 IMFMediaEngineEx
*media_engine
= notify
->media_engine
;
1196 DWORD width
, height
;
1202 case MF_MEDIA_ENGINE_EVENT_CANPLAY
:
1203 hr
= IMFMediaEngineEx_Play(media_engine
);
1204 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1207 case MF_MEDIA_ENGINE_EVENT_FORMATCHANGE
:
1208 ret
= IMFMediaEngineEx_HasVideo(media_engine
);
1209 ok(ret
, "Unexpected HasVideo %u.\n", ret
);
1210 hr
= IMFMediaEngineEx_GetNativeVideoSize(media_engine
, &width
, &height
);
1211 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1212 ok(width
== 64, "Unexpected width %lu.\n", width
);
1213 ok(height
== 64, "Unexpected height %lu.\n", height
);
1216 case MF_MEDIA_ENGINE_EVENT_ERROR
:
1217 ok(broken(param2
== MF_E_UNSUPPORTED_BYTESTREAM_TYPE
), "Unexpected error %#lx\n", param2
);
1218 notify
->error
= param2
;
1220 case MF_MEDIA_ENGINE_EVENT_FIRSTFRAMEREADY
:
1221 SetEvent(notify
->frame_ready_event
);
1223 case MF_MEDIA_ENGINE_EVENT_TIMEUPDATE
:
1224 SetEvent(notify
->ready_event
);
1231 static IMFMediaEngineNotifyVtbl test_transfer_notify_vtbl
=
1233 test_transfer_notify_QueryInterface
,
1234 test_transfer_notify_AddRef
,
1235 test_transfer_notify_Release
,
1236 test_transfer_notify_EventNotify
,
1239 static struct test_transfer_notify
*create_transfer_notify(void)
1241 struct test_transfer_notify
*object
;
1243 object
= calloc(1, sizeof(*object
));
1244 object
->IMFMediaEngineNotify_iface
.lpVtbl
= &test_transfer_notify_vtbl
;
1245 object
->refcount
= 1;
1246 object
->ready_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1247 ok(!!object
->ready_event
, "Failed to create an event, error %lu.\n", GetLastError());
1249 object
->frame_ready_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1250 ok(!!object
->frame_ready_event
, "Failed to create an event, error %lu.\n", GetLastError());
1255 static void test_TransferVideoFrame(void)
1257 struct test_transfer_notify
*notify
;
1258 ID3D11Texture2D
*texture
= NULL
, *rb_texture
;
1259 D3D11_MAPPED_SUBRESOURCE map_desc
;
1260 IMFMediaEngineEx
*media_engine
= NULL
;
1261 IMFDXGIDeviceManager
*manager
;
1262 ID3D11DeviceContext
*context
;
1263 D3D11_TEXTURE2D_DESC desc
;
1264 IMFByteStream
*stream
;
1265 ID3D11Device
*device
;
1272 stream
= load_resource(L
"i420-64x64.avi", L
"video/avi");
1274 notify
= create_transfer_notify();
1276 if (!(device
= create_d3d11_device()))
1278 skip("Failed to create a D3D11 device, skipping tests.\n");
1282 hr
= pMFCreateDXGIDeviceManager(&token
, &manager
);
1283 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1284 hr
= IMFDXGIDeviceManager_ResetDevice(manager
, (IUnknown
*)device
, token
);
1285 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1287 media_engine
= create_media_engine_ex(¬ify
->IMFMediaEngineNotify_iface
, manager
, DXGI_FORMAT_B8G8R8X8_UNORM
);
1289 IMFDXGIDeviceManager_Release(manager
);
1291 if (!(notify
->media_engine
= media_engine
))
1294 memset(&desc
, 0, sizeof(desc
));
1298 desc
.Format
= DXGI_FORMAT_B8G8R8X8_UNORM
;
1299 desc
.BindFlags
= D3D11_BIND_RENDER_TARGET
;
1300 desc
.SampleDesc
.Count
= 1;
1301 hr
= ID3D11Device_CreateTexture2D(device
, &desc
, NULL
, &texture
);
1302 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1304 url
= SysAllocString(L
"i420-64x64.avi");
1305 hr
= IMFMediaEngineEx_SetSourceFromByteStream(media_engine
, stream
, url
);
1306 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1308 IMFByteStream_Release(stream
);
1310 res
= WaitForSingleObject(notify
->frame_ready_event
, 5000);
1311 ok(!res
, "Unexpected res %#lx.\n", res
);
1313 if (FAILED(notify
->error
))
1315 win_skip("Media engine reported error %#lx, skipping tests.\n", notify
->error
);
1320 hr
= IMFMediaEngineEx_GetNumberOfStreams(media_engine
, &res
);
1321 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1322 ok(res
== 2, "Unexpected stream count %lu.\n", res
);
1324 /* FIXME: Wine first video frame is often full of garbage, wait for another update */
1325 res
= WaitForSingleObject(notify
->ready_event
, 500);
1326 /* It's also missing the MF_MEDIA_ENGINE_EVENT_TIMEUPDATE notifications */
1328 ok(!res
, "Unexpected res %#lx.\n", res
);
1330 SetRect(&dst_rect
, 0, 0, desc
.Width
, desc
.Height
);
1331 hr
= IMFMediaEngineEx_TransferVideoFrame(notify
->media_engine
, (IUnknown
*)texture
, NULL
, &dst_rect
, NULL
);
1332 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1334 ID3D11Texture2D_GetDesc(texture
, &desc
);
1335 desc
.Usage
= D3D11_USAGE_STAGING
;
1337 desc
.CPUAccessFlags
= D3D11_CPU_ACCESS_READ
;
1339 hr
= ID3D11Device_CreateTexture2D(device
, &desc
, NULL
, &rb_texture
);
1340 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1342 ID3D11Device_GetImmediateContext(device
, &context
);
1343 ID3D11DeviceContext_CopySubresourceRegion(context
, (ID3D11Resource
*)rb_texture
,
1344 0, 0, 0, 0, (ID3D11Resource
*)texture
, 0, NULL
);
1346 memset(&map_desc
, 0, sizeof(map_desc
));
1347 hr
= ID3D11DeviceContext_Map(context
, (ID3D11Resource
*)rb_texture
, 0, D3D11_MAP_READ
, 0, &map_desc
);
1348 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1349 ok(!!map_desc
.pData
, "got pData %p\n", map_desc
.pData
);
1350 ok(map_desc
.DepthPitch
== 16384, "got DepthPitch %u\n", map_desc
.DepthPitch
);
1351 ok(map_desc
.RowPitch
== desc
.Width
* 4, "got RowPitch %u\n", map_desc
.RowPitch
);
1352 check_rgb32_data(L
"rgb32frame.bmp", map_desc
.pData
, map_desc
.RowPitch
* desc
.Height
, &dst_rect
);
1353 ID3D11DeviceContext_Unmap(context
, (ID3D11Resource
*)rb_texture
, 0);
1355 ID3D11DeviceContext_Release(context
);
1356 ID3D11Texture2D_Release(rb_texture
);
1361 IMFMediaEngineEx_Shutdown(media_engine
);
1362 IMFMediaEngineEx_Release(media_engine
);
1366 ID3D11Texture2D_Release(texture
);
1368 ID3D11Device_Release(device
);
1370 IMFMediaEngineNotify_Release(¬ify
->IMFMediaEngineNotify_iface
);
1373 struct passthrough_mft
1375 IMFTransform IMFTransform_iface
;
1378 IMFMediaType
*media_type_in
, *media_type_out
;
1380 LONG processing_count
;
1383 CRITICAL_SECTION cs
;
1386 static struct passthrough_mft
*impl_from_IMFTransform(IMFTransform
*iface
)
1388 return CONTAINING_RECORD(iface
, struct passthrough_mft
, IMFTransform_iface
);
1391 static HRESULT WINAPI
passthrough_mft_QueryInterface(IMFTransform
*iface
, REFIID iid
, void **out
)
1393 struct passthrough_mft
*impl
= impl_from_IMFTransform(iface
);
1395 if (IsEqualGUID(iid
, &IID_IUnknown
) ||
1396 IsEqualGUID(iid
, &IID_IMFTransform
))
1398 *out
= &impl
->IMFTransform_iface
;
1399 IUnknown_AddRef((IUnknown
*)*out
);
1404 return E_NOINTERFACE
;
1407 static ULONG WINAPI
passthrough_mft_AddRef(IMFTransform
*iface
)
1409 struct passthrough_mft
*impl
= impl_from_IMFTransform(iface
);
1410 ULONG refcount
= InterlockedIncrement(&impl
->refcount
);
1414 static ULONG WINAPI
passthrough_mft_Release(IMFTransform
*iface
)
1416 struct passthrough_mft
*impl
= impl_from_IMFTransform(iface
);
1417 ULONG refcount
= InterlockedDecrement(&impl
->refcount
);
1421 if (impl
->media_type_out
) IMFMediaType_Release(impl
->media_type_out
);
1422 if (impl
->media_type_in
) IMFMediaType_Release(impl
->media_type_in
);
1423 DeleteCriticalSection(&impl
->cs
);
1430 static HRESULT WINAPI
passthrough_mft_GetStreamLimits(IMFTransform
*iface
, DWORD
*input_minimum
,
1431 DWORD
*input_maximum
, DWORD
*output_minimum
, DWORD
*output_maximum
)
1433 *input_minimum
= *input_maximum
= *output_minimum
= *output_maximum
= 1;
1437 static HRESULT WINAPI
passthrough_mft_GetStreamCount(IMFTransform
*iface
, DWORD
*inputs
, DWORD
*outputs
)
1439 *inputs
= *outputs
= 1;
1443 static HRESULT WINAPI
passthrough_mft_GetStreamIDs(IMFTransform
*iface
, DWORD input_size
, DWORD
*inputs
,
1444 DWORD output_size
, DWORD
*outputs
)
1449 static HRESULT WINAPI
passthrough_mft_GetInputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_INPUT_STREAM_INFO
*info
)
1454 static HRESULT WINAPI
passthrough_mft_GetOutputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_OUTPUT_STREAM_INFO
*info
)
1457 return MF_E_INVALIDSTREAMNUMBER
;
1460 MFT_OUTPUT_STREAM_PROVIDES_SAMPLES
|
1461 MFT_OUTPUT_STREAM_WHOLE_SAMPLES
|
1462 MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE
|
1463 MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER
;
1465 info
->cbAlignment
= 0;
1470 static HRESULT WINAPI
passthrough_mft_GetAttributes(IMFTransform
*iface
, IMFAttributes
**attributes
)
1475 static HRESULT WINAPI
passthrough_mft_GetInputStreamAttributes(IMFTransform
*iface
, DWORD id
, IMFAttributes
**attributes
)
1480 static HRESULT WINAPI
passthrough_mft_GetOutputStreamAttributes(IMFTransform
*iface
, DWORD id
, IMFAttributes
**attributes
)
1485 static HRESULT WINAPI
passthrough_mft_DeleteInputStream(IMFTransform
*iface
, DWORD id
)
1490 static HRESULT WINAPI
passthrough_mft_AddInputStreams(IMFTransform
*iface
, DWORD streams
, DWORD
*ids
)
1495 static HRESULT WINAPI
passthrough_mft_GetInputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
1496 IMFMediaType
**type
)
1498 static const GUID
*types
[] = { &MFMediaType_Video
, &MFMediaType_Audio
};
1502 return MF_E_INVALIDSTREAMNUMBER
;
1504 if (index
> ARRAY_SIZE(types
) - 1)
1505 return MF_E_NO_MORE_TYPES
;
1507 if (SUCCEEDED(hr
= MFCreateMediaType(type
)))
1508 hr
= IMFMediaType_SetGUID(*type
, &MF_MT_MAJOR_TYPE
, types
[index
]);
1513 static HRESULT WINAPI
passthrough_mft_GetOutputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
1514 IMFMediaType
**type
)
1516 struct passthrough_mft
*impl
= impl_from_IMFTransform(iface
);
1520 return MF_E_INVALIDSTREAMNUMBER
;
1522 EnterCriticalSection(&impl
->cs
);
1526 hr
= MF_E_NO_MORE_TYPES
;
1528 else if (impl
->media_type_out
)
1530 *type
= impl
->media_type_out
;
1531 IMFMediaType_AddRef(*type
);
1533 else if (impl
->media_type_in
)
1535 *type
= impl
->media_type_in
;
1536 IMFMediaType_AddRef(*type
);
1540 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1543 LeaveCriticalSection(&impl
->cs
);
1548 static HRESULT WINAPI
passthrough_mft_SetInputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
1550 struct passthrough_mft
*impl
= impl_from_IMFTransform(iface
);
1554 return MF_E_INVALIDSTREAMNUMBER
;
1556 EnterCriticalSection(&impl
->cs
);
1558 if (!(flags
& MFT_SET_TYPE_TEST_ONLY
))
1560 if (impl
->media_type_in
)
1561 IMFMediaType_Release(impl
->media_type_in
);
1563 impl
->media_type_in
= type
;
1564 IMFMediaType_AddRef(impl
->media_type_in
);
1567 LeaveCriticalSection(&impl
->cs
);
1572 static HRESULT WINAPI
passthrough_mft_SetOutputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
1574 struct passthrough_mft
*impl
= impl_from_IMFTransform(iface
);
1577 return MF_E_INVALIDSTREAMNUMBER
;
1579 EnterCriticalSection(&impl
->cs
);
1581 if (impl
->media_type_out
)
1582 IMFMediaType_Release(impl
->media_type_out
);
1584 impl
->media_type_out
= type
;
1585 IMFMediaType_AddRef(impl
->media_type_out
);
1587 LeaveCriticalSection(&impl
->cs
);
1592 static HRESULT WINAPI
passthrough_mft_GetInputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
1594 struct passthrough_mft
*impl
= impl_from_IMFTransform(iface
);
1598 return MF_E_INVALIDSTREAMNUMBER
;
1600 EnterCriticalSection(&impl
->cs
);
1601 if (impl
->media_type_in
)
1603 *type
= impl
->media_type_in
;
1604 IMFMediaType_AddRef(*type
);
1608 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1610 LeaveCriticalSection(&impl
->cs
);
1615 static HRESULT WINAPI
passthrough_mft_GetOutputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
1617 struct passthrough_mft
*impl
= impl_from_IMFTransform(iface
);
1621 return MF_E_INVALIDSTREAMNUMBER
;
1623 EnterCriticalSection(&impl
->cs
);
1625 if (impl
->media_type_out
)
1627 *type
= impl
->media_type_out
;
1628 IMFMediaType_AddRef(*type
);
1632 hr
= MF_E_TRANSFORM_TYPE_NOT_SET
;
1635 LeaveCriticalSection(&impl
->cs
);
1640 static HRESULT WINAPI
passthrough_mft_GetInputStatus(IMFTransform
*iface
, DWORD id
, DWORD
*flags
)
1645 static HRESULT WINAPI
passthrough_mft_GetOutputStatus(IMFTransform
*iface
, DWORD
*flags
)
1650 static HRESULT WINAPI
passthrough_mft_SetOutputBounds(IMFTransform
*iface
, LONGLONG lower
, LONGLONG upper
)
1655 static HRESULT WINAPI
passthrough_mft_ProcessEvent(IMFTransform
*iface
, DWORD id
, IMFMediaEvent
*event
)
1660 static HRESULT WINAPI
passthrough_mft_ProcessMessage(IMFTransform
*iface
, MFT_MESSAGE_TYPE message
, ULONG_PTR param
)
1662 if (message
== MFT_MESSAGE_COMMAND_FLUSH
)
1668 static HRESULT WINAPI
passthrough_mft_ProcessInput(IMFTransform
*iface
, DWORD id
, IMFSample
*sample
, DWORD flags
)
1670 struct passthrough_mft
*impl
= impl_from_IMFTransform(iface
);
1674 return MF_E_INVALIDSTREAMNUMBER
;
1676 EnterCriticalSection(&impl
->cs
);
1679 hr
= MF_E_NOTACCEPTING
;
1683 impl
->sample
= sample
;
1684 IMFSample_AddRef(impl
->sample
);
1687 LeaveCriticalSection(&impl
->cs
);
1692 static HRESULT WINAPI
passthrough_mft_ProcessOutput(IMFTransform
*iface
, DWORD flags
, DWORD count
,
1693 MFT_OUTPUT_DATA_BUFFER
*samples
, DWORD
*status
)
1695 struct passthrough_mft
*impl
= impl_from_IMFTransform(iface
);
1700 return E_INVALIDARG
;
1702 EnterCriticalSection(&impl
->cs
);
1706 hr
= IMFSample_GetUINT32(impl
->sample
, &IID_IMFSample
, &val
);
1708 if (impl
->index
> 0)
1710 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1711 ok(val
== impl
->index
, "Got unexpected value %u.\n", val
);
1715 ok(hr
== MF_E_ATTRIBUTENOTFOUND
, "Unexpected hr %#lx.\n", hr
);
1718 IMFSample_SetUINT32(impl
->sample
, &IID_IMFSample
, impl
->index
+ 1);
1720 samples
->pSample
= impl
->sample
;
1721 *status
= samples
[0].dwStatus
= 0;
1722 impl
->processing_count
++;
1724 impl
->sample
= NULL
;
1730 hr
= MF_E_TRANSFORM_NEED_MORE_INPUT
;
1733 LeaveCriticalSection(&impl
->cs
);
1738 static const IMFTransformVtbl passthrough_mft_vtbl
=
1740 passthrough_mft_QueryInterface
,
1741 passthrough_mft_AddRef
,
1742 passthrough_mft_Release
,
1743 passthrough_mft_GetStreamLimits
,
1744 passthrough_mft_GetStreamCount
,
1745 passthrough_mft_GetStreamIDs
,
1746 passthrough_mft_GetInputStreamInfo
,
1747 passthrough_mft_GetOutputStreamInfo
,
1748 passthrough_mft_GetAttributes
,
1749 passthrough_mft_GetInputStreamAttributes
,
1750 passthrough_mft_GetOutputStreamAttributes
,
1751 passthrough_mft_DeleteInputStream
,
1752 passthrough_mft_AddInputStreams
,
1753 passthrough_mft_GetInputAvailableType
,
1754 passthrough_mft_GetOutputAvailableType
,
1755 passthrough_mft_SetInputType
,
1756 passthrough_mft_SetOutputType
,
1757 passthrough_mft_GetInputCurrentType
,
1758 passthrough_mft_GetOutputCurrentType
,
1759 passthrough_mft_GetInputStatus
,
1760 passthrough_mft_GetOutputStatus
,
1761 passthrough_mft_SetOutputBounds
,
1762 passthrough_mft_ProcessEvent
,
1763 passthrough_mft_ProcessMessage
,
1764 passthrough_mft_ProcessInput
,
1765 passthrough_mft_ProcessOutput
,
1768 HRESULT
passthrough_mft_create(UINT32 index
, struct passthrough_mft
**out
)
1770 struct passthrough_mft
*impl
;
1774 if (!(impl
= calloc(1, sizeof(*impl
))))
1775 return E_OUTOFMEMORY
;
1777 impl
->IMFTransform_iface
.lpVtbl
= &passthrough_mft_vtbl
;
1778 impl
->index
= index
;
1781 InitializeCriticalSection(&impl
->cs
);
1787 static void test_effect(void)
1789 struct passthrough_mft
*video_effect
= NULL
, *video_effect2
= NULL
, *audio_effect
= NULL
, *audio_effect2
= NULL
;
1790 struct test_transfer_notify
*notify
;
1791 IMFMediaEngineEx
*media_engine_ex
= NULL
;
1792 ID3D11Texture2D
*texture
= NULL
;
1793 IMFDXGIDeviceManager
*manager
;
1794 ID3D11Device
*device
= NULL
;
1795 D3D11_TEXTURE2D_DESC desc
;
1796 IMFByteStream
*stream
;
1804 stream
= load_resource(L
"i420-64x64.avi", L
"video/avi");
1806 notify
= create_transfer_notify();
1808 if (!(device
= create_d3d11_device()))
1810 skip("Failed to create a D3D11 device, skipping tests.\n");
1814 hr
= pMFCreateDXGIDeviceManager(&token
, &manager
);
1815 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1816 hr
= IMFDXGIDeviceManager_ResetDevice(manager
, (IUnknown
*)device
, token
);
1817 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1819 media_engine_ex
= create_media_engine_ex(¬ify
->IMFMediaEngineNotify_iface
,
1820 manager
, DXGI_FORMAT_B8G8R8X8_UNORM
);
1822 IMFDXGIDeviceManager_Release(manager
);
1824 if (!(notify
->media_engine
= media_engine_ex
))
1827 memset(&desc
, 0, sizeof(desc
));
1831 desc
.Format
= DXGI_FORMAT_B8G8R8X8_UNORM
;
1832 desc
.BindFlags
= D3D11_BIND_RENDER_TARGET
;
1833 desc
.SampleDesc
.Count
= 1;
1834 hr
= ID3D11Device_CreateTexture2D(device
, &desc
, NULL
, &texture
);
1835 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1837 hr
= IMFMediaEngineEx_RemoveAllEffects(media_engine_ex
);
1838 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1840 hr
= passthrough_mft_create(0, &video_effect
);
1841 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1843 hr
= passthrough_mft_create(1, &video_effect2
);
1844 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1846 hr
= IMFMediaEngineEx_InsertVideoEffect(media_engine_ex
, (IUnknown
*)&video_effect
->IMFTransform_iface
, FALSE
);
1847 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1848 EXPECT_REF(&video_effect
->IMFTransform_iface
, 2);
1850 hr
= IMFMediaEngineEx_InsertVideoEffect(media_engine_ex
, (IUnknown
*)&video_effect2
->IMFTransform_iface
, FALSE
);
1851 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1852 EXPECT_REF(&video_effect2
->IMFTransform_iface
, 2);
1854 hr
= IMFMediaEngineEx_RemoveAllEffects(media_engine_ex
);
1855 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1856 EXPECT_REF(&video_effect
->IMFTransform_iface
, 1);
1857 EXPECT_REF(&video_effect2
->IMFTransform_iface
, 1);
1859 hr
= IMFMediaEngineEx_InsertVideoEffect(media_engine_ex
, (IUnknown
*)&video_effect
->IMFTransform_iface
, FALSE
);
1860 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1861 EXPECT_REF(&video_effect
->IMFTransform_iface
, 2);
1863 hr
= IMFMediaEngineEx_InsertVideoEffect(media_engine_ex
, (IUnknown
*)&video_effect2
->IMFTransform_iface
, FALSE
);
1864 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1865 EXPECT_REF(&video_effect2
->IMFTransform_iface
, 2);
1867 hr
= passthrough_mft_create(0, &audio_effect
);
1868 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1870 hr
= passthrough_mft_create(1, &audio_effect2
);
1871 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1873 hr
= IMFMediaEngineEx_InsertAudioEffect(media_engine_ex
, (IUnknown
*)&audio_effect
->IMFTransform_iface
, FALSE
);
1874 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1875 EXPECT_REF(&audio_effect
->IMFTransform_iface
, 2);
1877 hr
= IMFMediaEngineEx_InsertAudioEffect(media_engine_ex
, (IUnknown
*)&audio_effect2
->IMFTransform_iface
, FALSE
);
1878 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1879 EXPECT_REF(&audio_effect2
->IMFTransform_iface
, 2);
1881 url
= SysAllocString(L
"i420-64x64.avi");
1882 hr
= IMFMediaEngineEx_SetSourceFromByteStream(media_engine_ex
, stream
, url
);
1883 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1885 IMFByteStream_Release(stream
);
1887 /* Wait for MediaEngine to be ready. */
1888 res
= WaitForSingleObject(notify
->frame_ready_event
, 5000);
1889 ok(!res
, "Unexpected res %#lx.\n", res
);
1891 SetRect(&dst_rect
, 0, 0, desc
.Width
, desc
.Height
);
1892 hr
= IMFMediaEngineEx_TransferVideoFrame(notify
->media_engine
, (IUnknown
*)texture
, NULL
, &dst_rect
, NULL
);
1893 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1895 ok(video_effect
->processing_count
> 0, "Unexpected processing count %lu.\n", video_effect
->processing_count
);
1896 ok(video_effect2
->processing_count
> 0, "Unexpected processing count %lu.\n", video_effect2
->processing_count
);
1898 if (SUCCEEDED(hr
= MFCreateAudioRenderer(NULL
, &sink
)))
1900 ok(audio_effect
->processing_count
> 0, "Unexpected processing count %lu.\n", audio_effect
->processing_count
);
1901 ok(audio_effect2
->processing_count
> 0, "Unexpected processing count %lu.\n", audio_effect2
->processing_count
);
1903 IMFMediaSink_Release(sink
);
1905 else if (hr
== MF_E_NO_AUDIO_PLAYBACK_DEVICE
)
1907 ok(!audio_effect
->processing_count
, "Unexpected processing count %lu.\n", audio_effect
->processing_count
);
1908 ok(!audio_effect2
->processing_count
, "Unexpected processing count %lu.\n", audio_effect2
->processing_count
);
1912 if (media_engine_ex
)
1914 IMFMediaEngineEx_Shutdown(media_engine_ex
);
1916 hr
= IMFMediaEngineEx_RemoveAllEffects(media_engine_ex
);
1917 ok(hr
== MF_E_SHUTDOWN
, "Unexpected hr %#lx.\n", hr
);
1919 IMFMediaEngineEx_Release(media_engine_ex
);
1923 ID3D11Texture2D_Release(texture
);
1925 ID3D11Device_Release(device
);
1928 IMFTransform_Release(&audio_effect2
->IMFTransform_iface
);
1930 IMFTransform_Release(&audio_effect
->IMFTransform_iface
);
1933 IMFTransform_Release(&video_effect2
->IMFTransform_iface
);
1935 IMFTransform_Release(&video_effect
->IMFTransform_iface
);
1937 IMFMediaEngineNotify_Release(¬ify
->IMFMediaEngineNotify_iface
);
1940 static void test_GetDuration(void)
1942 static const double allowed_error
= 0.000001;
1943 struct test_transfer_notify
*notify
;
1944 IMFMediaEngineEx
*media_engine
;
1945 IMFByteStream
*stream
;
1951 notify
= create_transfer_notify();
1952 media_engine
= create_media_engine_ex(¬ify
->IMFMediaEngineNotify_iface
, NULL
, DXGI_FORMAT_B8G8R8X8_UNORM
);
1953 notify
->media_engine
= media_engine
;
1954 ok(!!media_engine
, "create_media_engine_ex failed.\n");
1956 stream
= load_resource(L
"i420-64x64.avi", L
"video/avi");
1957 url
= SysAllocString(L
"i420-64x64.avi");
1958 hr
= IMFMediaEngineEx_SetSourceFromByteStream(media_engine
, stream
, url
);
1959 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1960 res
= WaitForSingleObject(notify
->ready_event
, 5000);
1961 ok(!res
, "Unexpected res %#lx.\n", res
);
1963 duration
= IMFMediaEngineEx_GetDuration(media_engine
);
1964 ok(compare_double(duration
, 0.133467, allowed_error
), "Got unexpected duration %lf.\n", duration
);
1967 IMFByteStream_Release(stream
);
1968 IMFMediaEngineEx_Shutdown(media_engine
);
1969 IMFMediaEngineEx_Release(media_engine
);
1970 IMFMediaEngineNotify_Release(¬ify
->IMFMediaEngineNotify_iface
);
1973 START_TEST(mfmediaengine
)
1979 hr
= CoCreateInstance(&CLSID_MFMediaEngineClassFactory
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IMFMediaEngineClassFactory
,
1983 win_skip("Media Engine is not supported.\n");
1990 hr
= MFStartup(MF_VERSION
, MFSTARTUP_FULL
);
1991 ok(hr
== S_OK
, "MFStartup failed: %#lx.\n", hr
);
1994 test_CreateInstance();
1997 test_playback_rate();
2001 test_SetSourceFromByteStream();
2002 test_audio_configuration();
2003 test_TransferVideoFrame();
2007 IMFMediaEngineClassFactory_Release(factory
);