2 * Copyright 2018 Alistair Leslie-Hughes
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
33 DEFINE_GUID(GUID_NULL
, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
40 #include "mfreadwrite.h"
44 #include "wine/test.h"
46 static ULONG
get_refcount(void *iface
)
48 IUnknown
*unknown
= iface
;
49 IUnknown_AddRef(unknown
);
50 return IUnknown_Release(unknown
);
53 static HWND
create_window(void)
55 RECT r
= {0, 0, 640, 480};
57 AdjustWindowRect(&r
, WS_OVERLAPPEDWINDOW
| WS_VISIBLE
, FALSE
);
59 return CreateWindowA("static", "mfreadwrite_test", WS_OVERLAPPEDWINDOW
| WS_VISIBLE
,
60 0, 0, r
.right
- r
.left
, r
.bottom
- r
.top
, NULL
, NULL
, NULL
, NULL
);
63 static IDirect3DDevice9
*create_d3d9_device(IDirect3D9
*d3d9
, HWND focus_window
)
65 D3DPRESENT_PARAMETERS present_parameters
= {0};
66 IDirect3DDevice9
*device
= NULL
;
68 present_parameters
.BackBufferWidth
= 640;
69 present_parameters
.BackBufferHeight
= 480;
70 present_parameters
.BackBufferFormat
= D3DFMT_X8R8G8B8
;
71 present_parameters
.SwapEffect
= D3DSWAPEFFECT_DISCARD
;
72 present_parameters
.hDeviceWindow
= focus_window
;
73 present_parameters
.Windowed
= TRUE
;
74 present_parameters
.EnableAutoDepthStencil
= TRUE
;
75 present_parameters
.AutoDepthStencilFormat
= D3DFMT_D24S8
;
76 present_parameters
.Flags
= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER
;
78 IDirect3D9_CreateDevice(d3d9
, D3DADAPTER_DEFAULT
, D3DDEVTYPE_HAL
, focus_window
,
79 D3DCREATE_HARDWARE_VERTEXPROCESSING
, &present_parameters
, &device
);
84 static HRESULT (WINAPI
*pMFCreateMFByteStreamOnStream
)(IStream
*stream
, IMFByteStream
**bytestream
);
86 static void init_functions(void)
88 HMODULE mod
= GetModuleHandleA("mfplat.dll");
90 #define X(f) if (!(p##f = (void*)GetProcAddress(mod, #f))) return;
91 X(MFCreateMFByteStreamOnStream
);
101 struct test_media_stream
103 IMFMediaStream IMFMediaStream_iface
;
105 IMFMediaSource
*source
;
106 IMFStreamDescriptor
*sd
;
107 IMFMediaEventQueue
*event_queue
;
109 LONGLONG sample_duration
, sample_time
;
112 static struct test_media_stream
*impl_from_IMFMediaStream(IMFMediaStream
*iface
)
114 return CONTAINING_RECORD(iface
, struct test_media_stream
, IMFMediaStream_iface
);
117 static HRESULT WINAPI
test_media_stream_QueryInterface(IMFMediaStream
*iface
, REFIID riid
, void **out
)
119 if (IsEqualIID(riid
, &IID_IMFMediaStream
)
120 || IsEqualIID(riid
, &IID_IMFMediaEventGenerator
)
121 || IsEqualIID(riid
, &IID_IUnknown
))
128 return E_NOINTERFACE
;
131 IMFMediaStream_AddRef(iface
);
135 static ULONG WINAPI
test_media_stream_AddRef(IMFMediaStream
*iface
)
137 struct test_media_stream
*stream
= impl_from_IMFMediaStream(iface
);
138 return InterlockedIncrement(&stream
->refcount
);
141 static ULONG WINAPI
test_media_stream_Release(IMFMediaStream
*iface
)
143 struct test_media_stream
*stream
= impl_from_IMFMediaStream(iface
);
144 ULONG refcount
= InterlockedDecrement(&stream
->refcount
);
148 IMFMediaEventQueue_Release(stream
->event_queue
);
155 static HRESULT WINAPI
test_media_stream_GetEvent(IMFMediaStream
*iface
, DWORD flags
, IMFMediaEvent
**event
)
157 struct test_media_stream
*stream
= impl_from_IMFMediaStream(iface
);
158 return IMFMediaEventQueue_GetEvent(stream
->event_queue
, flags
, event
);
161 static HRESULT WINAPI
test_media_stream_BeginGetEvent(IMFMediaStream
*iface
, IMFAsyncCallback
*callback
, IUnknown
*state
)
163 struct test_media_stream
*stream
= impl_from_IMFMediaStream(iface
);
164 ok(callback
!= NULL
&& state
== (IUnknown
*)iface
, "Unexpected arguments.\n");
165 return IMFMediaEventQueue_BeginGetEvent(stream
->event_queue
, callback
, state
);
168 static HRESULT WINAPI
test_media_stream_EndGetEvent(IMFMediaStream
*iface
, IMFAsyncResult
*result
, IMFMediaEvent
**event
)
170 struct test_media_stream
*stream
= impl_from_IMFMediaStream(iface
);
171 ok(!!result
&& !!event
, "Unexpected arguments.\n");
172 return IMFMediaEventQueue_EndGetEvent(stream
->event_queue
, result
, event
);
175 static HRESULT WINAPI
test_media_stream_QueueEvent(IMFMediaStream
*iface
, MediaEventType event_type
, REFGUID ext_type
,
176 HRESULT hr
, const PROPVARIANT
*value
)
178 struct test_media_stream
*stream
= impl_from_IMFMediaStream(iface
);
179 return IMFMediaEventQueue_QueueEventParamVar(stream
->event_queue
, event_type
, ext_type
, hr
, value
);
182 static HRESULT WINAPI
test_media_stream_GetMediaSource(IMFMediaStream
*iface
, IMFMediaSource
**source
)
184 struct test_media_stream
*stream
= impl_from_IMFMediaStream(iface
);
186 *source
= stream
->source
;
187 IMFMediaSource_AddRef(*source
);
192 static HRESULT WINAPI
test_media_stream_GetStreamDescriptor(IMFMediaStream
*iface
, IMFStreamDescriptor
**sd
)
194 struct test_media_stream
*stream
= impl_from_IMFMediaStream(iface
);
197 IMFStreamDescriptor_AddRef(*sd
);
202 static BOOL fail_request_sample
;
204 static HRESULT WINAPI
test_media_stream_RequestSample(IMFMediaStream
*iface
, IUnknown
*token
)
206 struct test_media_stream
*stream
= impl_from_IMFMediaStream(iface
);
207 IMFMediaBuffer
*buffer
;
211 if (fail_request_sample
)
214 hr
= MFCreateSample(&sample
);
215 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
216 if (stream
->sample_duration
)
218 hr
= IMFSample_SetSampleDuration(sample
, stream
->sample_duration
);
219 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
221 hr
= IMFSample_SetSampleTime(sample
, stream
->sample_time
);
222 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
224 stream
->sample_time
+= stream
->sample_duration
;
228 hr
= IMFSample_SetSampleTime(sample
, 123);
229 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
231 hr
= IMFSample_SetSampleDuration(sample
, 1);
232 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
236 IMFSample_SetUnknown(sample
, &MFSampleExtension_Token
, token
);
238 /* Reader expects buffers, empty samples are considered an error. */
239 hr
= MFCreateMemoryBuffer(8, &buffer
);
240 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
241 hr
= IMFSample_AddBuffer(sample
, buffer
);
242 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
243 IMFMediaBuffer_Release(buffer
);
245 hr
= IMFMediaEventQueue_QueueEventParamUnk(stream
->event_queue
, MEMediaSample
, &GUID_NULL
, S_OK
,
247 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
248 IMFSample_Release(sample
);
253 static const IMFMediaStreamVtbl test_media_stream_vtbl
=
255 test_media_stream_QueryInterface
,
256 test_media_stream_AddRef
,
257 test_media_stream_Release
,
258 test_media_stream_GetEvent
,
259 test_media_stream_BeginGetEvent
,
260 test_media_stream_EndGetEvent
,
261 test_media_stream_QueueEvent
,
262 test_media_stream_GetMediaSource
,
263 test_media_stream_GetStreamDescriptor
,
264 test_media_stream_RequestSample
,
267 #define TEST_SOURCE_NUM_STREAMS 3
271 IMFMediaSource IMFMediaSource_iface
;
273 IMFMediaEventQueue
*event_queue
;
274 IMFPresentationDescriptor
*pd
;
275 struct test_media_stream
*streams
[TEST_SOURCE_NUM_STREAMS
];
276 unsigned stream_count
;
277 enum source_state state
;
281 static struct test_source
*impl_from_IMFMediaSource(IMFMediaSource
*iface
)
283 return CONTAINING_RECORD(iface
, struct test_source
, IMFMediaSource_iface
);
286 static HRESULT WINAPI
test_source_QueryInterface(IMFMediaSource
*iface
, REFIID riid
, void **out
)
288 if (IsEqualIID(riid
, &IID_IMFMediaSource
)
289 || IsEqualIID(riid
, &IID_IMFMediaEventGenerator
)
290 || IsEqualIID(riid
, &IID_IUnknown
))
297 return E_NOINTERFACE
;
300 IMFMediaSource_AddRef(iface
);
304 static ULONG WINAPI
test_source_AddRef(IMFMediaSource
*iface
)
306 struct test_source
*source
= impl_from_IMFMediaSource(iface
);
307 return InterlockedIncrement(&source
->refcount
);
310 static ULONG WINAPI
test_source_Release(IMFMediaSource
*iface
)
312 struct test_source
*source
= impl_from_IMFMediaSource(iface
);
313 ULONG refcount
= InterlockedDecrement(&source
->refcount
);
317 IMFMediaEventQueue_Release(source
->event_queue
);
324 static HRESULT WINAPI
test_source_GetEvent(IMFMediaSource
*iface
, DWORD flags
, IMFMediaEvent
**event
)
326 struct test_source
*source
= impl_from_IMFMediaSource(iface
);
327 return IMFMediaEventQueue_GetEvent(source
->event_queue
, flags
, event
);
330 static HRESULT WINAPI
test_source_BeginGetEvent(IMFMediaSource
*iface
, IMFAsyncCallback
*callback
, IUnknown
*state
)
332 struct test_source
*source
= impl_from_IMFMediaSource(iface
);
333 ok(callback
!= NULL
&& state
== (IUnknown
*)iface
, "Unexpected arguments source %p, %p, state %p.\n", iface
, callback
, state
);
334 return IMFMediaEventQueue_BeginGetEvent(source
->event_queue
, callback
, state
);
337 static HRESULT WINAPI
test_source_EndGetEvent(IMFMediaSource
*iface
, IMFAsyncResult
*result
, IMFMediaEvent
**event
)
339 struct test_source
*source
= impl_from_IMFMediaSource(iface
);
340 return IMFMediaEventQueue_EndGetEvent(source
->event_queue
, result
, event
);
343 static HRESULT WINAPI
test_source_QueueEvent(IMFMediaSource
*iface
, MediaEventType event_type
, REFGUID ext_type
,
344 HRESULT hr
, const PROPVARIANT
*value
)
346 struct test_source
*source
= impl_from_IMFMediaSource(iface
);
347 return IMFMediaEventQueue_QueueEventParamVar(source
->event_queue
, event_type
, ext_type
, hr
, value
);
350 static HRESULT WINAPI
test_source_GetCharacteristics(IMFMediaSource
*iface
, DWORD
*flags
)
352 *flags
= MFMEDIASOURCE_CAN_SEEK
;
357 static HRESULT WINAPI
test_source_CreatePresentationDescriptor(IMFMediaSource
*iface
, IMFPresentationDescriptor
**pd
)
359 struct test_source
*source
= impl_from_IMFMediaSource(iface
);
360 IMFStreamDescriptor
*sds
[ARRAY_SIZE(source
->streams
)];
361 IMFMediaType
*media_type
;
365 EnterCriticalSection(&source
->cs
);
370 IMFPresentationDescriptor_AddRef(*pd
);
374 for (i
= 0; i
< source
->stream_count
; ++i
)
376 hr
= MFCreateMediaType(&media_type
);
377 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
379 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Audio
);
380 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
381 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, &MFAudioFormat_PCM
);
382 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
383 hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, 32);
384 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
386 hr
= MFCreateStreamDescriptor(i
, 1, &media_type
, &sds
[i
]);
387 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
389 IMFMediaType_Release(media_type
);
392 hr
= MFCreatePresentationDescriptor(source
->stream_count
, sds
, &source
->pd
);
393 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
394 for (i
= 0; i
< source
->stream_count
; ++i
)
395 IMFStreamDescriptor_Release(sds
[i
]);
398 IMFPresentationDescriptor_AddRef(*pd
);
401 LeaveCriticalSection(&source
->cs
);
406 static BOOL
is_stream_selected(IMFPresentationDescriptor
*pd
, DWORD index
)
408 IMFStreamDescriptor
*sd
;
409 BOOL selected
= FALSE
;
411 if (SUCCEEDED(IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd
, index
, &selected
, &sd
)))
412 IMFStreamDescriptor_Release(sd
);
417 static HRESULT WINAPI
test_source_Start(IMFMediaSource
*iface
, IMFPresentationDescriptor
*pd
, const GUID
*time_format
,
418 const PROPVARIANT
*start_position
)
420 struct test_source
*source
= impl_from_IMFMediaSource(iface
);
421 MediaEventType event_type
;
426 ok(time_format
&& IsEqualGUID(time_format
, &GUID_NULL
), "Unexpected time format %s.\n",
427 wine_dbgstr_guid(time_format
));
428 ok(start_position
&& (start_position
->vt
== VT_I8
|| start_position
->vt
== VT_EMPTY
),
429 "Unexpected position type.\n");
431 EnterCriticalSection(&source
->cs
);
433 event_type
= source
->state
== SOURCE_RUNNING
? MESourceSeeked
: MESourceStarted
;
434 hr
= IMFMediaEventQueue_QueueEventParamVar(source
->event_queue
, event_type
, &GUID_NULL
, S_OK
, NULL
);
435 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
437 for (i
= 0; i
< source
->stream_count
; ++i
)
439 if (!is_stream_selected(pd
, i
))
443 var
.punkVal
= (IUnknown
*)&source
->streams
[i
]->IMFMediaStream_iface
;
444 event_type
= source
->streams
[i
]->is_new
? MENewStream
: MEUpdatedStream
;
445 source
->streams
[i
]->is_new
= FALSE
;
446 hr
= IMFMediaEventQueue_QueueEventParamVar(source
->event_queue
, event_type
, &GUID_NULL
, S_OK
, &var
);
447 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
449 event_type
= source
->state
== SOURCE_RUNNING
? MEStreamSeeked
: MEStreamStarted
;
450 hr
= IMFMediaEventQueue_QueueEventParamVar(source
->streams
[i
]->event_queue
, event_type
, &GUID_NULL
,
452 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
455 source
->state
= SOURCE_RUNNING
;
457 LeaveCriticalSection(&source
->cs
);
462 static HRESULT WINAPI
test_source_Stop(IMFMediaSource
*iface
)
464 ok(0, "Unexpected call.\n");
468 static HRESULT WINAPI
test_source_Pause(IMFMediaSource
*iface
)
470 ok(0, "Unexpected call.\n");
474 static HRESULT WINAPI
test_source_Shutdown(IMFMediaSource
*iface
)
476 struct test_source
*source
= impl_from_IMFMediaSource(iface
);
479 hr
= IMFMediaEventQueue_Shutdown(source
->event_queue
);
480 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
485 static const IMFMediaSourceVtbl test_source_vtbl
=
487 test_source_QueryInterface
,
490 test_source_GetEvent
,
491 test_source_BeginGetEvent
,
492 test_source_EndGetEvent
,
493 test_source_QueueEvent
,
494 test_source_GetCharacteristics
,
495 test_source_CreatePresentationDescriptor
,
499 test_source_Shutdown
,
502 static struct test_media_stream
*create_test_stream(DWORD stream_index
, IMFMediaSource
*source
)
504 struct test_media_stream
*stream
;
505 IMFPresentationDescriptor
*pd
;
509 stream
= calloc(1, sizeof(*stream
));
510 stream
->IMFMediaStream_iface
.lpVtbl
= &test_media_stream_vtbl
;
511 stream
->refcount
= 1;
512 hr
= MFCreateEventQueue(&stream
->event_queue
);
513 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
514 stream
->source
= source
;
515 IMFMediaSource_AddRef(stream
->source
);
516 stream
->is_new
= TRUE
;
518 IMFMediaSource_CreatePresentationDescriptor(source
, &pd
);
519 IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd
, stream_index
, &selected
, &stream
->sd
);
520 IMFPresentationDescriptor_Release(pd
);
525 static IMFMediaSource
*create_test_source(int stream_count
)
527 struct test_source
*source
;
530 source
= calloc(1, sizeof(*source
));
531 source
->IMFMediaSource_iface
.lpVtbl
= &test_source_vtbl
;
532 source
->refcount
= 1;
533 source
->stream_count
= stream_count
;
534 MFCreateEventQueue(&source
->event_queue
);
535 InitializeCriticalSection(&source
->cs
);
536 for (i
= 0; i
< source
->stream_count
; ++i
)
537 source
->streams
[i
] = create_test_stream(i
, &source
->IMFMediaSource_iface
);
539 return &source
->IMFMediaSource_iface
;
542 static IMFByteStream
*get_resource_stream(const char *name
)
544 IMFByteStream
*bytestream
;
551 res
= FindResourceA(NULL
, name
, (const char *)RT_RCDATA
);
552 ok(res
!= 0, "Resource %s wasn't found.\n", name
);
554 ptr
= LockResource(LoadResource(GetModuleHandleA(NULL
), res
));
556 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
557 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
559 hr
= IStream_Write(stream
, ptr
, SizeofResource(GetModuleHandleA(NULL
), res
), &written
);
560 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
562 hr
= pMFCreateMFByteStreamOnStream(stream
, &bytestream
);
563 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
564 IStream_Release(stream
);
569 static void test_factory(void)
571 IMFReadWriteClassFactory
*factory
, *factory2
;
576 hr
= CoCreateInstance(&CLSID_MFReadWriteClassFactory
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IMFReadWriteClassFactory
,
578 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
580 hr
= CoCreateInstance(&CLSID_MFReadWriteClassFactory
, (IUnknown
*)factory
, CLSCTX_INPROC_SERVER
, &IID_IMFReadWriteClassFactory
,
582 ok(hr
== CLASS_E_NOAGGREGATION
, "Unexpected hr %#lx.\n", hr
);
584 IMFReadWriteClassFactory_Release(factory
);
589 struct async_callback
591 IMFSourceReaderCallback IMFSourceReaderCallback_iface
;
596 static struct async_callback
*impl_from_IMFSourceReaderCallback(IMFSourceReaderCallback
*iface
)
598 return CONTAINING_RECORD(iface
, struct async_callback
, IMFSourceReaderCallback_iface
);
601 static HRESULT WINAPI
async_callback_QueryInterface(IMFSourceReaderCallback
*iface
, REFIID riid
, void **out
)
603 if (IsEqualIID(riid
, &IID_IMFSourceReaderCallback
) ||
604 IsEqualIID(riid
, &IID_IUnknown
))
607 IMFSourceReaderCallback_AddRef(iface
);
612 return E_NOINTERFACE
;
615 static ULONG WINAPI
async_callback_AddRef(IMFSourceReaderCallback
*iface
)
617 struct async_callback
*callback
= impl_from_IMFSourceReaderCallback(iface
);
618 return InterlockedIncrement(&callback
->refcount
);
621 static ULONG WINAPI
async_callback_Release(IMFSourceReaderCallback
*iface
)
623 struct async_callback
*callback
= impl_from_IMFSourceReaderCallback(iface
);
624 ULONG refcount
= InterlockedDecrement(&callback
->refcount
);
632 static HRESULT WINAPI
async_callback_OnReadSample(IMFSourceReaderCallback
*iface
, HRESULT hr
, DWORD stream_index
,
633 DWORD stream_flags
, LONGLONG timestamp
, IMFSample
*sample
)
635 ok(0, "Unexpected call.\n");
639 static HRESULT WINAPI
async_callback_OnFlush(IMFSourceReaderCallback
*iface
, DWORD stream_index
)
641 ok(0, "Unexpected call.\n");
645 static HRESULT WINAPI
async_callback_OnEvent(IMFSourceReaderCallback
*iface
, DWORD stream_index
, IMFMediaEvent
*event
)
647 ok(0, "Unexpected call.\n");
651 static const IMFSourceReaderCallbackVtbl async_callback_vtbl
=
653 async_callback_QueryInterface
,
654 async_callback_AddRef
,
655 async_callback_Release
,
656 async_callback_OnReadSample
,
657 async_callback_OnFlush
,
658 async_callback_OnEvent
,
661 static struct async_callback
*create_async_callback(void)
663 struct async_callback
*callback
;
665 callback
= calloc(1, sizeof(*callback
));
666 callback
->IMFSourceReaderCallback_iface
.lpVtbl
= &async_callback_vtbl
;
667 callback
->refcount
= 1;
672 static void test_source_reader(const char *filename
, bool video
)
674 IMFMediaType
*mediatype
, *mediatype2
;
675 DWORD stream_flags
, actual_index
;
676 struct async_callback
*callback
;
677 IMFAttributes
*attributes
;
678 IMFSourceReader
*reader
;
679 IMFMediaSource
*source
;
680 IMFByteStream
*stream
;
687 if (!pMFCreateMFByteStreamOnStream
)
689 win_skip("MFCreateMFByteStreamOnStream() not found\n");
693 winetest_push_context("%s", filename
);
695 stream
= get_resource_stream(filename
);
697 /* Create the source reader with video processing enabled. This allows
698 * outputting RGB formats. */
699 MFCreateAttributes(&attributes
, 1);
700 hr
= IMFAttributes_SetUINT32(attributes
, &MF_SOURCE_READER_ENABLE_VIDEO_PROCESSING
, TRUE
);
701 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
703 hr
= MFCreateSourceReaderFromByteStream(stream
, attributes
, &reader
);
706 skip("MFCreateSourceReaderFromByteStream() failed, is G-Streamer missing?\n");
707 IMFByteStream_Release(stream
);
708 IMFAttributes_Release(attributes
);
709 winetest_pop_context();
712 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
714 IMFAttributes_Release(attributes
);
716 /* Access underlying media source object. */
717 hr
= IMFSourceReader_GetServiceForStream(reader
, MF_SOURCE_READER_MEDIASOURCE
, &GUID_NULL
, &IID_IMFMediaSource
,
719 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
720 IMFMediaSource_Release(source
);
722 /* Stream selection. */
724 hr
= IMFSourceReader_GetStreamSelection(reader
, MF_SOURCE_READER_FIRST_VIDEO_STREAM
, &selected
);
727 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
728 ok(selected
, "Unexpected selection.\n");
732 ok(hr
== MF_E_INVALIDSTREAMNUMBER
, "Unexpected hr %#lx.\n", hr
);
735 hr
= IMFSourceReader_GetStreamSelection(reader
, 100, &selected
);
736 ok(hr
== MF_E_INVALIDSTREAMNUMBER
, "Unexpected hr %#lx.\n", hr
);
739 hr
= IMFSourceReader_GetStreamSelection(reader
, MF_SOURCE_READER_FIRST_AUDIO_STREAM
, &selected
);
740 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
741 ok(selected
, "Unexpected selection.\n");
744 hr
= IMFSourceReader_GetStreamSelection(reader
, 0, &selected
);
745 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
746 ok(selected
, "Unexpected selection.\n");
748 hr
= IMFSourceReader_SetStreamSelection(reader
, MF_SOURCE_READER_FIRST_VIDEO_STREAM
, TRUE
);
749 ok(hr
== (video
? S_OK
: MF_E_INVALIDSTREAMNUMBER
), "Unexpected hr %#lx.\n", hr
);
751 hr
= IMFSourceReader_SetStreamSelection(reader
, 100, TRUE
);
752 ok(hr
== MF_E_INVALIDSTREAMNUMBER
, "Unexpected hr %#lx.\n", hr
);
754 hr
= IMFSourceReader_SetStreamSelection(reader
, MF_SOURCE_READER_FIRST_AUDIO_STREAM
, FALSE
);
755 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
758 hr
= IMFSourceReader_GetStreamSelection(reader
, MF_SOURCE_READER_FIRST_AUDIO_STREAM
, &selected
);
759 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
760 ok(!selected
, "Unexpected selection.\n");
762 hr
= IMFSourceReader_SetStreamSelection(reader
, MF_SOURCE_READER_ALL_STREAMS
, TRUE
);
763 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
766 hr
= IMFSourceReader_GetStreamSelection(reader
, MF_SOURCE_READER_FIRST_AUDIO_STREAM
, &selected
);
767 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
768 ok(selected
, "Unexpected selection.\n");
770 /* Native media type. */
771 hr
= IMFSourceReader_GetNativeMediaType(reader
, MF_SOURCE_READER_FIRST_VIDEO_STREAM
, 0, &mediatype
);
774 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
775 hr
= IMFSourceReader_GetNativeMediaType(reader
, MF_SOURCE_READER_FIRST_VIDEO_STREAM
, 0, &mediatype2
);
776 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
777 ok(mediatype
!= mediatype2
, "Unexpected media type instance.\n");
778 IMFMediaType_Release(mediatype2
);
779 IMFMediaType_Release(mediatype
);
783 ok(hr
== MF_E_INVALIDSTREAMNUMBER
, "Unexpected hr %#lx.\n", hr
);
786 hr
= IMFSourceReader_GetNativeMediaType(reader
, 100, 0, &mediatype
);
787 ok(hr
== MF_E_INVALIDSTREAMNUMBER
, "Unexpected hr %#lx.\n", hr
);
789 hr
= IMFSourceReader_GetNativeMediaType(reader
, MF_SOURCE_READER_FIRST_AUDIO_STREAM
, 0, &mediatype
);
790 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
791 hr
= IMFSourceReader_GetNativeMediaType(reader
, MF_SOURCE_READER_FIRST_AUDIO_STREAM
, 0, &mediatype2
);
792 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
793 ok(mediatype
!= mediatype2
, "Unexpected media type instance.\n");
794 IMFMediaType_Release(mediatype2
);
795 IMFMediaType_Release(mediatype
);
797 /* MF_SOURCE_READER_CURRENT_TYPE_INDEX is Win8+ */
798 hr
= IMFSourceReader_GetNativeMediaType(reader
, MF_SOURCE_READER_FIRST_AUDIO_STREAM
,
799 MF_SOURCE_READER_CURRENT_TYPE_INDEX
, &mediatype
);
800 ok(hr
== S_OK
|| broken(hr
== MF_E_NO_MORE_TYPES
), "Unexpected hr %#lx.\n", hr
);
802 IMFMediaType_Release(mediatype
);
804 /* Current media type. */
805 hr
= IMFSourceReader_GetCurrentMediaType(reader
, MF_SOURCE_READER_FIRST_VIDEO_STREAM
, &mediatype
);
812 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
814 hr
= IMFMediaType_GetGUID(mediatype
, &MF_MT_SUBTYPE
, &subtype
);
815 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
816 todo_wine
ok(IsEqualGUID(&subtype
, &MFVideoFormat_H264
), "Got subtype %s.\n", debugstr_guid(&subtype
));
818 hr
= IMFMediaType_GetUINT64(mediatype
, &MF_MT_FRAME_SIZE
, &framesize
);
819 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
820 ok(framesize
== ((UINT64
)160 << 32 | 120), "Got frame size %ux%u.\n",
821 (unsigned int)(framesize
>> 32), (unsigned int)framesize
);
823 hr
= IMFMediaType_GetUINT32(mediatype
, &MF_MT_DEFAULT_STRIDE
, &stride
);
824 todo_wine
ok(hr
== MF_E_ATTRIBUTENOTFOUND
, "Unexpected hr %#lx.\n", hr
);
826 IMFMediaType_Release(mediatype
);
828 /* Set the type to a YUV format. */
830 hr
= MFCreateMediaType(&mediatype
);
831 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
832 hr
= IMFMediaType_SetGUID(mediatype
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
);
833 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
834 hr
= IMFMediaType_SetGUID(mediatype
, &MF_MT_SUBTYPE
, &MFVideoFormat_NV12
);
835 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
836 hr
= IMFSourceReader_SetCurrentMediaType(reader
, MF_SOURCE_READER_FIRST_VIDEO_STREAM
, NULL
, mediatype
);
837 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
838 IMFMediaType_Release(mediatype
);
840 hr
= IMFSourceReader_GetCurrentMediaType(reader
, MF_SOURCE_READER_FIRST_VIDEO_STREAM
, &mediatype
);
841 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
843 hr
= IMFMediaType_GetGUID(mediatype
, &MF_MT_SUBTYPE
, &subtype
);
844 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
845 ok(IsEqualGUID(&subtype
, &MFVideoFormat_NV12
), "Got subtype %s.\n", debugstr_guid(&subtype
));
847 hr
= IMFMediaType_GetUINT32(mediatype
, &MF_MT_DEFAULT_STRIDE
, &stride
);
848 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
849 ok(stride
== 160, "Got stride %u.\n", stride
);
851 IMFMediaType_Release(mediatype
);
853 /* Set the type to an RGB format. */
855 hr
= MFCreateMediaType(&mediatype
);
856 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
857 hr
= IMFMediaType_SetGUID(mediatype
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Video
);
858 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
859 hr
= IMFMediaType_SetGUID(mediatype
, &MF_MT_SUBTYPE
, &MFVideoFormat_RGB32
);
860 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
861 hr
= IMFSourceReader_SetCurrentMediaType(reader
, MF_SOURCE_READER_FIRST_VIDEO_STREAM
, NULL
, mediatype
);
862 todo_wine
ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
863 IMFMediaType_Release(mediatype
);
867 hr
= IMFSourceReader_GetCurrentMediaType(reader
, MF_SOURCE_READER_FIRST_VIDEO_STREAM
, &mediatype
);
868 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
870 hr
= IMFMediaType_GetGUID(mediatype
, &MF_MT_SUBTYPE
, &subtype
);
871 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
872 ok(IsEqualGUID(&subtype
, &MFVideoFormat_RGB32
), "Got subtype %s.\n", debugstr_guid(&subtype
));
874 hr
= IMFMediaType_GetUINT32(mediatype
, &MF_MT_DEFAULT_STRIDE
, &stride
);
875 todo_wine
ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
876 todo_wine
ok(stride
== 160 * 4, "Got stride %u.\n", stride
);
878 IMFMediaType_Release(mediatype
);
883 ok(hr
== MF_E_INVALIDSTREAMNUMBER
, "Unexpected hr %#lx.\n", hr
);
886 hr
= IMFSourceReader_GetCurrentMediaType(reader
, 100, &mediatype
);
887 ok(hr
== MF_E_INVALIDSTREAMNUMBER
, "Unexpected hr %#lx.\n", hr
);
889 hr
= IMFSourceReader_GetCurrentMediaType(reader
, MF_SOURCE_READER_FIRST_AUDIO_STREAM
, &mediatype
);
890 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
891 IMFMediaType_Release(mediatype
);
893 hr
= IMFSourceReader_GetCurrentMediaType(reader
, 0, &mediatype
);
894 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
895 IMFMediaType_Release(mediatype
);
899 hr
= IMFSourceReader_ReadSample(reader
, MF_SOURCE_READER_FIRST_AUDIO_STREAM
, 0, &actual_index
, &stream_flags
,
900 ×tamp
, &sample
);
901 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
902 todo_wine_if (video
) ok(!actual_index
, "Unexpected stream index %lu.\n", actual_index
);
903 ok(!(stream_flags
& ~MF_SOURCE_READERF_ENDOFSTREAM
), "Unexpected stream flags %#lx.\n", stream_flags
);
905 if (stream_flags
& MF_SOURCE_READERF_ENDOFSTREAM
)
907 ok(!sample
, "Unexpected sample object.\n");
911 IMFSample_Release(sample
);
914 hr
= IMFSourceReader_ReadSample(reader
, MF_SOURCE_READER_FIRST_VIDEO_STREAM
, 0, &actual_index
, &stream_flags
,
915 ×tamp
, &sample
);
920 hr
= IMFSourceReader_ReadSample(reader
, MF_SOURCE_READER_FIRST_VIDEO_STREAM
,
921 0, &actual_index
, &stream_flags
, ×tamp
, &sample
);
922 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
923 todo_wine
ok(actual_index
== 1, "Unexpected stream index %lu.\n", actual_index
);
924 ok(!(stream_flags
& ~MF_SOURCE_READERF_ENDOFSTREAM
), "Unexpected stream flags %#lx.\n", stream_flags
);
926 if (stream_flags
& MF_SOURCE_READERF_ENDOFSTREAM
)
928 ok(!sample
, "Unexpected sample object.\n");
932 IMFSample_Release(sample
);
937 hr
= IMFSourceReader_ReadSample(reader
, MF_SOURCE_READER_FIRST_VIDEO_STREAM
,
938 0, &actual_index
, &stream_flags
, ×tamp
, &sample
);
939 ok(hr
== MF_E_INVALIDSTREAMNUMBER
, "Unexpected hr %#lx.\n", hr
);
940 ok(actual_index
== MF_SOURCE_READER_FIRST_VIDEO_STREAM
, "Unexpected stream index %lu.\n", actual_index
);
941 ok(stream_flags
== MF_SOURCE_READERF_ERROR
, "Unexpected stream flags %#lx.\n", stream_flags
);
943 hr
= IMFSourceReader_ReadSample(reader
, MF_SOURCE_READER_FIRST_VIDEO_STREAM
,
944 0, NULL
, &stream_flags
, ×tamp
, &sample
);
945 ok(hr
== MF_E_INVALIDSTREAMNUMBER
, "Unexpected hr %#lx.\n", hr
);
948 hr
= IMFSourceReader_ReadSample(reader
, MF_SOURCE_READER_FIRST_VIDEO_STREAM
, 0, NULL
, NULL
, ×tamp
, &sample
);
949 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
951 hr
= IMFSourceReader_ReadSample(reader
, MF_SOURCE_READER_FIRST_AUDIO_STREAM
, MF_SOURCE_READER_CONTROLF_DRAIN
,
952 &actual_index
, &stream_flags
, ×tamp
, &sample
);
953 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
954 todo_wine_if (video
) ok(actual_index
== 0, "Unexpected stream index %lu.\n", actual_index
);
955 ok(stream_flags
== MF_SOURCE_READERF_ENDOFSTREAM
, "Unexpected stream flags %#lx.\n", stream_flags
);
956 ok(!sample
, "Unexpected sample object.\n");
958 hr
= IMFSourceReader_ReadSample(reader
, MF_SOURCE_READER_FIRST_AUDIO_STREAM
, MF_SOURCE_READER_CONTROLF_DRAIN
,
959 &actual_index
, &stream_flags
, ×tamp
, NULL
);
960 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
962 hr
= IMFSourceReader_ReadSample(reader
, MF_SOURCE_READER_FIRST_AUDIO_STREAM
, MF_SOURCE_READER_CONTROLF_DRAIN
,
963 &actual_index
, NULL
, ×tamp
, &sample
);
964 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
966 hr
= IMFSourceReader_ReadSample(reader
, MF_SOURCE_READER_FIRST_AUDIO_STREAM
, MF_SOURCE_READER_CONTROLF_DRAIN
,
967 NULL
, &stream_flags
, ×tamp
, &sample
);
968 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
969 ok(stream_flags
== MF_SOURCE_READERF_ENDOFSTREAM
, "Unexpected stream flags %#lx.\n", stream_flags
);
970 ok(!sample
, "Unexpected sample object.\n");
972 hr
= IMFSourceReader_ReadSample(reader
, MF_SOURCE_READER_FIRST_AUDIO_STREAM
, MF_SOURCE_READER_CONTROLF_DRAIN
,
973 &actual_index
, &stream_flags
, NULL
, &sample
);
974 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
975 todo_wine_if (video
) ok(!actual_index
, "Unexpected stream index %lu.\n", actual_index
);
976 ok(stream_flags
== MF_SOURCE_READERF_ENDOFSTREAM
, "Unexpected stream flags %#lx.\n", stream_flags
);
977 ok(!sample
, "Unexpected sample object.\n");
979 hr
= IMFSourceReader_ReadSample(reader
, MF_SOURCE_READER_ANY_STREAM
, MF_SOURCE_READER_CONTROLF_DRAIN
,
980 &actual_index
, &stream_flags
, NULL
, &sample
);
981 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
982 ok(actual_index
== 0, "Unexpected stream index %lu.\n", actual_index
);
983 ok(stream_flags
== MF_SOURCE_READERF_ENDOFSTREAM
, "Unexpected stream flags %#lx.\n", stream_flags
);
984 ok(!sample
, "Unexpected sample object.\n");
987 hr
= IMFSourceReader_Flush(reader
, MF_SOURCE_READER_FIRST_VIDEO_STREAM
);
988 ok(hr
== (video
? S_OK
: MF_E_INVALIDSTREAMNUMBER
), "Unexpected hr %#lx.\n", hr
);
990 hr
= IMFSourceReader_Flush(reader
, 100);
991 ok(hr
== MF_E_INVALIDSTREAMNUMBER
, "Unexpected hr %#lx.\n", hr
);
993 hr
= IMFSourceReader_Flush(reader
, MF_SOURCE_READER_FIRST_AUDIO_STREAM
);
994 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
996 hr
= IMFSourceReader_Flush(reader
, MF_SOURCE_READER_FIRST_AUDIO_STREAM
);
997 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
999 hr
= IMFSourceReader_Flush(reader
, MF_SOURCE_READER_ALL_STREAMS
);
1000 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1002 refcount
= IMFSourceReader_Release(reader
);
1003 ok(!refcount
, "Unexpected refcount %lu.\n", refcount
);
1006 callback
= create_async_callback();
1008 hr
= MFCreateAttributes(&attributes
, 1);
1009 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1011 hr
= IMFAttributes_SetUnknown(attributes
, &MF_SOURCE_READER_ASYNC_CALLBACK
,
1012 (IUnknown
*)&callback
->IMFSourceReaderCallback_iface
);
1013 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1014 IMFSourceReaderCallback_Release(&callback
->IMFSourceReaderCallback_iface
);
1016 refcount
= get_refcount(attributes
);
1017 hr
= MFCreateSourceReaderFromByteStream(stream
, attributes
, &reader
);
1018 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1019 ok(get_refcount(attributes
) > refcount
, "Unexpected refcount.\n");
1020 IMFAttributes_Release(attributes
);
1021 IMFSourceReader_Release(reader
);
1023 IMFByteStream_Release(stream
);
1025 winetest_pop_context();
1028 static void test_source_reader_from_media_source(void)
1030 static const DWORD expected_sample_order
[10] = {0, 0, 1, 1, 0, 0, 0, 0, 1, 0};
1032 struct async_callback
*callback
;
1033 IMFSourceReader
*reader
;
1034 IMFMediaSource
*source
;
1035 struct test_source
*test_source
;
1036 IMFMediaType
*media_type
;
1038 DWORD actual_index
, stream_flags
;
1041 IMFAttributes
*attributes
;
1046 source
= create_test_source(3);
1047 ok(!!source
, "Failed to create test source.\n");
1049 hr
= MFCreateSourceReaderFromMediaSource(source
, NULL
, &reader
);
1050 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1052 /* MF_SOURCE_READER_ANY_STREAM */
1053 hr
= IMFSourceReader_SetStreamSelection(reader
, 0, FALSE
);
1054 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1056 hr
= IMFSourceReader_SetStreamSelection(reader
, 1, TRUE
);
1057 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1060 pos
.hVal
.QuadPart
= 0;
1061 hr
= IMFSourceReader_SetCurrentPosition(reader
, &GUID_NULL
, &pos
);
1062 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1064 hr
= IMFSourceReader_ReadSample(reader
, MF_SOURCE_READER_ANY_STREAM
, 0, &actual_index
, &stream_flags
,
1065 ×tamp
, &sample
);
1066 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1067 ok(actual_index
== 1, "Unexpected stream index %lu\n", actual_index
);
1068 ok(!stream_flags
, "Unexpected stream flags %#lx.\n", stream_flags
);
1069 ok(timestamp
== 123, "Unexpected timestamp.\n");
1070 ok(!!sample
, "Expected sample object.\n");
1071 IMFSample_Release(sample
);
1073 hr
= IMFSourceReader_SetStreamSelection(reader
, 0, TRUE
);
1074 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1076 hr
= IMFSourceReader_SetStreamSelection(reader
, 2, TRUE
);
1077 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1079 for (i
= 0; i
< TEST_SOURCE_NUM_STREAMS
+ 1; ++i
)
1081 hr
= IMFSourceReader_ReadSample(reader
, MF_SOURCE_READER_ANY_STREAM
, 0, &actual_index
, &stream_flags
,
1082 ×tamp
, &sample
);
1083 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1084 ok(actual_index
== i
% TEST_SOURCE_NUM_STREAMS
, "%d: Unexpected stream index %lu.\n", i
, actual_index
);
1085 ok(!stream_flags
, "Unexpected stream flags %#lx.\n", stream_flags
);
1086 ok(timestamp
== 123, "Unexpected timestamp.\n");
1087 ok(!!sample
, "Expected sample object.\n");
1088 IMFSample_Release(sample
);
1091 hr
= IMFSourceReader_SetStreamSelection(reader
, 0, FALSE
);
1092 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1094 hr
= IMFSourceReader_SetStreamSelection(reader
, 0, TRUE
);
1095 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1097 for (i
= 0; i
< TEST_SOURCE_NUM_STREAMS
+ 1; ++i
)
1099 hr
= IMFSourceReader_ReadSample(reader
, MF_SOURCE_READER_ANY_STREAM
, 0, &actual_index
, &stream_flags
,
1100 ×tamp
, &sample
);
1101 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1102 ok(actual_index
== i
% TEST_SOURCE_NUM_STREAMS
, "%d: Unexpected stream index %lu.\n", i
, actual_index
);
1103 ok(!stream_flags
, "Unexpected stream flags %#lx.\n", stream_flags
);
1104 ok(timestamp
== 123, "Unexpected timestamp.\n");
1105 ok(!!sample
, "Expected sample object.\n");
1106 IMFSample_Release(sample
);
1109 hr
= IMFSourceReader_ReadSample(reader
, MF_SOURCE_READER_ANY_STREAM
, 0, &actual_index
, &stream_flags
,
1110 ×tamp
, &sample
);
1111 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1112 ok(!stream_flags
, "Unexpected stream flags %#lx.\n", stream_flags
);
1113 ok(timestamp
== 123, "Unexpected timestamp.\n");
1114 ok(!!sample
, "Expected sample object.\n");
1116 /* Once the last read sample of all streams has the same timestamp value, the reader will
1117 continue reading from the first stream until its timestamp increases. */
1118 ok(!actual_index
, "%d: Unexpected stream index %lu.\n", TEST_SOURCE_NUM_STREAMS
+ 1, actual_index
);
1120 IMFSample_Release(sample
);
1122 IMFSourceReader_Release(reader
);
1123 IMFMediaSource_Release(source
);
1125 source
= create_test_source(1);
1126 ok(!!source
, "Failed to create test source.\n");
1128 hr
= MFCreateSourceReaderFromMediaSource(source
, NULL
, &reader
);
1129 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1131 /* MF_SOURCE_READER_ANY_STREAM with a single stream */
1132 hr
= IMFSourceReader_SetStreamSelection(reader
, 0, TRUE
);
1133 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1136 pos
.hVal
.QuadPart
= 0;
1137 hr
= IMFSourceReader_SetCurrentPosition(reader
, &GUID_NULL
, &pos
);
1138 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1140 hr
= IMFSourceReader_ReadSample(reader
, MF_SOURCE_READER_ANY_STREAM
, 0, &actual_index
, &stream_flags
,
1141 ×tamp
, &sample
);
1142 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1143 ok(!actual_index
, "Unexpected stream index %lu.\n", actual_index
);
1144 ok(!stream_flags
, "Unexpected stream flags %#lx.\n", stream_flags
);
1145 ok(timestamp
== 123, "Unexpected timestamp.\n");
1146 ok(!!sample
, "Expected sample object.\n");
1147 IMFSample_Release(sample
);
1149 hr
= IMFSourceReader_ReadSample(reader
, MF_SOURCE_READER_ANY_STREAM
, 0, &actual_index
, &stream_flags
,
1150 ×tamp
, &sample
);
1151 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1152 ok(!actual_index
, "Unexpected stream index %lu\n", actual_index
);
1153 ok(!stream_flags
, "Unexpected stream flags %#lx.\n", stream_flags
);
1154 ok(timestamp
== 123, "Unexpected timestamp.\n");
1155 ok(!!sample
, "Expected sample object.\n");
1156 IMFSample_Release(sample
);
1158 IMFSourceReader_Release(reader
);
1159 IMFMediaSource_Release(source
);
1161 /* Request from stream 0. */
1162 source
= create_test_source(3);
1163 ok(!!source
, "Failed to create test source.\n");
1165 hr
= MFCreateSourceReaderFromMediaSource(source
, NULL
, &reader
);
1166 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1168 hr
= IMFSourceReader_SetStreamSelection(reader
, 0, TRUE
);
1169 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1171 hr
= IMFSourceReader_ReadSample(reader
, 0, 0, &actual_index
, &stream_flags
, ×tamp
, &sample
);
1172 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1173 ok(!actual_index
, "Unexpected stream index %lu.\n", actual_index
);
1174 ok(!stream_flags
, "Unexpected stream flags %#lx.\n", stream_flags
);
1175 ok(timestamp
== 123, "Unexpected timestamp.\n");
1176 ok(!!sample
, "Expected sample object.\n");
1177 IMFSample_Release(sample
);
1179 /* Request from deselected stream. */
1180 hr
= IMFSourceReader_SetStreamSelection(reader
, 1, FALSE
);
1181 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1185 hr
= IMFSourceReader_ReadSample(reader
, 1, 0, &actual_index
, &stream_flags
, ×tamp
, &sample
);
1186 ok(hr
== MF_E_INVALIDREQUEST
, "Unexpected hr %#lx.\n", hr
);
1187 ok(actual_index
== 1, "Unexpected stream index %lu.\n", actual_index
);
1188 ok(stream_flags
== MF_SOURCE_READERF_ERROR
, "Unexpected stream flags %#lx.\n", stream_flags
);
1189 ok(timestamp
== 0, "Unexpected timestamp.\n");
1190 ok(!sample
, "Expected sample object.\n");
1192 IMFSourceReader_Release(reader
);
1193 IMFMediaSource_Release(source
);
1195 /* Request a non-native bit depth. */
1196 source
= create_test_source(1);
1197 ok(!!source
, "Failed to create test source.\n");
1199 hr
= MFCreateSourceReaderFromMediaSource(source
, NULL
, &reader
);
1200 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1202 hr
= MFCreateMediaType(&media_type
);
1203 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1204 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Audio
);
1205 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1206 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, &MFAudioFormat_PCM
);
1207 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1208 hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, 16);
1209 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1211 hr
= IMFSourceReader_SetCurrentMediaType(reader
, 0, NULL
, media_type
);
1212 ok(hr
== MF_E_TOPO_CODEC_NOT_FOUND
, "Unexpected hr %#lx.\n", hr
);
1214 IMFMediaType_Release(media_type
);
1216 hr
= MFCreateMediaType(&media_type
);
1217 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1218 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_MAJOR_TYPE
, &MFMediaType_Audio
);
1219 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1220 hr
= IMFMediaType_SetGUID(media_type
, &MF_MT_SUBTYPE
, &MFAudioFormat_PCM
);
1221 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1222 hr
= IMFMediaType_SetUINT32(media_type
, &MF_MT_AUDIO_BITS_PER_SAMPLE
, 32);
1223 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1225 hr
= IMFSourceReader_SetCurrentMediaType(reader
, 0, NULL
, media_type
);
1226 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1228 hr
= IMFSourceReader_SetStreamSelection(reader
, 0, TRUE
);
1229 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1231 hr
= IMFSourceReader_ReadSample(reader
, 0, 0, &actual_index
, &stream_flags
, ×tamp
, &sample
);
1232 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1233 ok(!actual_index
, "Unexpected stream index %lu\n", actual_index
);
1234 ok(!stream_flags
, "Unexpected stream flags %#lx.\n", stream_flags
);
1235 ok(timestamp
== 123, "Unexpected timestamp.\n");
1236 ok(!!sample
, "Expected sample object.\n");
1237 IMFSample_Release(sample
);
1239 IMFMediaType_Release(media_type
);
1240 IMFSourceReader_Release(reader
);
1241 IMFMediaSource_Release(source
);
1244 source
= create_test_source(3);
1245 ok(!!source
, "Failed to create test source.\n");
1247 callback
= create_async_callback();
1249 hr
= MFCreateAttributes(&attributes
, 1);
1250 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1252 hr
= IMFAttributes_SetUnknown(attributes
, &MF_SOURCE_READER_ASYNC_CALLBACK
,
1253 (IUnknown
*)&callback
->IMFSourceReaderCallback_iface
);
1254 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1255 IMFSourceReaderCallback_Release(&callback
->IMFSourceReaderCallback_iface
);
1257 refcount
= get_refcount(attributes
);
1258 hr
= MFCreateSourceReaderFromMediaSource(source
, attributes
, &reader
);
1259 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1260 ok(get_refcount(attributes
) > refcount
, "Unexpected refcount.\n");
1262 hr
= IMFSourceReader_SetStreamSelection(reader
, 0, TRUE
);
1263 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1265 /* Return values are delivered to callback only. */
1266 hr
= IMFSourceReader_ReadSample(reader
, 0, 0, &actual_index
, &stream_flags
, ×tamp
, &sample
);
1267 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
1269 hr
= IMFSourceReader_ReadSample(reader
, 0, 0, NULL
, &stream_flags
, ×tamp
, &sample
);
1270 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
1272 hr
= IMFSourceReader_ReadSample(reader
, 0, 0, NULL
, NULL
, ×tamp
, &sample
);
1273 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
1275 hr
= IMFSourceReader_ReadSample(reader
, 0, 0, NULL
, NULL
, NULL
, &sample
);
1276 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
1278 /* Flush() arguments validation. */
1279 hr
= IMFSourceReader_Flush(reader
, 123);
1280 ok(hr
== MF_E_INVALIDSTREAMNUMBER
, "Unexpected hr %#lx.\n", hr
);
1282 hr
= IMFSourceReader_ReadSample(reader
, 0, 0, NULL
, NULL
, NULL
, NULL
);
1283 ok(hr
== MF_E_NOTACCEPTING
, "Unexpected hr %#lx.\n", hr
);
1285 IMFSourceReader_Release(reader
);
1286 IMFMediaSource_Release(source
);
1288 /* RequestSample failure. */
1289 source
= create_test_source(3);
1290 ok(!!source
, "Failed to create test source.\n");
1292 fail_request_sample
= TRUE
;
1294 hr
= MFCreateSourceReaderFromMediaSource(source
, NULL
, &reader
);
1295 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1297 hr
= IMFSourceReader_SetStreamSelection(reader
, 0, TRUE
);
1298 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1300 hr
= IMFSourceReader_ReadSample(reader
, 0, 0, &actual_index
, &stream_flags
, ×tamp
, &sample
);
1301 ok(hr
== E_NOTIMPL
, "Unexpected hr %#lx.\n", hr
);
1305 hr
= IMFSourceReader_ReadSample(reader
, MF_SOURCE_READER_FIRST_AUDIO_STREAM
, 0, &actual_index
, &stream_flags
,
1306 ×tamp
, &sample
);
1307 ok(hr
== E_NOTIMPL
, "Unexpected hr %#lx.\n", hr
);
1308 ok(!actual_index
, "Unexpected index %lu.\n", actual_index
);
1309 ok(stream_flags
== MF_SOURCE_READERF_ERROR
, "Unexpected flags %#lx.\n", stream_flags
);
1313 hr
= IMFSourceReader_ReadSample(reader
, MF_SOURCE_READER_FIRST_AUDIO_STREAM
, 0, &actual_index
, &stream_flags
,
1314 ×tamp
, &sample
);
1315 ok(hr
== E_NOTIMPL
, "Unexpected hr %#lx.\n", hr
);
1316 ok(!actual_index
, "Unexpected index %lu.\n", actual_index
);
1317 ok(stream_flags
== MF_SOURCE_READERF_ERROR
, "Unexpected flags %#lx.\n", stream_flags
);
1321 hr
= IMFSourceReader_ReadSample(reader
, 0, 0, &actual_index
, &stream_flags
, ×tamp
, &sample
);
1322 ok(hr
== E_NOTIMPL
, "Unexpected hr %#lx.\n", hr
);
1323 ok(!actual_index
, "Unexpected index %lu.\n", actual_index
);
1324 ok(stream_flags
== MF_SOURCE_READERF_ERROR
, "Unexpected flags %#lx.\n", stream_flags
);
1326 IMFSourceReader_Release(reader
);
1327 IMFMediaSource_Release(source
);
1329 fail_request_sample
= FALSE
;
1331 /* MF_SOURCE_READER_ANY_STREAM with streams of different sample sizes */
1332 source
= create_test_source(2);
1333 ok(!!source
, "Failed to create test source.\n");
1335 test_source
= impl_from_IMFMediaSource(source
);
1336 test_source
->streams
[0]->sample_duration
= 100000;
1337 test_source
->streams
[1]->sample_duration
= 400000;
1339 hr
= MFCreateSourceReaderFromMediaSource(source
, NULL
, &reader
);
1340 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1342 hr
= IMFSourceReader_SetStreamSelection(reader
, 0, TRUE
);
1343 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1345 hr
= IMFSourceReader_SetStreamSelection(reader
, 1, TRUE
);
1346 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1348 /* The source reader picks the stream whose last sample had the lower timestamp */
1349 for (i
= 0; i
< ARRAY_SIZE(expected_sample_order
); i
++)
1351 hr
= IMFSourceReader_ReadSample(reader
, MF_SOURCE_READER_ANY_STREAM
, 0, &actual_index
, &stream_flags
, ×tamp
, &sample
);
1352 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1353 ok(!stream_flags
, "Unexpected stream flags %#lx.\n", stream_flags
);
1354 ok(!!sample
, "Expected sample object.\n");
1355 ok (actual_index
== expected_sample_order
[i
], "Got sample %u from unexpected stream %lu, expected %lu.\n",
1356 i
, actual_index
, expected_sample_order
[i
]);
1357 IMFSample_Release(sample
);
1360 IMFSourceReader_Release(reader
);
1361 IMFMediaSource_Release(source
);
1364 static void test_reader_d3d9(void)
1366 IDirect3DDeviceManager9
*d3d9_manager
;
1367 IDirect3DDevice9
*d3d9_device
;
1368 IMFAttributes
*attributes
;
1369 IMFSourceReader
*reader
;
1370 IMFMediaSource
*source
;
1377 window
= create_window();
1378 d3d9
= Direct3DCreate9(D3D_SDK_VERSION
);
1379 ok(!!d3d9
, "Failed to create a D3D9 object.\n");
1380 if (!(d3d9_device
= create_d3d9_device(d3d9
, window
)))
1382 skip("Failed to create a D3D9 device, skipping tests.\n");
1386 hr
= DXVA2CreateDirect3DDeviceManager9(&token
, &d3d9_manager
);
1387 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1389 hr
= IDirect3DDeviceManager9_ResetDevice(d3d9_manager
, d3d9_device
, token
);
1390 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1392 source
= create_test_source(3);
1393 ok(!!source
, "Failed to create test source.\n");
1395 hr
= MFCreateAttributes(&attributes
, 1);
1396 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1398 hr
= IMFAttributes_SetUnknown(attributes
, &MF_SOURCE_READER_D3D_MANAGER
, (IUnknown
*)d3d9_manager
);
1399 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1401 hr
= MFCreateSourceReaderFromMediaSource(source
, attributes
, &reader
);
1402 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1404 IMFAttributes_Release(attributes
);
1406 IMFSourceReader_Release(reader
);
1408 refcount
= IDirect3DDeviceManager9_Release(d3d9_manager
);
1409 ok(!refcount
, "Unexpected refcount %lu.\n", refcount
);
1411 IDirect3DDevice9_Release(d3d9_device
);
1414 IDirect3D9_Release(d3d9
);
1415 DestroyWindow(window
);
1418 static void test_sink_writer_create(void)
1420 IMFSinkWriter
*writer
;
1423 hr
= MFCreateSinkWriterFromURL(NULL
, NULL
, NULL
, NULL
);
1424 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
1426 writer
= (void *)0xdeadbeef;
1427 hr
= MFCreateSinkWriterFromURL(NULL
, NULL
, NULL
, &writer
);
1428 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
1429 ok(!writer
, "Unexpected pointer %p.\n", writer
);
1431 hr
= MFCreateSinkWriterFromMediaSink(NULL
, NULL
, NULL
);
1432 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
1434 writer
= (void *)0xdeadbeef;
1435 hr
= MFCreateSinkWriterFromMediaSink(NULL
, NULL
, &writer
);
1436 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
1437 ok(!writer
, "Unexpected pointer %p.\n", writer
);
1440 static void test_sink_writer_mp4(void)
1442 WCHAR tmp_file
[MAX_PATH
];
1443 IMFSinkWriter
*writer
;
1444 IMFByteStream
*stream
;
1445 IMFAttributes
*attr
;
1449 GetTempPathW(ARRAY_SIZE(tmp_file
), tmp_file
);
1450 wcscat(tmp_file
, L
"tmp.mp4");
1452 hr
= MFCreateAttributes(&attr
, 1);
1453 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1454 hr
= IMFAttributes_SetGUID(attr
, &MF_TRANSCODE_CONTAINERTYPE
, &MFTranscodeContainerType_MPEG4
);
1455 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1456 hr
= MFCreateTempFile(MF_ACCESSMODE_READWRITE
, MF_OPENMODE_DELETE_IF_EXIST
, MF_FILEFLAGS_NONE
, &stream
);
1457 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1459 /* Test MFCreateSinkWriterFromURL. */
1460 writer
= (void *)0xdeadbeef;
1461 hr
= MFCreateSinkWriterFromURL(NULL
, NULL
, attr
, &writer
);
1462 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
1463 ok(!writer
, "Unexpected pointer %p.\n", writer
);
1465 writer
= (void *)0xdeadbeef;
1466 hr
= MFCreateSinkWriterFromURL(NULL
, stream
, NULL
, &writer
);
1467 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
1468 ok(!writer
, "Unexpected pointer %p.\n", writer
);
1470 hr
= MFCreateSinkWriterFromURL(NULL
, stream
, attr
, &writer
);
1471 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1473 IMFSinkWriter_Release(writer
);
1475 hr
= MFCreateSinkWriterFromURL(tmp_file
, NULL
, NULL
, &writer
);
1476 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1478 IMFSinkWriter_Release(writer
);
1480 hr
= MFCreateSinkWriterFromURL(tmp_file
, NULL
, attr
, &writer
);
1481 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1483 IMFSinkWriter_Release(writer
);
1485 hr
= MFCreateSinkWriterFromURL(tmp_file
, stream
, NULL
, &writer
);
1486 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1488 IMFSinkWriter_Release(writer
);
1490 hr
= MFCreateSinkWriterFromURL(tmp_file
, stream
, attr
, &writer
);
1491 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1493 /* Test GetServiceForStream. */
1494 sink
= (void *)0xdeadbeef;
1495 hr
= IMFSinkWriter_GetServiceForStream(writer
, MF_SINK_WRITER_MEDIASINK
,
1496 &GUID_NULL
, &IID_IMFMediaSink
, (void **)&sink
);
1498 ok(hr
== MF_E_UNSUPPORTED_SERVICE
, "Unexpected hr %#lx.\n", hr
);
1500 ok(!sink
, "Unexpected pointer %p.\n", sink
);
1502 DeleteFileW(tmp_file
);
1503 IMFSinkWriter_Release(writer
);
1504 IMFByteStream_Release(stream
);
1505 IMFAttributes_Release(attr
);
1508 static void test_interfaces(void)
1510 IMFSourceReader
*reader
;
1511 IMFMediaSource
*source
;
1515 source
= create_test_source(1);
1516 ok(!!source
, "Failed to create test source.\n");
1518 hr
= MFCreateSourceReaderFromMediaSource(source
, NULL
, &reader
);
1519 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1521 hr
= IMFSourceReader_QueryInterface(reader
, &IID_IMFSourceReaderEx
, (void **)&unk
);
1522 ok(hr
== S_OK
|| broken(hr
== E_NOINTERFACE
) /* Windows 7 and below.*/, "Unexpected hr %#lx.\n", hr
);
1524 IUnknown_Release(unk
);
1526 IMFSourceReader_Release(reader
);
1527 IMFMediaSource_Release(source
);
1534 hr
= MFStartup(MF_VERSION
, MFSTARTUP_FULL
);
1535 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
1541 test_source_reader("test.wav", false);
1542 test_source_reader("test.mp4", true);
1543 test_source_reader_from_media_source();
1545 test_sink_writer_create();
1546 test_sink_writer_mp4();
1549 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);