msxml4/tests: Copy namespaces as attributes tests.
[wine.git] / dlls / mfreadwrite / tests / mfplat.c
blobce74a451b52b5d6c9328c5a66c5e0a576498041e
1 /*
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
19 #include <stdarg.h>
20 #include <stdbool.h>
21 #include <string.h>
23 #define COBJMACROS
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "winreg.h"
30 #include "initguid.h"
31 #include "ole2.h"
33 DEFINE_GUID(GUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
35 #undef INITGUID
36 #include "guiddef.h"
37 #include "mfapi.h"
38 #include "mfidl.h"
39 #include "mferror.h"
40 #include "mfreadwrite.h"
41 #include "d3d9.h"
42 #include "dxva2api.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);
81 return 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);
92 #undef X
95 enum source_state
97 SOURCE_STOPPED = 0,
98 SOURCE_RUNNING,
101 struct test_media_stream
103 IMFMediaStream IMFMediaStream_iface;
104 LONG refcount;
105 IMFMediaSource *source;
106 IMFStreamDescriptor *sd;
107 IMFMediaEventQueue *event_queue;
108 BOOL is_new;
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))
123 *out = iface;
125 else
127 *out = NULL;
128 return E_NOINTERFACE;
131 IMFMediaStream_AddRef(iface);
132 return S_OK;
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);
146 if (!refcount)
148 IMFMediaEventQueue_Release(stream->event_queue);
149 free(stream);
152 return refcount;
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);
189 return S_OK;
192 static HRESULT WINAPI test_media_stream_GetStreamDescriptor(IMFMediaStream *iface, IMFStreamDescriptor **sd)
194 struct test_media_stream *stream = impl_from_IMFMediaStream(iface);
196 *sd = stream->sd;
197 IMFStreamDescriptor_AddRef(*sd);
199 return S_OK;
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;
208 IMFSample *sample;
209 HRESULT hr;
211 if (fail_request_sample)
212 return E_NOTIMPL;
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;
226 else
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);
235 if (token)
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,
246 (IUnknown *)sample);
247 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
248 IMFSample_Release(sample);
250 return S_OK;
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
269 struct test_source
271 IMFMediaSource IMFMediaSource_iface;
272 LONG refcount;
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;
278 CRITICAL_SECTION cs;
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))
292 *out = iface;
294 else
296 *out = NULL;
297 return E_NOINTERFACE;
300 IMFMediaSource_AddRef(iface);
301 return S_OK;
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);
315 if (!refcount)
317 IMFMediaEventQueue_Release(source->event_queue);
318 free(source);
321 return refcount;
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;
354 return S_OK;
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;
362 HRESULT hr = S_OK;
363 int i;
365 EnterCriticalSection(&source->cs);
367 if (source->pd)
369 *pd = source->pd;
370 IMFPresentationDescriptor_AddRef(*pd);
372 else
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]);
397 *pd = source->pd;
398 IMFPresentationDescriptor_AddRef(*pd);
401 LeaveCriticalSection(&source->cs);
403 return hr;
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);
414 return selected;
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;
422 PROPVARIANT var;
423 HRESULT hr;
424 int i;
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))
440 continue;
442 var.vt = VT_UNKNOWN;
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,
451 S_OK, NULL);
452 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
455 source->state = SOURCE_RUNNING;
457 LeaveCriticalSection(&source->cs);
459 return S_OK;
462 static HRESULT WINAPI test_source_Stop(IMFMediaSource *iface)
464 ok(0, "Unexpected call.\n");
465 return E_NOTIMPL;
468 static HRESULT WINAPI test_source_Pause(IMFMediaSource *iface)
470 ok(0, "Unexpected call.\n");
471 return E_NOTIMPL;
474 static HRESULT WINAPI test_source_Shutdown(IMFMediaSource *iface)
476 struct test_source *source = impl_from_IMFMediaSource(iface);
477 HRESULT hr;
479 hr = IMFMediaEventQueue_Shutdown(source->event_queue);
480 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
482 return S_OK;
485 static const IMFMediaSourceVtbl test_source_vtbl =
487 test_source_QueryInterface,
488 test_source_AddRef,
489 test_source_Release,
490 test_source_GetEvent,
491 test_source_BeginGetEvent,
492 test_source_EndGetEvent,
493 test_source_QueueEvent,
494 test_source_GetCharacteristics,
495 test_source_CreatePresentationDescriptor,
496 test_source_Start,
497 test_source_Stop,
498 test_source_Pause,
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;
506 BOOL selected;
507 HRESULT hr;
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);
522 return stream;
525 static IMFMediaSource *create_test_source(int stream_count)
527 struct test_source *source;
528 int i;
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;
545 IStream *stream;
546 DWORD written;
547 HRESULT hr;
548 HRSRC res;
549 void *ptr;
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);
566 return bytestream;
569 static void test_factory(void)
571 IMFReadWriteClassFactory *factory, *factory2;
572 HRESULT hr;
574 CoInitialize(NULL);
576 hr = CoCreateInstance(&CLSID_MFReadWriteClassFactory, NULL, CLSCTX_INPROC_SERVER, &IID_IMFReadWriteClassFactory,
577 (void **)&factory);
578 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
580 hr = CoCreateInstance(&CLSID_MFReadWriteClassFactory, (IUnknown *)factory, CLSCTX_INPROC_SERVER, &IID_IMFReadWriteClassFactory,
581 (void **)&factory2);
582 ok(hr == CLASS_E_NOAGGREGATION, "Unexpected hr %#lx.\n", hr);
584 IMFReadWriteClassFactory_Release(factory);
586 CoUninitialize();
589 struct async_callback
591 IMFSourceReaderCallback IMFSourceReaderCallback_iface;
592 LONG refcount;
593 HANDLE event;
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))
606 *out = iface;
607 IMFSourceReaderCallback_AddRef(iface);
608 return S_OK;
611 *out = NULL;
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);
626 if (!refcount)
627 free(callback);
629 return 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");
636 return E_NOTIMPL;
639 static HRESULT WINAPI async_callback_OnFlush(IMFSourceReaderCallback *iface, DWORD stream_index)
641 ok(0, "Unexpected call.\n");
642 return E_NOTIMPL;
645 static HRESULT WINAPI async_callback_OnEvent(IMFSourceReaderCallback *iface, DWORD stream_index, IMFMediaEvent *event)
647 ok(0, "Unexpected call.\n");
648 return E_NOTIMPL;
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;
669 return callback;
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;
681 LONGLONG timestamp;
682 IMFSample *sample;
683 ULONG refcount;
684 BOOL selected;
685 HRESULT hr;
687 if (!pMFCreateMFByteStreamOnStream)
689 win_skip("MFCreateMFByteStreamOnStream() not found\n");
690 return;
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);
704 if (FAILED(hr))
706 skip("MFCreateSourceReaderFromByteStream() failed, is G-Streamer missing?\n");
707 IMFByteStream_Release(stream);
708 IMFAttributes_Release(attributes);
709 winetest_pop_context();
710 return;
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,
718 (void **)&source);
719 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
720 IMFMediaSource_Release(source);
722 /* Stream selection. */
723 selected = FALSE;
724 hr = IMFSourceReader_GetStreamSelection(reader, MF_SOURCE_READER_FIRST_VIDEO_STREAM, &selected);
725 if (video)
727 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
728 ok(selected, "Unexpected selection.\n");
730 else
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);
738 selected = FALSE;
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");
743 selected = FALSE;
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);
757 selected = TRUE;
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);
765 selected = FALSE;
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);
772 if (video)
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);
781 else
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);
801 if (SUCCEEDED(hr))
802 IMFMediaType_Release(mediatype);
804 /* Current media type. */
805 hr = IMFSourceReader_GetCurrentMediaType(reader, MF_SOURCE_READER_FIRST_VIDEO_STREAM, &mediatype);
806 if (video)
808 GUID subtype;
809 UINT32 stride;
810 UINT64 framesize;
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);
865 if (hr == S_OK)
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);
881 else
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);
897 for (;;)
899 hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, &actual_index, &stream_flags,
900 &timestamp, &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");
908 break;
911 IMFSample_Release(sample);
914 hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, &actual_index, &stream_flags,
915 &timestamp, &sample);
916 if (video)
918 for (;;)
920 hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_VIDEO_STREAM,
921 0, &actual_index, &stream_flags, &timestamp, &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");
929 break;
932 IMFSample_Release(sample);
935 else
937 hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_VIDEO_STREAM,
938 0, &actual_index, &stream_flags, &timestamp, &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, &timestamp, &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, &timestamp, &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, &timestamp, &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, &timestamp, 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, &timestamp, &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, &timestamp, &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");
986 /* Flush. */
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);
1005 /* Async mode. */
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;
1037 HRESULT hr;
1038 DWORD actual_index, stream_flags;
1039 IMFSample *sample;
1040 LONGLONG timestamp;
1041 IMFAttributes *attributes;
1042 ULONG refcount;
1043 int i;
1044 PROPVARIANT pos;
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);
1059 pos.vt = VT_I8;
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 &timestamp, &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 &timestamp, &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 &timestamp, &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 &timestamp, &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);
1135 pos.vt = VT_I8;
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 &timestamp, &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 &timestamp, &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, &timestamp, &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);
1183 actual_index = 0;
1184 stream_flags = 0;
1185 hr = IMFSourceReader_ReadSample(reader, 1, 0, &actual_index, &stream_flags, &timestamp, &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, &timestamp, &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);
1243 /* Async mode. */
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, &timestamp, &sample);
1267 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1269 hr = IMFSourceReader_ReadSample(reader, 0, 0, NULL, &stream_flags, &timestamp, &sample);
1270 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
1272 hr = IMFSourceReader_ReadSample(reader, 0, 0, NULL, NULL, &timestamp, &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, &timestamp, &sample);
1301 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
1303 actual_index = ~0u;
1304 stream_flags = 0;
1305 hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, &actual_index, &stream_flags,
1306 &timestamp, &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);
1311 actual_index = ~0u;
1312 stream_flags = 0;
1313 hr = IMFSourceReader_ReadSample(reader, MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, &actual_index, &stream_flags,
1314 &timestamp, &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);
1319 actual_index = ~0u;
1320 stream_flags = 0;
1321 hr = IMFSourceReader_ReadSample(reader, 0, 0, &actual_index, &stream_flags, &timestamp, &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, &timestamp, &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;
1371 IDirect3D9 *d3d9;
1372 HWND window;
1373 HRESULT hr;
1374 UINT token;
1375 ULONG refcount;
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");
1383 goto done;
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);
1413 done:
1414 IDirect3D9_Release(d3d9);
1415 DestroyWindow(window);
1418 static void test_sink_writer_create(void)
1420 IMFSinkWriter *writer;
1421 HRESULT hr;
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;
1446 IMFMediaSink *sink;
1447 HRESULT hr;
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);
1472 if (hr == S_OK)
1473 IMFSinkWriter_Release(writer);
1475 hr = MFCreateSinkWriterFromURL(tmp_file, NULL, NULL, &writer);
1476 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1477 if (hr == S_OK)
1478 IMFSinkWriter_Release(writer);
1480 hr = MFCreateSinkWriterFromURL(tmp_file, NULL, attr, &writer);
1481 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1482 if (hr == S_OK)
1483 IMFSinkWriter_Release(writer);
1485 hr = MFCreateSinkWriterFromURL(tmp_file, stream, NULL, &writer);
1486 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1487 if (hr == S_OK)
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);
1497 todo_wine
1498 ok(hr == MF_E_UNSUPPORTED_SERVICE, "Unexpected hr %#lx.\n", hr);
1499 todo_wine
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;
1512 IUnknown *unk;
1513 HRESULT hr;
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);
1523 if (unk)
1524 IUnknown_Release(unk);
1526 IMFSourceReader_Release(reader);
1527 IMFMediaSource_Release(source);
1530 START_TEST(mfplat)
1532 HRESULT hr;
1534 hr = MFStartup(MF_VERSION, MFSTARTUP_FULL);
1535 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
1537 init_functions();
1539 test_factory();
1540 test_interfaces();
1541 test_source_reader("test.wav", false);
1542 test_source_reader("test.mp4", true);
1543 test_source_reader_from_media_source();
1544 test_reader_d3d9();
1545 test_sink_writer_create();
1546 test_sink_writer_mp4();
1548 hr = MFShutdown();
1549 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);