windowscodecs: Silence fixme for IID_CMetaBitmapRenderTarget.
[wine.git] / dlls / amstream / tests / amstream.c
blobb796dbd64f81c602f515ceec45b56edf480775c8
1 /*
2 * Unit tests for MultiMedia Stream functions
4 * Copyright (C) 2009, 2012 Christian Costa
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
22 #define NONAMELESSUNION
23 #define WINE_NO_NAMELESS_EXTENSION
25 #include "wine/test.h"
26 #include "dshow.h"
27 #include "amstream.h"
28 #include "mmreg.h"
29 #include "ks.h"
30 #include "initguid.h"
31 #include "ksmedia.h"
32 #include "dvdmedia.h"
33 #include "wmcodecdsp.h"
34 #include "wine/strmbase.h"
36 static const WAVEFORMATEX audio_format =
38 .wFormatTag = WAVE_FORMAT_PCM,
39 .nChannels = 1,
40 .nSamplesPerSec = 11025,
41 .wBitsPerSample = 16,
42 .nBlockAlign = 2,
43 .nAvgBytesPerSec = 2 * 11025,
46 static const AM_MEDIA_TYPE audio_mt =
48 /* MEDIATYPE_Audio, MEDIASUBTYPE_PCM, FORMAT_WaveFormatEx */
49 .majortype = {0x73647561, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}},
50 .subtype = {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}},
51 .formattype = {0x05589f81, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}},
52 .cbFormat = sizeof(WAVEFORMATEX),
53 .pbFormat = (BYTE *)&audio_format,
56 static const VIDEOINFO rgb8_video_info =
58 .bmiHeader.biSize = sizeof(BITMAPINFOHEADER),
59 .bmiHeader.biWidth = 333,
60 .bmiHeader.biHeight = -444,
61 .bmiHeader.biPlanes = 1,
62 .bmiHeader.biBitCount = 8,
63 .bmiHeader.biCompression = BI_RGB,
66 static const VIDEOINFO rgb555_video_info =
68 .bmiHeader.biSize = sizeof(BITMAPINFOHEADER),
69 .bmiHeader.biWidth = 333,
70 .bmiHeader.biHeight = -444,
71 .bmiHeader.biPlanes = 1,
72 .bmiHeader.biBitCount = 16,
73 .bmiHeader.biCompression = BI_RGB,
76 static const VIDEOINFO rgb565_video_info =
78 .bmiHeader.biSize = sizeof(BITMAPINFOHEADER),
79 .bmiHeader.biWidth = 333,
80 .bmiHeader.biHeight = -444,
81 .bmiHeader.biPlanes = 1,
82 .bmiHeader.biBitCount = 16,
83 .bmiHeader.biCompression = BI_BITFIELDS,
84 .u.dwBitMasks = {0xf800, 0x07e0, 0x001f},
87 static const VIDEOINFO rgb24_video_info =
89 .bmiHeader.biSize = sizeof(BITMAPINFOHEADER),
90 .bmiHeader.biWidth = 333,
91 .bmiHeader.biHeight = -444,
92 .bmiHeader.biPlanes = 1,
93 .bmiHeader.biBitCount = 24,
94 .bmiHeader.biCompression = BI_RGB,
97 static const VIDEOINFO rgb32_video_info =
99 .bmiHeader.biSize = sizeof(BITMAPINFOHEADER),
100 .bmiHeader.biWidth = 333,
101 .bmiHeader.biHeight = -444,
102 .bmiHeader.biPlanes = 1,
103 .bmiHeader.biBitCount = 32,
104 .bmiHeader.biCompression = BI_RGB,
107 static const AM_MEDIA_TYPE rgb8_mt =
109 /* MEDIATYPE_Video, MEDIASUBTYPE_RGB8, FORMAT_VideoInfo */
110 .majortype = {0x73646976, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}},
111 .subtype = {0xe436eb7a, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}},
112 .formattype = {0x05589f80, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}},
113 .cbFormat = sizeof(VIDEOINFO),
114 .pbFormat = (BYTE *)&rgb8_video_info,
117 static const AM_MEDIA_TYPE rgb555_mt =
119 /* MEDIATYPE_Video, MEDIASUBTYPE_RGB555, FORMAT_VideoInfo */
120 .majortype = {0x73646976, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}},
121 .subtype = {0xe436eb7c, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}},
122 .formattype = {0x05589f80, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}},
123 .cbFormat = sizeof(VIDEOINFO),
124 .pbFormat = (BYTE *)&rgb555_video_info,
127 static const AM_MEDIA_TYPE rgb565_mt =
129 /* MEDIATYPE_Video, MEDIASUBTYPE_RGB565, FORMAT_VideoInfo */
130 .majortype = {0x73646976, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}},
131 .subtype = {0xe436eb7b, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}},
132 .formattype = {0x05589f80, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}},
133 .cbFormat = sizeof(VIDEOINFO),
134 .pbFormat = (BYTE *)&rgb565_video_info,
137 static const AM_MEDIA_TYPE rgb24_mt =
139 /* MEDIATYPE_Video, MEDIASUBTYPE_RGB24, FORMAT_VideoInfo */
140 .majortype = {0x73646976, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}},
141 .subtype = {0xe436eb7d, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}},
142 .formattype = {0x05589f80, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}},
143 .cbFormat = sizeof(VIDEOINFO),
144 .pbFormat = (BYTE *)&rgb24_video_info,
147 static const AM_MEDIA_TYPE rgb32_mt =
149 /* MEDIATYPE_Video, MEDIASUBTYPE_RGB32, FORMAT_VideoInfo */
150 .majortype = {0x73646976, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}},
151 .subtype = {0xe436eb7e, 0x524f, 0x11ce, {0x9f, 0x53, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70}},
152 .formattype = {0x05589f80, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}},
153 .cbFormat = sizeof(VIDEOINFO),
154 .pbFormat = (BYTE *)&rgb32_video_info,
157 static const DDSURFACEDESC rgb8_format =
159 .dwSize = sizeof(DDSURFACEDESC),
160 .dwFlags = DDSD_PIXELFORMAT,
161 .ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT),
162 .ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8,
163 .ddpfPixelFormat.u1.dwRGBBitCount = 8,
166 static const DDSURFACEDESC rgb555_format =
168 .dwSize = sizeof(DDSURFACEDESC),
169 .dwFlags = DDSD_PIXELFORMAT,
170 .ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT),
171 .ddpfPixelFormat.dwFlags = DDPF_RGB,
172 .ddpfPixelFormat.u1.dwRGBBitCount = 16,
173 .ddpfPixelFormat.u2.dwRBitMask = 0x7c00,
174 .ddpfPixelFormat.u3.dwGBitMask = 0x03e0,
175 .ddpfPixelFormat.u4.dwBBitMask = 0x001f,
178 static const DDSURFACEDESC rgb565_format =
180 .dwSize = sizeof(DDSURFACEDESC),
181 .dwFlags = DDSD_PIXELFORMAT,
182 .ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT),
183 .ddpfPixelFormat.dwFlags = DDPF_RGB,
184 .ddpfPixelFormat.u1.dwRGBBitCount = 16,
185 .ddpfPixelFormat.u2.dwRBitMask = 0xf800,
186 .ddpfPixelFormat.u3.dwGBitMask = 0x07e0,
187 .ddpfPixelFormat.u4.dwBBitMask = 0x001f,
190 static const DDSURFACEDESC rgb24_format =
192 .dwSize = sizeof(DDSURFACEDESC),
193 .dwFlags = DDSD_PIXELFORMAT,
194 .ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT),
195 .ddpfPixelFormat.dwFlags = DDPF_RGB,
196 .ddpfPixelFormat.u1.dwRGBBitCount = 24,
197 .ddpfPixelFormat.u2.dwRBitMask = 0xff0000,
198 .ddpfPixelFormat.u3.dwGBitMask = 0x00ff00,
199 .ddpfPixelFormat.u4.dwBBitMask = 0x0000ff,
202 static const DDSURFACEDESC rgb32_format =
204 .dwSize = sizeof(DDSURFACEDESC),
205 .dwFlags = DDSD_PIXELFORMAT,
206 .ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT),
207 .ddpfPixelFormat.dwFlags = DDPF_RGB,
208 .ddpfPixelFormat.u1.dwRGBBitCount = 32,
209 .ddpfPixelFormat.u2.dwRBitMask = 0xff0000,
210 .ddpfPixelFormat.u3.dwGBitMask = 0x00ff00,
211 .ddpfPixelFormat.u4.dwBBitMask = 0x0000ff,
214 static const DDSURFACEDESC argb32_format =
216 .dwSize = sizeof(DDSURFACEDESC),
217 .dwFlags = DDSD_PIXELFORMAT,
218 .ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT),
219 .ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS,
220 .ddpfPixelFormat.u1.dwRGBBitCount = 32,
221 .ddpfPixelFormat.u2.dwRBitMask = 0xff0000,
222 .ddpfPixelFormat.u3.dwGBitMask = 0x00ff00,
223 .ddpfPixelFormat.u4.dwBBitMask = 0x0000ff,
224 .ddpfPixelFormat.u5.dwRGBAlphaBitMask = 0xff000000,
227 static const DDSURFACEDESC yuy2_format =
229 .dwSize = sizeof(DDSURFACEDESC),
230 .dwFlags = DDSD_PIXELFORMAT,
231 .ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT),
232 .ddpfPixelFormat.dwFlags = DDPF_FOURCC,
233 .ddpfPixelFormat.dwFourCC = MAKEFOURCC('Y', 'U', 'Y', '2'),
234 .ddpfPixelFormat.u1.dwYUVBitCount = 16,
237 static const DDSURFACEDESC yv12_format =
239 .dwSize = sizeof(DDSURFACEDESC),
240 .dwFlags = DDSD_PIXELFORMAT,
241 .ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT),
242 .ddpfPixelFormat.dwFlags = DDPF_FOURCC,
243 .ddpfPixelFormat.dwFourCC = MAKEFOURCC('Y', 'V', '1', '2'),
244 .ddpfPixelFormat.u1.dwYUVBitCount = 12,
247 static const WCHAR primary_video_sink_id[] = L"I{A35FF56A-9FDA-11D0-8FDF-00C04FD9189D}";
248 static const WCHAR primary_audio_sink_id[] = L"I{A35FF56B-9FDA-11D0-8FDF-00C04FD9189D}";
250 static const WCHAR *load_resource(const WCHAR *name)
252 HMODULE module = GetModuleHandleA(NULL);
253 HRSRC resource;
254 DWORD written;
255 HANDLE file;
256 WCHAR *path;
257 DWORD size;
258 void *ptr;
260 path = calloc(MAX_PATH + 1, sizeof(WCHAR));
261 ok(!!path, "Failed to allocate temp path string.\n");
262 GetTempPathW(MAX_PATH + 1, path);
263 wcscat(path, name);
265 file = CreateFileW(path, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
266 ok(file != INVALID_HANDLE_VALUE, "Failed to create file %s, error %lu.\n", wine_dbgstr_w(path), GetLastError());
268 resource = FindResourceW(module, name, (const WCHAR *)RT_RCDATA);
269 ok(!!resource, "Failed to find resource %s, error %lu.\n", wine_dbgstr_w(name), GetLastError());
271 size = SizeofResource(module, resource);
272 ptr = LockResource(LoadResource(module, resource));
274 WriteFile(file, ptr, size, &written, NULL);
275 ok(written == size, "Failed to write file %s.\n", wine_dbgstr_w(path));
277 CloseHandle(file);
279 return path;
282 static void unload_resource(const WCHAR *path)
284 BOOL ret = DeleteFileW(path);
285 ok(ret, "Failed to delete file %s.\n", wine_dbgstr_w(path));
286 free((void *)path);
289 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown*)obj, ref, __LINE__)
290 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
292 ULONG rc;
293 IUnknown_AddRef(obj);
294 rc = IUnknown_Release(obj);
295 ok_(__FILE__,line)(rc == ref, "expected refcount %ld, got %ld\n", ref, rc);
298 static IAMMultiMediaStream *create_ammultimediastream(void)
300 IAMMultiMediaStream *stream = NULL;
301 HRESULT hr = CoCreateInstance(&CLSID_AMMultiMediaStream, NULL, CLSCTX_INPROC_SERVER,
302 &IID_IAMMultiMediaStream, (void **)&stream);
303 ok(hr == S_OK, "Got hr %#lx.\n", hr);
304 return stream;
307 static ULONG get_refcount(void *iface)
309 IUnknown *unknown = iface;
310 IUnknown_AddRef(unknown);
311 return IUnknown_Release(unknown);
314 #define check_interface(a, b, c) check_interface_(__LINE__, a, b, c)
315 static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOOL supported)
317 IUnknown *iface = iface_ptr;
318 HRESULT hr, expected_hr;
319 IUnknown *unk;
321 expected_hr = supported ? S_OK : E_NOINTERFACE;
323 hr = IUnknown_QueryInterface(iface, iid, (void **)&unk);
324 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#lx, expected %#lx.\n", hr, expected_hr);
325 if (SUCCEEDED(hr))
326 IUnknown_Release(unk);
329 static void test_interfaces(void)
331 IAMMultiMediaStream *mmstream = create_ammultimediastream();
332 IMediaStreamFilter *filter;
333 IMediaStream *stream;
334 HRESULT hr;
335 ULONG ref;
337 check_interface(mmstream, &IID_IAMMultiMediaStream, TRUE);
338 check_interface(mmstream, &IID_IMultiMediaStream, TRUE);
339 check_interface(mmstream, &IID_IUnknown, TRUE);
341 check_interface(mmstream, &IID_IAMMediaStream, FALSE);
342 check_interface(mmstream, &IID_IAMMediaTypeStream, FALSE);
343 check_interface(mmstream, &IID_IAudioMediaStream, FALSE);
344 check_interface(mmstream, &IID_IBaseFilter, FALSE);
345 check_interface(mmstream, &IID_IDirectDrawMediaStream, FALSE);
346 check_interface(mmstream, &IID_IMediaFilter, FALSE);
347 check_interface(mmstream, &IID_IMediaStream, FALSE);
348 check_interface(mmstream, &IID_IMediaStreamFilter, FALSE);
349 check_interface(mmstream, &IID_IPin, FALSE);
351 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
352 ok(hr == S_OK, "Got hr %#lx.\n", hr);
354 check_interface(filter, &IID_IBaseFilter, TRUE);
355 check_interface(filter, &IID_IMediaFilter, TRUE);
356 check_interface(filter, &IID_IMediaStreamFilter, TRUE);
357 check_interface(filter, &IID_IPersist, TRUE);
358 check_interface(filter, &IID_IUnknown, TRUE);
360 check_interface(filter, &IID_IAMMediaStream, FALSE);
361 check_interface(filter, &IID_IAMMediaTypeStream, FALSE);
362 check_interface(filter, &IID_IAMMultiMediaStream, FALSE);
363 check_interface(filter, &IID_IAudioMediaStream, FALSE);
364 check_interface(filter, &IID_IDirectDrawMediaStream, FALSE);
365 check_interface(filter, &IID_IMediaStream, FALSE);
366 check_interface(filter, &IID_IMultiMediaStream, FALSE);
367 check_interface(filter, &IID_IPin, FALSE);
369 IMediaStreamFilter_Release(filter);
371 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
372 ok(hr == S_OK, "Got hr %#lx.\n", hr);
374 check_interface(stream, &IID_IAMMediaStream, TRUE);
375 check_interface(stream, &IID_IAudioMediaStream, TRUE);
376 check_interface(stream, &IID_IMediaStream, TRUE);
377 check_interface(stream, &IID_IMemInputPin, TRUE);
378 check_interface(stream, &IID_IPin, TRUE);
379 check_interface(stream, &IID_IUnknown, TRUE);
381 check_interface(stream, &IID_IAMMediaTypeStream, FALSE);
382 check_interface(stream, &IID_IAMMultiMediaStream, FALSE);
383 check_interface(stream, &IID_IBaseFilter, FALSE);
384 check_interface(stream, &IID_IDirectDrawMediaStream, FALSE);
385 check_interface(stream, &IID_IMediaFilter, FALSE);
386 check_interface(stream, &IID_IMediaStreamFilter, FALSE);
387 check_interface(stream, &IID_IMultiMediaStream, FALSE);
388 check_interface(stream, &IID_IPersist, FALSE);
389 check_interface(stream, &IID_IQualityControl, FALSE);
391 IMediaStream_Release(stream);
393 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
394 ok(hr == S_OK, "Got hr %#lx.\n", hr);
396 check_interface(stream, &IID_IAMMediaStream, TRUE);
397 check_interface(stream, &IID_IDirectDrawMediaStream, TRUE);
398 check_interface(stream, &IID_IMediaStream, TRUE);
399 check_interface(stream, &IID_IMemInputPin, TRUE);
400 check_interface(stream, &IID_IPin, TRUE);
401 check_interface(stream, &IID_IUnknown, TRUE);
403 check_interface(stream, &IID_IAMMediaTypeStream, FALSE);
404 check_interface(stream, &IID_IAMMultiMediaStream, FALSE);
405 check_interface(stream, &IID_IAudioMediaStream, FALSE);
406 check_interface(stream, &IID_IBaseFilter, FALSE);
407 check_interface(stream, &IID_IDirectDraw, FALSE);
408 check_interface(stream, &IID_IMediaFilter, FALSE);
409 check_interface(stream, &IID_IMediaStreamFilter, FALSE);
410 check_interface(stream, &IID_IMultiMediaStream, FALSE);
411 check_interface(stream, &IID_IPersist, FALSE);
412 check_interface(stream, &IID_IQualityControl, FALSE);
414 IMediaStream_Release(stream);
416 ref = IAMMultiMediaStream_Release(mmstream);
417 ok(!ref, "Got outstanding refcount %lu.\n", ref);
420 static void test_openfile(const WCHAR *test_avi_path)
422 IAMMultiMediaStream *mmstream = create_ammultimediastream();
423 IMediaControl *media_control;
424 IMediaStreamFilter *filter;
425 IMediaFilter *media_filter;
426 IReferenceClock *clock;
427 IGraphBuilder *graph;
428 OAFilterState state;
429 HRESULT hr;
430 ULONG ref;
432 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
433 ok(hr == S_OK, "Got hr %#lx.\n", hr);
434 ok(!graph, "Expected NULL graph.\n");
436 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
437 ok(!!filter, "Expected non-NULL filter.\n");
438 ok(hr == S_OK, "Got hr %#lx.\n", hr);
440 check_interface(filter, &IID_IMediaSeeking, FALSE);
442 hr = IAMMultiMediaStream_OpenFile(mmstream, test_avi_path, AMMSF_NORENDER);
443 ok(hr == S_OK, "Got hr %#lx.\n", hr);
445 check_interface(filter, &IID_IMediaSeeking, FALSE);
447 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
448 ok(hr == S_OK, "Got hr %#lx.\n", hr);
449 ok(!!graph, "Expected non-NULL graph.\n");
450 IGraphBuilder_Release(graph);
451 IMediaStreamFilter_Release(filter);
453 ref = IAMMultiMediaStream_Release(mmstream);
454 ok(!ref, "Got outstanding refcount %ld.\n", ref);
456 mmstream = create_ammultimediastream();
458 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
459 ok(hr == S_OK, "Got hr %#lx.\n", hr);
460 ok(!graph, "Expected NULL graph.\n");
462 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
463 ok(!!filter, "Expected non-NULL filter.\n");
464 ok(hr == S_OK, "Got hr %#lx.\n", hr);
466 check_interface(filter, &IID_IMediaSeeking, FALSE);
468 hr = IAMMultiMediaStream_OpenFile(mmstream, test_avi_path, AMMSF_RENDERALLSTREAMS);
469 ok(hr == S_OK, "Got hr %#lx.\n", hr);
471 check_interface(filter, &IID_IMediaSeeking, FALSE);
473 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
474 ok(hr == S_OK, "Got hr %#lx.\n", hr);
475 ok(!!graph, "Expected non-NULL graph.\n");
477 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void **)&media_filter);
478 ok(hr == S_OK, "Got hr %#lx.\n", hr);
480 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
481 ok(hr == S_OK, "Got hr %#lx.\n", hr);
483 clock = NULL;
484 IMediaFilter_GetSyncSource(media_filter, &clock);
485 ok(!!clock, "Expected non-NULL clock.\n");
487 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
488 ok(hr == S_OK, "Got hr %#lx.\n", hr);
490 ref = IAMMultiMediaStream_Release(mmstream);
491 ok(!ref, "Got outstanding refcount %ld.\n", ref);
492 IMediaFilter_Release(media_filter);
493 ref = IGraphBuilder_Release(graph);
494 ok(!ref, "Got outstanding refcount %ld.\n", ref);
495 ref = IMediaStreamFilter_Release(filter);
496 ok(!ref, "Got outstanding refcount %ld.\n", ref);
497 ref = IReferenceClock_Release(clock);
498 ok(!ref, "Got outstanding refcount %ld.\n", ref);
500 mmstream = create_ammultimediastream();
501 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
502 ok(hr == S_OK, "Got hr %#lx.\n", hr);
503 ok(!graph, "Expected NULL graph.\n");
505 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
506 ok(!!filter, "Expected non-NULL filter.\n");
507 ok(hr == S_OK, "Got hr %#lx.\n", hr);
509 check_interface(filter, &IID_IMediaSeeking, FALSE);
511 hr = IAMMultiMediaStream_OpenFile(mmstream, test_avi_path, AMMSF_RENDERTOEXISTING);
512 ok(hr == VFW_E_CANNOT_CONNECT, "Got hr %#lx.\n", hr);
514 check_interface(filter, &IID_IMediaSeeking, FALSE);
516 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
517 ok(hr == S_OK, "Got hr %#lx.\n", hr);
518 ok(!!graph, "Expected non-NULL graph.\n");
519 IGraphBuilder_Release(graph);
520 IMediaStreamFilter_Release(filter);
522 ref = IAMMultiMediaStream_Release(mmstream);
523 ok(!ref, "Got outstanding refcount %ld.\n", ref);
525 mmstream = create_ammultimediastream();
526 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, NULL);
527 ok(hr == S_OK, "Got hr %#lx.\n", hr);
528 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
529 ok(hr == S_OK, "Got hr %#lx.\n", hr);
530 ok(!!graph, "Expected non-NULL graph.\n");
531 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void **)&media_filter);
532 ok(hr == S_OK, "Got hr %#lx.\n", hr);
533 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
534 ok(hr == S_OK, "Got hr %#lx.\n", hr);
536 check_interface(filter, &IID_IMediaSeeking, FALSE);
538 hr = IAMMultiMediaStream_OpenFile(mmstream, test_avi_path, AMMSF_RENDERTOEXISTING);
539 ok(hr == S_OK, "Got hr %#lx.\n", hr);
541 check_interface(filter, &IID_IMediaSeeking, TRUE);
543 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
544 ok(hr == S_OK, "Got hr %#lx.\n", hr);
546 clock = NULL;
547 IMediaFilter_GetSyncSource(media_filter, &clock);
548 ok(!!clock, "Expected non-NULL clock.\n");
550 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
551 ok(hr == S_OK, "Got hr %#lx.\n", hr);
553 ref = IAMMultiMediaStream_Release(mmstream);
554 ok(!ref, "Got outstanding refcount %ld.\n", ref);
555 IMediaFilter_Release(media_filter);
556 ref = IGraphBuilder_Release(graph);
557 ok(!ref, "Got outstanding refcount %ld.\n", ref);
558 ref = IMediaStreamFilter_Release(filter);
559 ok(!ref, "Got outstanding refcount %ld.\n", ref);
560 ref = IReferenceClock_Release(clock);
561 ok(!ref, "Got outstanding refcount %ld.\n", ref);
563 mmstream = create_ammultimediastream();
564 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, NULL);
565 ok(hr == S_OK, "Got hr %#lx.\n", hr);
566 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
567 ok(hr == S_OK, "Got hr %#lx.\n", hr);
568 ok(!!graph, "Expected non-NULL graph.\n");
569 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void **)&media_control);
570 ok(hr == S_OK, "Got hr %#lx.\n", hr);
572 hr = IAMMultiMediaStream_OpenFile(mmstream, test_avi_path, AMMSF_RUN);
573 ok(hr == S_OK, "Got hr %#lx.\n", hr);
575 state = 0xdeadbeef;
576 hr = IMediaControl_GetState(media_control, INFINITE, &state);
577 ok(hr == S_OK, "Got hr %#lx.\n", hr);
578 ok(state == State_Running, "Got state %#lx.\n", state);
580 ref = IAMMultiMediaStream_Release(mmstream);
581 ok(!ref, "Got outstanding refcount %ld.\n", ref);
582 IMediaControl_Release(media_control);
583 ref = IGraphBuilder_Release(graph);
584 ok(!ref, "Got outstanding refcount %ld.\n", ref);
586 mmstream = create_ammultimediastream();
587 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, NULL);
588 ok(hr == S_OK, "Got hr %#lx.\n", hr);
589 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
590 ok(hr == S_OK, "Got hr %#lx.\n", hr);
591 ok(!!graph, "Expected non-NULL graph.\n");
592 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void **)&media_filter);
593 ok(hr == S_OK, "Got hr %#lx.\n", hr);
595 hr = IAMMultiMediaStream_OpenFile(mmstream, test_avi_path, AMMSF_NOCLOCK);
596 ok(hr == S_OK, "Got hr %#lx.\n", hr);
598 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
599 ok(hr == S_OK, "Got hr %#lx.\n", hr);
601 clock = (IReferenceClock *)0xdeadbeef;
602 IMediaFilter_GetSyncSource(media_filter, &clock);
603 ok(!clock, "Got clock %p.\n", clock);
605 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
606 ok(hr == S_OK, "Got hr %#lx.\n", hr);
608 ref = IAMMultiMediaStream_Release(mmstream);
609 ok(!ref, "Got outstanding refcount %ld.\n", ref);
610 IMediaFilter_Release(media_filter);
611 ref = IGraphBuilder_Release(graph);
612 ok(!ref, "Got outstanding refcount %ld.\n", ref);
615 static void test_mmstream_get_duration(const WCHAR *test_avi_path)
617 IAMMultiMediaStream *mmstream = create_ammultimediastream();
618 HRESULT hr, audio_hr;
619 LONGLONG duration;
620 ULONG ref;
622 duration = 0xdeadbeefdeadbeefULL;
623 hr = IAMMultiMediaStream_GetDuration(mmstream, &duration);
624 ok(hr == E_NOINTERFACE, "Got hr %#lx.\n", hr);
625 ok(duration == 0xdeadbeefdeadbeefULL, "Got duration %s.\n", wine_dbgstr_longlong(duration));
627 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, NULL);
628 ok(hr == S_OK, "Got hr %#lx.\n", hr);
630 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, AMMSF_ADDDEFAULTRENDERER, NULL);
631 ok(hr == S_OK || hr == VFW_E_NO_AUDIO_HARDWARE, "Got hr %#lx.\n", hr);
632 audio_hr = hr;
634 hr = IAMMultiMediaStream_OpenFile(mmstream, test_avi_path, AMMSF_RENDERTOEXISTING);
635 ok(hr == S_OK, "Got hr %#lx.\n", hr);
637 duration = 0xdeadbeefdeadbeefULL;
638 hr = IAMMultiMediaStream_GetDuration(mmstream, &duration);
639 if (audio_hr == S_OK)
641 ok(hr == S_OK, "Got hr %#lx.\n", hr);
642 ok(duration == 1000000LL, "Got duration %s.\n", wine_dbgstr_longlong(duration));
644 else
646 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
647 ok(!duration, "Got duration %s.\n", wine_dbgstr_longlong(duration));
650 ref = IAMMultiMediaStream_Release(mmstream);
651 ok(!ref, "Got outstanding refcount %ld.\n", ref);
653 mmstream = create_ammultimediastream();
654 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, NULL);
655 ok(hr == S_OK, "Got hr %#lx.\n", hr);
657 duration = 0xdeadbeefdeadbeefULL;
658 hr = IAMMultiMediaStream_GetDuration(mmstream, &duration);
659 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
660 ok(duration == 0, "Got duration %s.\n", wine_dbgstr_longlong(duration));
662 ref = IAMMultiMediaStream_Release(mmstream);
663 ok(!ref, "Got outstanding refcount %ld.\n", ref);
665 mmstream = create_ammultimediastream();
667 hr = IAMMultiMediaStream_OpenFile(mmstream, test_avi_path, AMMSF_RENDERTOEXISTING);
668 ok(hr == VFW_E_CANNOT_CONNECT, "Got hr %#lx.\n", hr);
670 duration = 0xdeadbeefdeadbeefULL;
671 hr = IAMMultiMediaStream_GetDuration(mmstream, &duration);
672 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
673 ok(duration == 0, "Got duration %s.\n", wine_dbgstr_longlong(duration));
675 ref = IAMMultiMediaStream_Release(mmstream);
676 ok(!ref, "Got outstanding refcount %ld.\n", ref);
678 mmstream = create_ammultimediastream();
679 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, NULL);
680 ok(hr == S_OK, "Got hr %#lx.\n", hr);
682 hr = IAMMultiMediaStream_OpenFile(mmstream, test_avi_path, AMMSF_NORENDER);
683 ok(hr == S_OK, "Got hr %#lx.\n", hr);
685 duration = 0xdeadbeefdeadbeefULL;
686 hr = IAMMultiMediaStream_GetDuration(mmstream, &duration);
687 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
688 ok(duration == 0, "Got duration %s.\n", wine_dbgstr_longlong(duration));
690 ref = IAMMultiMediaStream_Release(mmstream);
691 ok(!ref, "Got outstanding refcount %ld.\n", ref);
694 static const GUID test_mspid = {0x88888888};
696 struct teststream
698 IAMMediaStream IAMMediaStream_iface;
699 IPin IPin_iface;
700 LONG refcount;
701 GUID mspid;
702 IAMMultiMediaStream *mmstream;
703 IMediaStreamFilter *filter;
704 IFilterGraph *graph;
705 FILTER_STATE state;
706 HRESULT set_state_result;
709 static struct teststream *impl_from_IAMMediaStream(IAMMediaStream *iface)
711 return CONTAINING_RECORD(iface, struct teststream, IAMMediaStream_iface);
714 static struct teststream *impl_from_IPin(IPin *iface)
716 return CONTAINING_RECORD(iface, struct teststream, IPin_iface);
719 static HRESULT WINAPI pin_QueryInterface(IPin *iface, REFIID iid, void **out)
721 struct teststream *stream = impl_from_IPin(iface);
722 return IAMMediaStream_QueryInterface(&stream->IAMMediaStream_iface, iid, out);
725 static ULONG WINAPI pin_AddRef(IPin *iface)
727 struct teststream *stream = impl_from_IPin(iface);
728 return IAMMediaStream_AddRef(&stream->IAMMediaStream_iface);
731 static ULONG WINAPI pin_Release(IPin *iface)
733 struct teststream *stream = impl_from_IPin(iface);
734 return IAMMediaStream_Release(&stream->IAMMediaStream_iface);
737 static HRESULT WINAPI pin_Connect(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
739 ok(0, "Unexpected call.\n");
740 return E_NOTIMPL;
743 static HRESULT WINAPI pin_ReceiveConnection(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
745 ok(0, "Unexpected call.\n");
746 return E_NOTIMPL;
749 static HRESULT WINAPI pin_Disconnect(IPin *iface)
751 if (winetest_debug > 1) trace("Disconnect\n");
752 return E_NOTIMPL;
755 static HRESULT WINAPI pin_ConnectedTo(IPin *iface, IPin **peer)
757 if (winetest_debug > 1) trace("ConnectedTo\n");
758 return E_NOTIMPL;
761 static HRESULT WINAPI pin_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *mt)
763 ok(0, "Unexpected call.\n");
764 return E_NOTIMPL;
767 static HRESULT WINAPI pin_QueryPinInfo(IPin *iface, PIN_INFO *info)
769 ok(0, "Unexpected call.\n");
770 return E_NOTIMPL;
773 static HRESULT WINAPI pin_QueryDirection(IPin *iface, PIN_DIRECTION *dir)
775 if (winetest_debug > 1) trace("QueryDirection\n");
776 *dir = PINDIR_INPUT;
777 return S_OK;
780 static HRESULT WINAPI pin_QueryId(IPin *iface, WCHAR **id)
782 ok(0, "Unexpected call.\n");
783 return E_NOTIMPL;
786 static HRESULT WINAPI pin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *mt)
788 ok(0, "Unexpected call.\n");
789 return E_NOTIMPL;
792 static HRESULT WINAPI pin_EnumMediaTypes(IPin *iface, IEnumMediaTypes **out)
794 ok(0, "Unexpected call.\n");
795 return E_NOTIMPL;
798 static HRESULT WINAPI pin_QueryInternalConnections(IPin *iface, IPin **pins, ULONG *count)
800 ok(0, "Unexpected call.\n");
801 return E_NOTIMPL;
804 static HRESULT WINAPI pin_EndOfStream(IPin *iface)
806 ok(0, "Unexpected call.\n");
807 return E_NOTIMPL;
810 static HRESULT WINAPI pin_BeginFlush(IPin *iface)
812 ok(0, "Unexpected call.\n");
813 return E_NOTIMPL;
816 static HRESULT WINAPI pin_EndFlush(IPin *iface)
818 ok(0, "Unexpected call.\n");
819 return E_NOTIMPL;
822 static HRESULT WINAPI pin_NewSegment(IPin *iface, REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
824 ok(0, "Unexpected call.\n");
825 return E_NOTIMPL;
828 static const IPinVtbl pin_vtbl =
830 pin_QueryInterface,
831 pin_AddRef,
832 pin_Release,
833 pin_Connect,
834 pin_ReceiveConnection,
835 pin_Disconnect,
836 pin_ConnectedTo,
837 pin_ConnectionMediaType,
838 pin_QueryPinInfo,
839 pin_QueryDirection,
840 pin_QueryId,
841 pin_QueryAccept,
842 pin_EnumMediaTypes,
843 pin_QueryInternalConnections,
844 pin_EndOfStream,
845 pin_BeginFlush,
846 pin_EndFlush,
847 pin_NewSegment
850 static HRESULT WINAPI stream_QueryInterface(IAMMediaStream *iface, REFIID iid, void **out)
852 struct teststream *stream = impl_from_IAMMediaStream(iface);
854 if (winetest_debug > 1) trace("QueryInterface(%s)\n", wine_dbgstr_guid(iid));
856 if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IMediaStream) || IsEqualGUID(iid, &IID_IAMMediaStream))
858 IAMMediaStream_AddRef(iface);
859 *out = iface;
860 return S_OK;
862 else if (IsEqualGUID(iid, &IID_IPin))
864 IAMMediaStream_AddRef(iface);
865 *out = &stream->IPin_iface;
866 return S_OK;
869 ok(0, "Unexpected interface %s.\n", wine_dbgstr_guid(iid));
870 return E_NOINTERFACE;
873 static ULONG WINAPI stream_AddRef(IAMMediaStream *iface)
875 struct teststream *stream = impl_from_IAMMediaStream(iface);
876 return InterlockedIncrement(&stream->refcount);
879 static ULONG WINAPI stream_Release(IAMMediaStream *iface)
881 struct teststream *stream = impl_from_IAMMediaStream(iface);
882 return InterlockedDecrement(&stream->refcount);
885 static HRESULT WINAPI stream_GetMultiMediaStream(IAMMediaStream *iface, IMultiMediaStream **mmstream)
887 ok(0, "Unexpected call.\n");
888 return E_NOTIMPL;
891 static HRESULT WINAPI stream_GetInformation(IAMMediaStream *iface, MSPID *id, STREAM_TYPE *type)
893 struct teststream *stream = impl_from_IAMMediaStream(iface);
894 if (winetest_debug > 1) trace("GetInformation(%p, %p)\n", id, type);
895 if (id)
896 *id = stream->mspid;
897 if (type)
898 *type = STREAMTYPE_READ;
899 return S_OK;
902 static HRESULT WINAPI stream_SetSameFormat(IAMMediaStream *iface, IMediaStream *ref, DWORD flags)
904 ok(0, "Unexpected call.\n");
905 return E_NOTIMPL;
908 static HRESULT WINAPI stream_AllocateSample(IAMMediaStream *iface, DWORD flags, IStreamSample **sample)
910 ok(0, "Unexpected call.\n");
911 return E_NOTIMPL;
914 static HRESULT WINAPI stream_CreateSharedSample(IAMMediaStream *iface,
915 IStreamSample *existing, DWORD flags, IStreamSample **out)
917 ok(0, "Unexpected call.\n");
918 return E_NOTIMPL;
921 static HRESULT WINAPI stream_SendEndOfStream(IAMMediaStream *iface, DWORD flags)
923 ok(0, "Unexpected call.\n");
924 return E_NOTIMPL;
927 static HRESULT WINAPI stream_Initialize(IAMMediaStream *iface, IUnknown *source,
928 DWORD flags, REFMSPID id, const STREAM_TYPE type)
930 ok(0, "Unexpected call.\n");
931 return E_NOTIMPL;
934 static HRESULT WINAPI stream_SetState(IAMMediaStream *iface, FILTER_STATE state)
936 struct teststream *stream = impl_from_IAMMediaStream(iface);
937 if (winetest_debug > 1) trace("SetState(%#x)\n", state);
938 if (SUCCEEDED(stream->set_state_result))
939 stream->state = state;
940 return stream->set_state_result;
943 static HRESULT WINAPI stream_JoinAMMultiMediaStream(IAMMediaStream *iface, IAMMultiMediaStream *mmstream)
945 struct teststream *stream = impl_from_IAMMediaStream(iface);
946 if (winetest_debug > 1) trace("JoinAMMultiMediaStream(%p)\n", mmstream);
947 stream->mmstream = mmstream;
948 return S_OK;
951 static HRESULT WINAPI stream_JoinFilter(IAMMediaStream *iface, IMediaStreamFilter *filter)
953 struct teststream *stream = impl_from_IAMMediaStream(iface);
954 if (winetest_debug > 1) trace("JoinFilter(%p)\n", filter);
955 stream->filter = filter;
956 return S_OK;
959 static HRESULT WINAPI stream_JoinFilterGraph(IAMMediaStream *iface, IFilterGraph *graph)
961 struct teststream *stream = impl_from_IAMMediaStream(iface);
962 if (winetest_debug > 1) trace("JoinFilterGraph(%p)\n", graph);
963 stream->graph = graph;
964 return S_OK;
967 static const IAMMediaStreamVtbl stream_vtbl =
969 stream_QueryInterface,
970 stream_AddRef,
971 stream_Release,
972 stream_GetMultiMediaStream,
973 stream_GetInformation,
974 stream_SetSameFormat,
975 stream_AllocateSample,
976 stream_CreateSharedSample,
977 stream_SendEndOfStream,
978 stream_Initialize,
979 stream_SetState,
980 stream_JoinAMMultiMediaStream,
981 stream_JoinFilter,
982 stream_JoinFilterGraph,
985 static void teststream_init(struct teststream *stream)
987 memset(stream, 0, sizeof(*stream));
988 stream->IAMMediaStream_iface.lpVtbl = &stream_vtbl;
989 stream->IPin_iface.lpVtbl = &pin_vtbl;
990 stream->refcount = 1;
991 stream->mspid = test_mspid;
992 stream->set_state_result = S_OK;
995 #define check_enum_stream(a,b,c,d) check_enum_stream_(__LINE__,a,b,c,d)
996 static void check_enum_stream_(int line, IAMMultiMediaStream *mmstream,
997 IMediaStreamFilter *filter, LONG index, IMediaStream *expect)
999 IMediaStream *stream = NULL, *stream2 = NULL;
1000 HRESULT hr;
1002 hr = IAMMultiMediaStream_EnumMediaStreams(mmstream, index, &stream);
1003 ok_(__FILE__, line)(hr == (expect ? S_OK : S_FALSE),
1004 "IAMMultiMediaStream::EnumMediaStreams() returned %#lx.\n", hr);
1005 hr = IMediaStreamFilter_EnumMediaStreams(filter, index, &stream2);
1006 ok_(__FILE__, line)(hr == (expect ? S_OK : S_FALSE),
1007 "IMediaStreamFilter::EnumMediaStreams() returned %#lx.\n", hr);
1008 if (hr == S_OK)
1010 ok_(__FILE__, line)(stream == expect, "Expected stream %p, got %p.\n", expect, stream);
1011 ok_(__FILE__, line)(stream2 == expect, "Expected stream %p, got %p.\n", expect, stream2);
1012 IMediaStream_Release(stream);
1013 IMediaStream_Release(stream2);
1017 struct testfilter
1019 struct strmbase_filter filter;
1020 struct strmbase_source source;
1021 IMediaSeeking IMediaSeeking_iface;
1022 IQualityControl IQualityControl_iface;
1023 LONGLONG current_position;
1024 LONGLONG stop_position;
1025 const AM_MEDIA_TYPE *preferred_mt;
1026 HANDLE wait_state_event;
1027 IBaseFilter *qc_notify_sender;
1028 Quality qc_notify_quality;
1029 HRESULT get_duration_hr;
1030 HRESULT get_stop_position_hr;
1031 HRESULT set_positions_hr;
1032 HRESULT init_stream_hr;
1033 HRESULT cleanup_stream_hr;
1034 HRESULT wait_state_hr;
1035 HRESULT is_format_supported_hr;
1036 HRESULT qc_notify_hr;
1039 static inline struct testfilter *impl_from_BaseFilter(struct strmbase_filter *iface)
1041 return CONTAINING_RECORD(iface, struct testfilter, filter);
1044 static struct strmbase_pin *testfilter_get_pin(struct strmbase_filter *iface, unsigned int index)
1046 struct testfilter *filter = impl_from_BaseFilter(iface);
1047 if (!index)
1048 return &filter->source.pin;
1049 return NULL;
1052 static void testfilter_destroy(struct strmbase_filter *iface)
1054 struct testfilter *filter = impl_from_BaseFilter(iface);
1055 CloseHandle(filter->wait_state_event);
1056 strmbase_source_cleanup(&filter->source);
1057 strmbase_filter_cleanup(&filter->filter);
1060 static HRESULT testfilter_init_stream(struct strmbase_filter *iface)
1062 struct testfilter *filter = impl_from_BaseFilter(iface);
1063 HRESULT hr;
1065 if (SUCCEEDED(filter->init_stream_hr) && filter->source.pin.peer)
1067 hr = IMemAllocator_Commit(filter->source.pAllocator);
1068 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1071 return filter->init_stream_hr;
1074 static HRESULT testfilter_cleanup_stream(struct strmbase_filter *iface)
1076 struct testfilter *filter = impl_from_BaseFilter(iface);
1077 HRESULT hr;
1079 if (SUCCEEDED(filter->cleanup_stream_hr) && filter->source.pin.peer)
1081 hr = IMemAllocator_Decommit(filter->source.pAllocator);
1082 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1085 return filter->cleanup_stream_hr;
1088 static HRESULT testfilter_wait_state(struct strmbase_filter *iface, DWORD timeout)
1090 struct testfilter *filter = impl_from_BaseFilter(iface);
1091 HRESULT hr;
1093 LeaveCriticalSection(&filter->filter.filter_cs);
1094 WaitForSingleObject(filter->wait_state_event, timeout);
1095 EnterCriticalSection(&filter->filter.filter_cs);
1097 hr = filter->wait_state_hr;
1099 return hr;
1102 static const struct strmbase_filter_ops testfilter_ops =
1104 .filter_get_pin = testfilter_get_pin,
1105 .filter_destroy = testfilter_destroy,
1106 .filter_init_stream = testfilter_init_stream,
1107 .filter_cleanup_stream = testfilter_cleanup_stream,
1108 .filter_wait_state = testfilter_wait_state,
1111 static inline struct testfilter *impl_from_base_pin(struct strmbase_pin *iface)
1113 return CONTAINING_RECORD(iface, struct testfilter, source.pin);
1116 static HRESULT testsource_get_media_type(struct strmbase_pin *iface, unsigned int index, AM_MEDIA_TYPE *mt)
1118 struct testfilter *filter = impl_from_base_pin(iface);
1120 if (index < 1 && filter->preferred_mt)
1121 return CopyMediaType(mt, filter->preferred_mt);
1123 return VFW_S_NO_MORE_ITEMS;
1126 static HRESULT testsource_query_interface(struct strmbase_pin *iface, REFIID iid, void **out)
1128 struct testfilter *filter = impl_from_base_pin(iface);
1130 if (IsEqualGUID(iid, &IID_IMediaSeeking) && filter->IMediaSeeking_iface.lpVtbl)
1131 *out = &filter->IMediaSeeking_iface;
1132 else if (IsEqualGUID(iid, &IID_IQualityControl) && filter->IQualityControl_iface.lpVtbl)
1133 *out = &filter->IQualityControl_iface;
1134 else
1135 return E_NOINTERFACE;
1137 IUnknown_AddRef((IUnknown *)*out);
1139 return S_OK;
1142 static HRESULT WINAPI testsource_DecideAllocator(struct strmbase_source *iface, IMemInputPin *pin, IMemAllocator **alloc)
1144 ALLOCATOR_PROPERTIES props = {0};
1145 HRESULT hr;
1147 /* AMDirectDrawStream tries to use it's custom allocator and
1148 * when it is able to do so it's behavior changes slightly
1149 * (e.g. it uses dynamic format change instead of reconnecting in SetFormat).
1150 * We don't yet implement the custom allocator so force the standard one for now. */
1151 hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER,
1152 &IID_IMemAllocator, (void **)alloc);
1153 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1155 IMemInputPin_GetAllocatorRequirements(pin, &props);
1156 hr = iface->pFuncsTable->pfnDecideBufferSize(iface, *alloc, &props);
1157 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1159 return IMemInputPin_NotifyAllocator(pin, *alloc, FALSE);
1162 static HRESULT WINAPI testsource_DecideBufferSize(struct strmbase_source *iface,
1163 IMemAllocator *alloc, ALLOCATOR_PROPERTIES *requested)
1165 ALLOCATOR_PROPERTIES actual;
1167 if (!requested->cbAlign)
1168 requested->cbAlign = 1;
1170 if (requested->cbBuffer < 4096)
1171 requested->cbBuffer = 4096;
1173 if (!requested->cBuffers)
1174 requested->cBuffers = 2;
1176 return IMemAllocator_SetProperties(alloc, requested, &actual);
1179 static const struct strmbase_source_ops testsource_ops =
1181 .base.pin_get_media_type = testsource_get_media_type,
1182 .base.pin_query_interface = testsource_query_interface,
1183 .pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection,
1184 .pfnDecideBufferSize = testsource_DecideBufferSize,
1185 .pfnDecideAllocator = testsource_DecideAllocator,
1188 static void testfilter_init(struct testfilter *filter)
1190 static const GUID clsid = {0xabacab};
1191 memset(filter, 0, sizeof(*filter));
1192 strmbase_filter_init(&filter->filter, NULL, &clsid, &testfilter_ops);
1193 strmbase_source_init(&filter->source, &filter->filter, L"", &testsource_ops);
1194 filter->stop_position = 0x8000000000000000ULL;
1195 filter->wait_state_event = CreateEventW(NULL, TRUE, TRUE, NULL);
1198 static inline struct testfilter *impl_from_IMediaSeeking(IMediaSeeking *iface)
1200 return CONTAINING_RECORD(iface, struct testfilter, IMediaSeeking_iface);
1203 static HRESULT WINAPI testsource_seeking_QueryInterface(IMediaSeeking *iface, REFIID iid, void **out)
1205 struct testfilter *filter = impl_from_IMediaSeeking(iface);
1206 return IBaseFilter_QueryInterface(&filter->filter.IBaseFilter_iface, iid, out);
1209 static ULONG WINAPI testsource_seeking_AddRef(IMediaSeeking *iface)
1211 struct testfilter *filter = impl_from_IMediaSeeking(iface);
1212 return IBaseFilter_AddRef(&filter->filter.IBaseFilter_iface);
1215 static ULONG WINAPI testsource_seeking_Release(IMediaSeeking *iface)
1217 struct testfilter *filter = impl_from_IMediaSeeking(iface);
1218 return IBaseFilter_Release(&filter->filter.IBaseFilter_iface);
1221 static HRESULT WINAPI testsource_seeking_GetCapabilities(IMediaSeeking *iface, DWORD *capabilities)
1223 return E_NOTIMPL;
1226 static HRESULT WINAPI testsource_seeking_CheckCapabilities(IMediaSeeking *iface, DWORD *capabilities)
1228 ok(0, "Unexpected call.\n");
1229 return E_NOTIMPL;
1232 static HRESULT WINAPI testsource_seeking_IsFormatSupported(IMediaSeeking *iface, const GUID *format)
1234 struct testfilter *filter = impl_from_IMediaSeeking(iface);
1236 ok(IsEqualGUID(format, &TIME_FORMAT_MEDIA_TIME),
1237 "Got format %s.\n", wine_dbgstr_guid(format));
1239 return filter->is_format_supported_hr;
1242 static HRESULT WINAPI testsource_seeking_QueryPreferredFormat(IMediaSeeking *iface, GUID *format)
1244 ok(0, "Unexpected call.\n");
1245 return E_NOTIMPL;
1248 static HRESULT WINAPI testsource_seeking_GetTimeFormat(IMediaSeeking *iface, GUID *format)
1250 ok(0, "Unexpected call.\n");
1251 return E_NOTIMPL;
1254 static HRESULT WINAPI testsource_seeking_IsUsingTimeFormat(IMediaSeeking *iface, const GUID *format)
1256 return E_NOTIMPL;
1259 static HRESULT WINAPI testsource_seeking_SetTimeFormat(IMediaSeeking *iface, const GUID *format)
1261 ok(0, "Unexpected call.\n");
1262 return E_NOTIMPL;
1265 static HRESULT WINAPI testsource_seeking_GetDuration(IMediaSeeking *iface, LONGLONG *duration)
1267 struct testfilter *filter = impl_from_IMediaSeeking(iface);
1269 if (SUCCEEDED(filter->get_duration_hr))
1270 *duration = 0x8000000000000000ULL;
1272 return filter->get_duration_hr;
1275 static HRESULT WINAPI testsource_seeking_GetStopPosition(IMediaSeeking *iface, LONGLONG *stop)
1277 struct testfilter *filter = impl_from_IMediaSeeking(iface);
1279 if (SUCCEEDED(filter->get_stop_position_hr))
1280 *stop = 0x8000000000000000ULL;
1282 return filter->get_stop_position_hr;
1285 static HRESULT WINAPI testsource_seeking_GetCurrentPosition(IMediaSeeking *iface, LONGLONG *current)
1287 *current = 0;
1288 return S_OK;
1291 static HRESULT WINAPI testsource_seeking_ConvertTimeFormat(IMediaSeeking *iface, LONGLONG *target,
1292 const GUID *target_format, LONGLONG source, const GUID *source_format)
1294 ok(0, "Unexpected call.\n");
1295 return E_NOTIMPL;
1298 static HRESULT WINAPI testsource_seeking_SetPositions(IMediaSeeking *iface, LONGLONG *current_ptr, DWORD current_flags,
1299 LONGLONG *stop_ptr, DWORD stop_flags)
1301 struct testfilter *filter = impl_from_IMediaSeeking(iface);
1303 if (SUCCEEDED(filter->set_positions_hr))
1305 if (current_ptr)
1306 filter->current_position = *current_ptr;
1308 if (stop_ptr)
1309 filter->stop_position = *stop_ptr;
1312 return filter->set_positions_hr;
1315 static HRESULT WINAPI testsource_seeking_GetPositions(IMediaSeeking *iface, LONGLONG *current, LONGLONG *stop)
1317 ok(0, "Unexpected call.\n");
1318 return E_NOTIMPL;
1321 static HRESULT WINAPI testsource_seeking_GetAvailable(IMediaSeeking *iface, LONGLONG *earliest, LONGLONG *latest)
1323 ok(0, "Unexpected call.\n");
1324 return E_NOTIMPL;
1327 static HRESULT WINAPI testsource_seeking_SetRate(IMediaSeeking *iface, double rate)
1329 ok(0, "Unexpected call.\n");
1330 return E_NOTIMPL;
1333 static HRESULT WINAPI testsource_seeking_GetRate(IMediaSeeking *iface, double *rate)
1335 ok(0, "Unexpected call.\n");
1336 return E_NOTIMPL;
1339 static HRESULT WINAPI testsource_seeking_GetPreroll(IMediaSeeking *iface, LONGLONG *preroll)
1341 ok(0, "Unexpected call.\n");
1342 return E_NOTIMPL;
1345 static const IMediaSeekingVtbl testsource_seeking_vtbl =
1347 testsource_seeking_QueryInterface,
1348 testsource_seeking_AddRef,
1349 testsource_seeking_Release,
1350 testsource_seeking_GetCapabilities,
1351 testsource_seeking_CheckCapabilities,
1352 testsource_seeking_IsFormatSupported,
1353 testsource_seeking_QueryPreferredFormat,
1354 testsource_seeking_GetTimeFormat,
1355 testsource_seeking_IsUsingTimeFormat,
1356 testsource_seeking_SetTimeFormat,
1357 testsource_seeking_GetDuration,
1358 testsource_seeking_GetStopPosition,
1359 testsource_seeking_GetCurrentPosition,
1360 testsource_seeking_ConvertTimeFormat,
1361 testsource_seeking_SetPositions,
1362 testsource_seeking_GetPositions,
1363 testsource_seeking_GetAvailable,
1364 testsource_seeking_SetRate,
1365 testsource_seeking_GetRate,
1366 testsource_seeking_GetPreroll,
1369 static inline struct testfilter *impl_from_IQualityControl(IQualityControl *iface)
1371 return CONTAINING_RECORD(iface, struct testfilter, IQualityControl_iface);
1374 static HRESULT WINAPI testsource_qc_QueryInterface(IQualityControl *iface, REFIID iid, void **out)
1376 struct testfilter *filter = impl_from_IQualityControl(iface);
1377 return IBaseFilter_QueryInterface(&filter->filter.IBaseFilter_iface, iid, out);
1380 static ULONG WINAPI testsource_qc_AddRef(IQualityControl *iface)
1382 struct testfilter *filter = impl_from_IQualityControl(iface);
1383 return IBaseFilter_AddRef(&filter->filter.IBaseFilter_iface);
1386 static ULONG WINAPI testsource_qc_Release(IQualityControl *iface)
1388 struct testfilter *filter = impl_from_IQualityControl(iface);
1389 return IBaseFilter_Release(&filter->filter.IBaseFilter_iface);
1392 static HRESULT WINAPI testsource_qc_Notify(IQualityControl *iface, IBaseFilter *sender, Quality q)
1394 struct testfilter *filter = impl_from_IQualityControl(iface);
1396 filter->qc_notify_sender = sender;
1397 filter->qc_notify_quality = q;
1399 return filter->qc_notify_hr;
1402 static HRESULT WINAPI testsource_qc_SetSink(IQualityControl *iface, IQualityControl *sink)
1404 ok(0, "Unexpected call.\n");
1405 return E_NOTIMPL;
1408 static const IQualityControlVtbl testsource_qc_vtbl =
1410 testsource_qc_QueryInterface,
1411 testsource_qc_AddRef,
1412 testsource_qc_Release,
1413 testsource_qc_Notify,
1414 testsource_qc_SetSink,
1417 #define check_get_stream(a,b,c,d) check_get_stream_(__LINE__,a,b,c,d)
1418 static void check_get_stream_(int line, IAMMultiMediaStream *mmstream,
1419 IMediaStreamFilter *filter, const GUID *mspid, IMediaStream *expect)
1421 IMediaStream *stream = NULL, *stream2 = NULL;
1422 HRESULT hr;
1424 hr = IAMMultiMediaStream_GetMediaStream(mmstream, mspid, &stream);
1425 ok_(__FILE__, line)(hr == (expect ? S_OK : MS_E_NOSTREAM),
1426 "IAMMultiMediaStream::GetMediaStream() returned %#lx.\n", hr);
1427 hr = IMediaStreamFilter_GetMediaStream(filter, mspid, &stream2);
1428 ok_(__FILE__, line)(hr == (expect ? S_OK : MS_E_NOSTREAM),
1429 "IMediaStreamFilter::GetMediaStream() returned %#lx.\n", hr);
1430 if (hr == S_OK)
1432 ok_(__FILE__, line)(stream == expect, "Expected stream %p, got %p.\n", expect, stream);
1433 ok_(__FILE__, line)(stream2 == expect, "Expected stream %p, got %p.\n", expect, stream2);
1436 if (stream) IMediaStream_Release(stream);
1437 if (stream2) IMediaStream_Release(stream2);
1440 static void test_add_stream(void)
1442 IAMMultiMediaStream *mmstream = create_ammultimediastream();
1443 IMediaStream *video_stream, *audio_stream, *stream;
1444 IDirectDrawMediaStream *ddraw_stream;
1445 IMediaStreamFilter *stream_filter;
1446 struct teststream teststream;
1447 IDirectDraw *ddraw, *ddraw2;
1448 IEnumFilters *enum_filters;
1449 IBaseFilter *filters[3];
1450 IGraphBuilder *graph;
1451 FILTER_INFO info;
1452 ULONG ref, count;
1453 CLSID clsid;
1454 HRESULT hr;
1456 teststream_init(&teststream);
1458 hr = IAMMultiMediaStream_GetFilter(mmstream, &stream_filter);
1459 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1461 hr = IAMMultiMediaStream_EnumMediaStreams(mmstream, 0, NULL);
1462 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1463 hr = IMediaStreamFilter_EnumMediaStreams(stream_filter, 0, NULL);
1464 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1466 hr = IAMMultiMediaStream_GetMediaStream(mmstream, &MSPID_PrimaryAudio, NULL);
1467 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
1468 hr = IMediaStreamFilter_GetMediaStream(stream_filter, &MSPID_PrimaryAudio, NULL);
1469 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
1470 hr = IAMMultiMediaStream_GetMediaStream(mmstream, &MSPID_PrimaryVideo, NULL);
1471 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
1472 hr = IMediaStreamFilter_GetMediaStream(stream_filter, &MSPID_PrimaryVideo, NULL);
1473 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
1475 check_enum_stream(mmstream, stream_filter, 0, NULL);
1477 check_get_stream(mmstream, stream_filter, NULL, NULL);
1478 check_get_stream(mmstream, stream_filter, &MSPID_PrimaryAudio, NULL);
1479 check_get_stream(mmstream, stream_filter, &MSPID_PrimaryVideo, NULL);
1480 check_get_stream(mmstream, stream_filter, &test_mspid, NULL);
1482 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &test_mspid, 0, &stream);
1483 ok(hr == MS_E_PURPOSEID, "Got hr %#lx.\n", hr);
1485 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &video_stream);
1486 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1488 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
1489 ok(hr == MS_E_PURPOSEID, "Got hr %#lx.\n", hr);
1491 hr = IAMMultiMediaStream_EnumMediaStreams(mmstream, 0, NULL);
1492 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
1493 hr = IMediaStreamFilter_EnumMediaStreams(stream_filter, 0, NULL);
1494 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
1495 hr = IAMMultiMediaStream_EnumMediaStreams(mmstream, 1, NULL);
1496 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1497 hr = IMediaStreamFilter_EnumMediaStreams(stream_filter, 1, NULL);
1498 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1500 check_enum_stream(mmstream, stream_filter, 0, video_stream);
1501 check_enum_stream(mmstream, stream_filter, 1, NULL);
1503 check_get_stream(mmstream, stream_filter, &MSPID_PrimaryVideo, video_stream);
1504 check_get_stream(mmstream, stream_filter, &MSPID_PrimaryAudio, NULL);
1505 check_get_stream(mmstream, stream_filter, &test_mspid, NULL);
1507 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &audio_stream);
1508 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1510 check_enum_stream(mmstream, stream_filter, 0, video_stream);
1511 check_enum_stream(mmstream, stream_filter, 1, audio_stream);
1512 check_enum_stream(mmstream, stream_filter, 2, NULL);
1514 check_get_stream(mmstream, stream_filter, &MSPID_PrimaryVideo, video_stream);
1515 check_get_stream(mmstream, stream_filter, &MSPID_PrimaryAudio, audio_stream);
1516 check_get_stream(mmstream, stream_filter, &test_mspid, NULL);
1518 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)&teststream, &IID_IUnknown, 0, &stream);
1519 ok(hr == MS_E_PURPOSEID, "Got hr %#lx.\n", hr);
1521 hr = IMediaStreamFilter_QueryFilterInfo(stream_filter, &info);
1522 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1524 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)&teststream, &test_mspid, 0, &stream);
1525 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1526 ok(stream == (IMediaStream *)&teststream, "Streams didn't match.\n");
1527 IMediaStream_Release(stream);
1528 ok(teststream.mmstream == mmstream, "IAMMultiMediaStream objects didn't match.\n");
1529 ok(teststream.filter == stream_filter, "IMediaStreamFilter objects didn't match.\n");
1530 ok(teststream.graph == info.pGraph, "IFilterGraph objects didn't match.\n");
1532 IFilterGraph_Release(info.pGraph);
1534 check_enum_stream(mmstream, stream_filter, 0, video_stream);
1535 check_enum_stream(mmstream, stream_filter, 1, audio_stream);
1536 check_enum_stream(mmstream, stream_filter, 2, (IMediaStream *)&teststream);
1537 check_enum_stream(mmstream, stream_filter, 3, NULL);
1539 check_get_stream(mmstream, stream_filter, &MSPID_PrimaryVideo, video_stream);
1540 check_get_stream(mmstream, stream_filter, &MSPID_PrimaryAudio, audio_stream);
1541 check_get_stream(mmstream, stream_filter, &test_mspid, (IMediaStream *)&teststream);
1543 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
1544 ok(hr == MS_E_PURPOSEID, "Got hr %#lx.\n", hr);
1546 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
1547 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1548 ok(!!graph, "Expected a non-NULL graph.\n");
1550 hr = IGraphBuilder_EnumFilters(graph, &enum_filters);
1551 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1552 hr = IEnumFilters_Next(enum_filters, 3, filters, &count);
1553 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1554 ok(count == 1, "Got count %lu.\n", count);
1555 ok(filters[0] == (IBaseFilter *)stream_filter,
1556 "Expected filter %p, got %p.\n", stream_filter, filters[0]);
1557 IBaseFilter_Release(filters[0]);
1558 IEnumFilters_Release(enum_filters);
1559 IGraphBuilder_Release(graph);
1561 IMediaStreamFilter_Release(stream_filter);
1562 ref = IAMMultiMediaStream_Release(mmstream);
1563 ok(!ref, "Got outstanding refcount %ld.\n", ref);
1564 ref = IMediaStream_Release(video_stream);
1565 ok(!ref, "Got outstanding refcount %ld.\n", ref);
1566 ref = IMediaStream_Release(audio_stream);
1567 ok(!ref, "Got outstanding refcount %ld.\n", ref);
1568 ok(teststream.refcount == 1, "Got outstanding refcount %ld.\n", teststream.refcount);
1570 /* The return parameter is optional. */
1572 mmstream = create_ammultimediastream();
1574 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, NULL);
1575 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1577 hr = IAMMultiMediaStream_GetMediaStream(mmstream, &MSPID_PrimaryVideo, &stream);
1578 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1579 IMediaStream_Release(stream);
1581 ref = IAMMultiMediaStream_Release(mmstream);
1582 ok(!ref, "Got outstanding refcount %ld.\n", ref);
1584 /* Test supplying a DirectDraw object with the primary video stream. */
1586 hr = DirectDrawCreate(NULL, &ddraw, NULL);
1587 ok(hr == DD_OK, "Got hr %#lx.\n", hr);
1588 mmstream = create_ammultimediastream();
1590 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)ddraw, &MSPID_PrimaryVideo, 0, &video_stream);
1591 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1593 hr = IMediaStream_QueryInterface(video_stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
1594 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1595 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw2);
1596 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1597 ok(ddraw2 == ddraw, "Expected IDirectDraw %p, got %p.\n", ddraw, ddraw2);
1598 IDirectDraw_Release(ddraw2);
1599 IDirectDrawMediaStream_Release(ddraw_stream);
1601 ref = IAMMultiMediaStream_Release(mmstream);
1602 ok(!ref, "Got outstanding refcount %ld.\n", ref);
1603 ref = IMediaStream_Release(video_stream);
1604 ok(!ref, "Got outstanding refcount %ld.\n", ref);
1605 ref = IDirectDraw_Release(ddraw);
1606 ok(!ref, "Got outstanding refcount %ld.\n", ref);
1608 mmstream = create_ammultimediastream();
1610 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &video_stream);
1611 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1613 hr = IMediaStream_QueryInterface(video_stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
1614 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1615 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw);
1616 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1617 ok(!!ddraw, "Expected a non-NULL IDirectDraw.\n");
1618 IDirectDraw_Release(ddraw);
1619 IDirectDrawMediaStream_Release(ddraw_stream);
1621 ref = IAMMultiMediaStream_Release(mmstream);
1622 ok(!ref, "Got outstanding refcount %ld.\n", ref);
1623 ref = IMediaStream_Release(video_stream);
1624 ok(!ref, "Got outstanding refcount %ld.\n", ref);
1626 /* Test the AMMSF_ADDDEFAULTRENDERER flag. No stream is added; however, a
1627 * new filter will be added to the graph. */
1629 mmstream = create_ammultimediastream();
1630 hr = IAMMultiMediaStream_GetFilter(mmstream, &stream_filter);
1631 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1633 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo,
1634 AMMSF_ADDDEFAULTRENDERER, &video_stream);
1635 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
1637 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo,
1638 AMMSF_ADDDEFAULTRENDERER, NULL);
1639 ok(hr == MS_E_PURPOSEID, "Got hr %#lx.\n", hr);
1641 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio,
1642 AMMSF_ADDDEFAULTRENDERER, &audio_stream);
1643 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
1645 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio,
1646 AMMSF_ADDDEFAULTRENDERER, NULL);
1647 ok(hr == S_OK || hr == VFW_E_NO_AUDIO_HARDWARE, "Got hr %#lx.\n", hr);
1649 check_enum_stream(mmstream, stream_filter, 0, NULL);
1651 check_get_stream(mmstream, stream_filter, &MSPID_PrimaryAudio, NULL);
1652 check_get_stream(mmstream, stream_filter, &MSPID_PrimaryVideo, NULL);
1654 if (hr == S_OK)
1656 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
1657 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1658 ok(!!graph, "Got graph %p.\n", graph);
1659 hr = IGraphBuilder_EnumFilters(graph, &enum_filters);
1660 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1661 hr = IEnumFilters_Next(enum_filters, 3, filters, &count);
1662 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1663 ok(count == 2, "Got count %lu.\n", count);
1664 ok(filters[1] == (IBaseFilter *)stream_filter,
1665 "Expected filter %p, got %p.\n", stream_filter, filters[1]);
1666 hr = IBaseFilter_GetClassID(filters[0], &clsid);
1667 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1668 ok(IsEqualGUID(&clsid, &CLSID_DSoundRender), "Got unexpected filter %s.\n", wine_dbgstr_guid(&clsid));
1669 IBaseFilter_Release(filters[0]);
1670 IBaseFilter_Release(filters[1]);
1671 IEnumFilters_Release(enum_filters);
1672 IGraphBuilder_Release(graph);
1675 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &test_mspid,
1676 AMMSF_ADDDEFAULTRENDERER, NULL);
1677 ok(hr == MS_E_PURPOSEID, "Got hr %#lx.\n", hr);
1678 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &test_mspid,
1679 AMMSF_ADDDEFAULTRENDERER, &audio_stream);
1680 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
1682 ref = IAMMultiMediaStream_Release(mmstream);
1683 ok(!ref, "Got outstanding refcount %ld.\n", ref);
1684 ref = IMediaStreamFilter_Release(stream_filter);
1685 ok(!ref, "Got outstanding refcount %ld.\n", ref);
1688 static void test_media_streams(void)
1690 IAMMultiMediaStream *pams;
1691 HRESULT hr;
1692 IMediaStream *video_stream = NULL;
1693 IMediaStream *audio_stream = NULL;
1694 IMediaStreamFilter* media_stream_filter = NULL;
1696 if (!(pams = create_ammultimediastream()))
1697 return;
1699 hr = IAMMultiMediaStream_Initialize(pams, STREAMTYPE_READ, 0, NULL);
1700 ok(hr == S_OK, "IAMMultiMediaStream_Initialize returned: %lx\n", hr);
1702 /* Retrieve media stream filter */
1703 hr = IAMMultiMediaStream_GetFilter(pams, NULL);
1704 ok(hr == E_POINTER, "IAMMultiMediaStream_GetFilter returned: %lx\n", hr);
1705 hr = IAMMultiMediaStream_GetFilter(pams, &media_stream_filter);
1706 ok(hr == S_OK, "IAMMultiMediaStream_GetFilter returned: %lx\n", hr);
1708 hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &MSPID_PrimaryVideo, 0, NULL);
1709 ok(hr == S_OK, "IAMMultiMediaStream_AddMediaStream returned: %lx\n", hr);
1710 hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryVideo, &video_stream);
1711 ok(hr == S_OK, "IAMMultiMediaStream_GetMediaStream returned: %lx\n", hr);
1713 /* Check interfaces and samples for video */
1714 if (video_stream)
1716 IAMMediaStream* am_media_stream;
1717 IMultiMediaStream *multi_media_stream;
1718 IPin *pin = NULL;
1719 IAudioMediaStream* audio_media_stream;
1720 IDirectDrawMediaStream *ddraw_stream = NULL;
1721 IDirectDrawStreamSample *ddraw_sample = NULL;
1723 hr = IMediaStream_QueryInterface(video_stream, &IID_IAMMediaStream, (LPVOID*)&am_media_stream);
1724 ok(hr == S_OK, "IMediaStream_QueryInterface returned: %lx\n", hr);
1725 ok((void*)am_media_stream == (void*)video_stream, "Not same interface, got %p expected %p\n", am_media_stream, video_stream);
1727 hr = IAMMediaStream_GetMultiMediaStream(am_media_stream, NULL);
1728 ok(hr == E_POINTER, "Expected E_POINTER, got %lx\n", hr);
1730 multi_media_stream = (void *)0xdeadbeef;
1731 hr = IAMMediaStream_GetMultiMediaStream(am_media_stream, &multi_media_stream);
1732 ok(hr == S_OK, "IAMMediaStream_GetMultiMediaStream returned: %lx\n", hr);
1733 ok((void *)multi_media_stream == (void *)pams, "Expected %p, got %p\n", pams, multi_media_stream);
1734 IMultiMediaStream_Release(multi_media_stream);
1736 IAMMediaStream_Release(am_media_stream);
1738 hr = IMediaStream_QueryInterface(video_stream, &IID_IPin, (void **)&pin);
1739 ok(hr == S_OK, "IMediaStream_QueryInterface returned: %lx\n", hr);
1741 IPin_Release(pin);
1743 hr = IMediaStream_QueryInterface(video_stream, &IID_IAudioMediaStream, (LPVOID*)&audio_media_stream);
1744 ok(hr == E_NOINTERFACE, "IMediaStream_QueryInterface returned: %lx\n", hr);
1746 hr = IMediaStream_QueryInterface(video_stream, &IID_IDirectDrawMediaStream, (LPVOID*)&ddraw_stream);
1747 ok(hr == S_OK, "IMediaStream_QueryInterface returned: %lx\n", hr);
1749 if (SUCCEEDED(hr))
1751 DDSURFACEDESC current_format, desired_format;
1752 IDirectDrawPalette *palette;
1753 DWORD flags;
1755 hr = IDirectDrawMediaStream_GetFormat(ddraw_stream, &current_format, &palette, &desired_format, &flags);
1756 ok(hr == MS_E_NOSTREAM, "IDirectDrawoMediaStream_GetFormat returned: %lx\n", hr);
1758 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &ddraw_sample);
1759 ok(hr == S_OK, "IDirectDrawMediaStream_CreateSample returned: %lx\n", hr);
1761 hr = IDirectDrawMediaStream_GetMultiMediaStream(ddraw_stream, NULL);
1762 ok(hr == E_POINTER, "Expected E_POINTER, got %lx\n", hr);
1764 multi_media_stream = (void *)0xdeadbeef;
1765 hr = IDirectDrawMediaStream_GetMultiMediaStream(ddraw_stream, &multi_media_stream);
1766 ok(hr == S_OK, "IDirectDrawMediaStream_GetMultiMediaStream returned: %lx\n", hr);
1767 ok((void *)multi_media_stream == (void *)pams, "Expected %p, got %p\n", pams, multi_media_stream);
1768 IMultiMediaStream_Release(multi_media_stream);
1771 if (ddraw_sample)
1772 IDirectDrawStreamSample_Release(ddraw_sample);
1773 if (ddraw_stream)
1774 IDirectDrawMediaStream_Release(ddraw_stream);
1777 hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &MSPID_PrimaryAudio, 0, NULL);
1778 ok(hr == S_OK, "IAMMultiMediaStream_AddMediaStream returned: %lx\n", hr);
1779 hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryAudio, &audio_stream);
1780 ok(hr == S_OK, "IAMMultiMediaStream_GetMediaStream returned: %lx\n", hr);
1782 /* Check interfaces and samples for audio */
1783 if (audio_stream)
1785 IAMMediaStream* am_media_stream;
1786 IMultiMediaStream *multi_media_stream;
1787 IPin *pin = NULL;
1788 IDirectDrawMediaStream* ddraw_stream = NULL;
1789 IAudioMediaStream* audio_media_stream = NULL;
1790 IAudioStreamSample *audio_sample = NULL;
1792 hr = IMediaStream_QueryInterface(audio_stream, &IID_IAMMediaStream, (LPVOID*)&am_media_stream);
1793 ok(hr == S_OK, "IMediaStream_QueryInterface returned: %lx\n", hr);
1794 ok((void*)am_media_stream == (void*)audio_stream, "Not same interface, got %p expected %p\n", am_media_stream, audio_stream);
1796 hr = IAMMediaStream_GetMultiMediaStream(am_media_stream, NULL);
1797 ok(hr == E_POINTER, "Expected E_POINTER, got %lx\n", hr);
1799 multi_media_stream = (void *)0xdeadbeef;
1800 hr = IAMMediaStream_GetMultiMediaStream(am_media_stream, &multi_media_stream);
1801 ok(hr == S_OK, "IAMMediaStream_GetMultiMediaStream returned: %lx\n", hr);
1802 ok((void *)multi_media_stream == (void *)pams, "Expected %p, got %p\n", pams, multi_media_stream);
1803 IMultiMediaStream_Release(multi_media_stream);
1805 IAMMediaStream_Release(am_media_stream);
1807 hr = IMediaStream_QueryInterface(audio_stream, &IID_IPin, (void **)&pin);
1808 ok(hr == S_OK, "IMediaStream_QueryInterface returned: %lx\n", hr);
1810 IPin_Release(pin);
1812 hr = IMediaStream_QueryInterface(audio_stream, &IID_IDirectDrawMediaStream, (LPVOID*)&ddraw_stream);
1813 ok(hr == E_NOINTERFACE, "IMediaStream_QueryInterface returned: %lx\n", hr);
1815 hr = IMediaStream_QueryInterface(audio_stream, &IID_IAudioMediaStream, (LPVOID*)&audio_media_stream);
1816 ok(hr == S_OK, "IMediaStream_QueryInterface returned: %lx\n", hr);
1818 if (SUCCEEDED(hr))
1820 IAudioData* audio_data = NULL;
1822 hr = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER, &IID_IAudioData, (void **)&audio_data);
1823 ok(hr == S_OK, "CoCreateInstance returned: %lx\n", hr);
1825 hr = IAudioMediaStream_CreateSample(audio_media_stream, NULL, 0, &audio_sample);
1826 ok(hr == E_POINTER, "IAudioMediaStream_CreateSample returned: %lx\n", hr);
1828 EXPECT_REF(audio_stream, 3);
1829 EXPECT_REF(audio_data, 1);
1830 hr = IAudioMediaStream_CreateSample(audio_media_stream, audio_data, 0, &audio_sample);
1831 ok(hr == S_OK, "IAudioMediaStream_CreateSample returned: %lx\n", hr);
1832 EXPECT_REF(audio_stream, 4);
1833 EXPECT_REF(audio_data, 2);
1835 hr = IAudioMediaStream_GetMultiMediaStream(audio_media_stream, NULL);
1836 ok(hr == E_POINTER, "Expected E_POINTER, got %lx\n", hr);
1838 multi_media_stream = (void *)0xdeadbeef;
1839 hr = IAudioMediaStream_GetMultiMediaStream(audio_media_stream, &multi_media_stream);
1840 ok(hr == S_OK, "IAudioMediaStream_GetMultiMediaStream returned: %lx\n", hr);
1841 ok((void *)multi_media_stream == (void *)pams, "Expected %p, got %p\n", pams, multi_media_stream);
1842 IMultiMediaStream_Release(multi_media_stream);
1844 if (audio_data)
1845 IAudioData_Release(audio_data);
1846 if (audio_sample)
1847 IAudioStreamSample_Release(audio_sample);
1848 if (audio_media_stream)
1849 IAudioMediaStream_Release(audio_media_stream);
1853 if (media_stream_filter)
1855 IEnumPins *enum_pins;
1857 hr = IMediaStreamFilter_EnumPins(media_stream_filter, &enum_pins);
1858 ok(hr == S_OK, "IBaseFilter_EnumPins returned: %lx\n", hr);
1859 if (hr == S_OK)
1861 IPin* pins[3] = { NULL, NULL, NULL };
1862 ULONG nb_pins;
1863 ULONG expected_nb_pins = audio_stream ? 2 : 1;
1864 int i;
1866 hr = IEnumPins_Next(enum_pins, 3, pins, &nb_pins);
1867 ok(SUCCEEDED(hr), "IEnumPins_Next returned: %lx\n", hr);
1868 ok(nb_pins == expected_nb_pins, "Number of pins is %lu instead of %lu\n", nb_pins, expected_nb_pins);
1869 for (i = 0; i < min(nb_pins, expected_nb_pins); i++)
1871 IPin* pin;
1873 hr = IPin_ConnectedTo(pins[i], &pin);
1874 ok(hr == VFW_E_NOT_CONNECTED, "IPin_ConnectedTo returned: %lx\n", hr);
1875 IPin_Release(pins[i]);
1877 IEnumPins_Release(enum_pins);
1881 /* Test open file with no filename */
1882 hr = IAMMultiMediaStream_OpenFile(pams, NULL, AMMSF_RENDERTOEXISTING);
1883 ok(hr == E_POINTER, "IAMMultiMediaStream_OpenFile returned %lx instead of %lx\n", hr, E_POINTER);
1885 if (video_stream)
1886 IMediaStream_Release(video_stream);
1887 if (audio_stream)
1888 IMediaStream_Release(audio_stream);
1889 if (media_stream_filter)
1890 IMediaStreamFilter_Release(media_stream_filter);
1892 IAMMultiMediaStream_Release(pams);
1895 static void test_enum_pins(void)
1897 IAMMultiMediaStream *mmstream = create_ammultimediastream();
1898 IMediaStream *stream0, *stream1;
1899 IPin *pins[3], *pin0, *pin1;
1900 IMediaStreamFilter *filter;
1901 IEnumPins *enum1, *enum2;
1902 ULONG ref, count;
1903 HRESULT hr;
1905 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
1906 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1908 ref = get_refcount(filter);
1909 ok(ref == 3, "Got unexpected refcount %ld.\n", ref);
1911 hr = IMediaStreamFilter_EnumPins(filter, NULL);
1912 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
1914 hr = IMediaStreamFilter_EnumPins(filter, &enum1);
1915 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1916 ref = get_refcount(filter);
1917 ok(ref == 3, "Got unexpected refcount %ld.\n", ref);
1918 ref = get_refcount(enum1);
1919 ok(ref == 1, "Got unexpected refcount %ld.\n", ref);
1921 hr = IEnumPins_Next(enum1, 1, NULL, NULL);
1922 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
1924 hr = IEnumPins_Next(enum1, 1, pins, NULL);
1925 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1927 hr = IEnumPins_Reset(enum1);
1928 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1930 hr = IEnumPins_Skip(enum1, 0);
1931 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1933 hr = IEnumPins_Skip(enum1, 1);
1934 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1936 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream0);
1937 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1938 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream1);
1939 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1940 hr = IMediaStream_QueryInterface(stream0, &IID_IPin, (void **)&pin0);
1941 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1942 hr = IMediaStream_QueryInterface(stream1, &IID_IPin, (void **)&pin1);
1943 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1945 /* Reset() isn't enough; we have to call EnumPins() again to see the updated
1946 * pin count. */
1947 hr = IEnumPins_Reset(enum1);
1948 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1950 hr = IEnumPins_Next(enum1, 1, pins, NULL);
1951 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1953 IEnumPins_Release(enum1);
1955 hr = IMediaStreamFilter_EnumPins(filter, &enum1);
1956 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1958 ref = get_refcount(filter);
1959 ok(ref == 4, "Got unexpected refcount %ld.\n", ref);
1960 ref = get_refcount(enum1);
1961 ok(ref == 1, "Got unexpected refcount %ld.\n", ref);
1962 ref = get_refcount(pin0);
1963 ok(ref == 4, "Got unexpected refcount %ld.\n", ref);
1964 ref = get_refcount(pin1);
1965 ok(ref == 4, "Got unexpected refcount %ld.\n", ref);
1967 hr = IEnumPins_Next(enum1, 1, pins, NULL);
1968 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1969 ok(pins[0] == pin0, "Expected pin %p, got %p.\n", pin0, pins[0]);
1970 ref = get_refcount(filter);
1971 ok(ref == 4, "Got unexpected refcount %ld.\n", ref);
1972 ref = get_refcount(enum1);
1973 ok(ref == 1, "Got unexpected refcount %ld.\n", ref);
1974 ref = get_refcount(pin0);
1975 ok(ref == 5, "Got unexpected refcount %ld.\n", ref);
1976 IPin_Release(pins[0]);
1978 hr = IEnumPins_Next(enum1, 1, pins, NULL);
1979 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1980 ok(pins[0] == pin1, "Expected pin %p, got %p.\n", pin1, pins[0]);
1981 ref = get_refcount(filter);
1982 ok(ref == 4, "Got unexpected refcount %ld.\n", ref);
1983 ref = get_refcount(enum1);
1984 ok(ref == 1, "Got unexpected refcount %ld.\n", ref);
1985 ref = get_refcount(pin1);
1986 ok(ref == 5, "Got unexpected refcount %ld.\n", ref);
1987 IPin_Release(pins[0]);
1989 hr = IEnumPins_Next(enum1, 1, pins, NULL);
1990 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
1992 hr = IEnumPins_Reset(enum1);
1993 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1995 hr = IEnumPins_Next(enum1, 1, pins, &count);
1996 ok(hr == S_OK, "Got hr %#lx.\n", hr);
1997 ok(count == 1, "Got count %lu.\n", count);
1998 ok(pins[0] == pin0, "Expected pin %p, got %p.\n", pin0, pins[0]);
1999 IPin_Release(pins[0]);
2001 hr = IEnumPins_Next(enum1, 1, pins, &count);
2002 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2003 ok(count == 1, "Got count %lu.\n", count);
2004 ok(pins[0] == pin1, "Expected pin %p, got %p.\n", pin1, pins[0]);
2005 IPin_Release(pins[0]);
2007 hr = IEnumPins_Reset(enum1);
2008 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2010 hr = IEnumPins_Next(enum1, 3, pins, NULL);
2011 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
2013 hr = IEnumPins_Next(enum1, 3, pins, &count);
2014 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
2015 ok(count == 2, "Got count %lu.\n", count);
2016 ok(pins[0] == pin0, "Expected pin %p, got %p.\n", pin0, pins[0]);
2017 ok(pins[1] == pin1, "Expected pin %p, got %p.\n", pin1, pins[1]);
2018 IPin_Release(pins[0]);
2019 IPin_Release(pins[1]);
2021 hr = IEnumPins_Reset(enum1);
2022 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2024 hr = IEnumPins_Clone(enum1, &enum2);
2025 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2027 hr = IEnumPins_Skip(enum1, 0);
2028 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2030 hr = IEnumPins_Skip(enum1, 2);
2031 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
2033 hr = IEnumPins_Next(enum1, 1, pins, NULL);
2034 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
2036 hr = IEnumPins_Next(enum2, 1, pins, NULL);
2037 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2038 ok(pins[0] == pin0, "Expected pin %p, got %p.\n", pin0, pins[0]);
2039 IPin_Release(pins[0]);
2041 hr = IEnumPins_Next(enum2, 1, pins, NULL);
2042 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2043 ok(pins[0] == pin1, "Expected pin %p, got %p.\n", pin1, pins[0]);
2044 IPin_Release(pins[0]);
2046 IEnumPins_Release(enum2);
2047 IEnumPins_Release(enum1);
2049 IMediaStreamFilter_Release(filter);
2050 ref = IAMMultiMediaStream_Release(mmstream);
2051 ok(!ref, "Got outstanding refcount %ld.\n", ref);
2052 IMediaStream_Release(stream1);
2053 IMediaStream_Release(stream0);
2054 ref = IPin_Release(pin1);
2055 ok(!ref, "Got outstanding refcount %ld.\n", ref);
2056 ref = IPin_Release(pin0);
2057 ok(!ref, "Got outstanding refcount %ld.\n", ref);
2060 static void test_find_pin(void)
2062 IAMMultiMediaStream *mmstream = create_ammultimediastream();
2063 IMediaStreamFilter *filter;
2064 IMediaStream *stream;
2065 IPin *pin, *pin2;
2066 HRESULT hr;
2067 ULONG ref;
2069 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
2070 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2072 hr = IMediaStreamFilter_FindPin(filter, primary_video_sink_id, &pin2);
2073 ok(hr == VFW_E_NOT_FOUND, "Got hr %#lx.\n", hr);
2075 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
2076 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2077 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
2078 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2080 hr = IMediaStreamFilter_FindPin(filter, primary_video_sink_id, &pin2);
2081 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2082 ok(pin2 == pin, "Expected pin %p, got %p.\n", pin, pin2);
2084 IPin_Release(pin2);
2085 IPin_Release(pin);
2086 IMediaStream_Release(stream);
2087 IMediaStreamFilter_Release(filter);
2088 ref = IAMMultiMediaStream_Release(mmstream);
2089 ok(!ref, "Got outstanding refcount %ld.\n", ref);
2092 static void test_pin_info(void)
2094 IAMMultiMediaStream *mmstream = create_ammultimediastream();
2095 IMediaStreamFilter *filter;
2096 IMediaStream *stream;
2097 PIN_DIRECTION dir;
2098 ULONG ref, count;
2099 PIN_INFO info;
2100 HRESULT hr;
2101 WCHAR *id;
2102 IPin *pin;
2104 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
2105 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2107 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
2108 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2109 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
2110 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2112 hr = IPin_QueryPinInfo(pin, &info);
2113 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2114 ok(info.pFilter == (IBaseFilter *)filter, "Expected filter %p, got %p.\n", filter, info.pFilter);
2115 ok(info.dir == PINDIR_INPUT, "Got direction %d.\n", info.dir);
2116 ok(!wcscmp(info.achName, primary_video_sink_id), "Got name %s.\n", wine_dbgstr_w(info.achName));
2117 IBaseFilter_Release(info.pFilter);
2119 hr = IPin_QueryDirection(pin, &dir);
2120 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2121 ok(dir == PINDIR_INPUT, "Got direction %d.\n", dir);
2123 hr = IPin_QueryId(pin, &id);
2124 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2125 ok(!wcscmp(id, primary_video_sink_id), "Got id %s.\n", wine_dbgstr_w(id));
2126 CoTaskMemFree(id);
2128 hr = IPin_QueryInternalConnections(pin, NULL, &count);
2129 ok(hr == E_NOTIMPL, "Got hr %#lx.\n", hr);
2131 IPin_Release(pin);
2132 IMediaStream_Release(stream);
2134 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
2135 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2136 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
2137 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2139 hr = IPin_QueryPinInfo(pin, &info);
2140 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2141 ok(info.pFilter == (IBaseFilter *)filter, "Expected filter %p, got %p.\n", filter, info.pFilter);
2142 ok(info.dir == PINDIR_INPUT, "Got direction %d.\n", info.dir);
2143 ok(!wcscmp(info.achName, primary_audio_sink_id), "Got name %s.\n", wine_dbgstr_w(info.achName));
2144 IBaseFilter_Release(info.pFilter);
2146 hr = IPin_QueryDirection(pin, &dir);
2147 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2148 ok(dir == PINDIR_INPUT, "Got direction %d.\n", dir);
2150 hr = IPin_QueryId(pin, &id);
2151 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2152 ok(!wcscmp(id, primary_audio_sink_id), "Got id %s.\n", wine_dbgstr_w(id));
2153 CoTaskMemFree(id);
2155 hr = IPin_QueryInternalConnections(pin, NULL, &count);
2156 ok(hr == E_NOTIMPL, "Got hr %#lx.\n", hr);
2158 IPin_Release(pin);
2159 IMediaStream_Release(stream);
2161 IMediaStreamFilter_Release(filter);
2162 ref = IAMMultiMediaStream_Release(mmstream);
2163 ok(!ref, "Got outstanding refcount %ld.\n", ref);
2166 struct graph
2168 IFilterGraph2 IFilterGraph2_iface;
2169 IMediaEventSink IMediaEventSink_iface;
2170 IUnknown *inner_unk;
2171 IFilterGraph2 *inner;
2172 IMediaEventSink *inner_event_sink;
2173 LONG refcount;
2174 unsigned int got_add_filter;
2175 IBaseFilter *filter;
2176 WCHAR filter_name[128];
2177 unsigned int got_notify;
2178 LONG event_code;
2179 LONG_PTR event_param1;
2180 LONG_PTR event_param2;
2183 static struct graph *impl_from_IFilterGraph2(IFilterGraph2 *iface)
2185 return CONTAINING_RECORD(iface, struct graph, IFilterGraph2_iface);
2188 static struct graph *impl_from_IMediaEventSink(IMediaEventSink *iface)
2190 return CONTAINING_RECORD(iface, struct graph, IMediaEventSink_iface);
2193 static HRESULT WINAPI graph_QueryInterface(IFilterGraph2 *iface, REFIID iid, void **out)
2195 struct graph *graph = impl_from_IFilterGraph2(iface);
2196 if (winetest_debug > 1) trace("QueryInterface(%s)\n", wine_dbgstr_guid(iid));
2197 if (IsEqualGUID(iid, &IID_IFilterGraph2)
2198 || IsEqualGUID(iid, &IID_IGraphBuilder)
2199 || IsEqualGUID(iid, &IID_IFilterGraph)
2200 || IsEqualGUID(iid, &IID_IUnknown))
2202 *out = iface;
2203 IFilterGraph2_AddRef(iface);
2204 return S_OK;
2206 else if (IsEqualGUID(iid, &IID_IMediaEventSink))
2208 *out = &graph->IMediaEventSink_iface;
2209 IFilterGraph2_AddRef(iface);
2210 return S_OK;
2212 else
2214 return IUnknown_QueryInterface(graph->inner_unk, iid, out);
2216 return E_NOINTERFACE;
2219 static ULONG WINAPI graph_AddRef(IFilterGraph2 *iface)
2221 struct graph *graph = impl_from_IFilterGraph2(iface);
2222 return InterlockedIncrement(&graph->refcount);
2225 static ULONG WINAPI graph_Release(IFilterGraph2 *iface)
2227 struct graph *graph = impl_from_IFilterGraph2(iface);
2228 return InterlockedDecrement(&graph->refcount);
2231 static HRESULT WINAPI graph_AddFilter(IFilterGraph2 *iface, IBaseFilter *filter, const WCHAR *name)
2233 struct graph *graph = impl_from_IFilterGraph2(iface);
2234 if (winetest_debug > 1) trace("AddFilter(%p, %s)\n", filter, wine_dbgstr_w(name));
2235 ++graph->got_add_filter;
2236 graph->filter = filter;
2237 if (name)
2238 wcscpy(graph->filter_name, name);
2239 else
2240 graph->filter_name[0] = 0;
2241 return IFilterGraph2_AddFilter(graph->inner, filter, name);
2244 static HRESULT WINAPI graph_RemoveFilter(IFilterGraph2 *iface, IBaseFilter *filter)
2246 ok(0, "Unexpected call.\n");
2247 return E_NOTIMPL;
2250 static HRESULT WINAPI graph_EnumFilters(IFilterGraph2 *iface, IEnumFilters **enumfilters)
2252 struct graph *graph = impl_from_IFilterGraph2(iface);
2253 if (winetest_debug > 1) trace("EnumFilters()\n");
2254 return IFilterGraph2_EnumFilters(graph->inner, enumfilters);
2257 static HRESULT WINAPI graph_FindFilterByName(IFilterGraph2 *iface, const WCHAR *name, IBaseFilter **filter)
2259 ok(0, "Unexpected call.\n");
2260 return E_NOTIMPL;
2263 static HRESULT WINAPI graph_ConnectDirect(IFilterGraph2 *iface, IPin *source, IPin *sink, const AM_MEDIA_TYPE *mt)
2265 struct graph *graph = impl_from_IFilterGraph2(iface);
2266 return IFilterGraph2_ConnectDirect(graph->inner, source, sink, mt);
2269 static HRESULT WINAPI graph_Reconnect(IFilterGraph2 *iface, IPin *pin)
2271 ok(0, "Unexpected call.\n");
2272 return E_NOTIMPL;
2275 static HRESULT WINAPI graph_Disconnect(IFilterGraph2 *iface, IPin *pin)
2277 struct graph *graph = impl_from_IFilterGraph2(iface);
2278 return IFilterGraph2_Disconnect(graph->inner, pin);
2281 static HRESULT WINAPI graph_SetDefaultSyncSource(IFilterGraph2 *iface)
2283 ok(0, "Unexpected call.\n");
2284 return E_NOTIMPL;
2287 static HRESULT WINAPI graph_Connect(IFilterGraph2 *iface, IPin *source, IPin *sink)
2289 ok(0, "Unexpected call.\n");
2290 return E_NOTIMPL;
2293 static HRESULT WINAPI graph_Render(IFilterGraph2 *iface, IPin *source)
2295 ok(0, "Unexpected call.\n");
2296 return E_NOTIMPL;
2299 static HRESULT WINAPI graph_RenderFile(IFilterGraph2 *iface, const WCHAR *filename, const WCHAR *playlist)
2301 ok(0, "Unexpected call.\n");
2302 return E_NOTIMPL;
2305 static HRESULT WINAPI graph_AddSourceFilter(IFilterGraph2 *iface,
2306 const WCHAR *filename, const WCHAR *filter_name, IBaseFilter **filter)
2308 ok(0, "Unexpected call.\n");
2309 return E_NOTIMPL;
2312 static HRESULT WINAPI graph_SetLogFile(IFilterGraph2 *iface, DWORD_PTR file)
2314 ok(0, "Unexpected call.\n");
2315 return E_NOTIMPL;
2318 static HRESULT WINAPI graph_Abort(IFilterGraph2 *iface)
2320 ok(0, "Unexpected call.\n");
2321 return E_NOTIMPL;
2324 static HRESULT WINAPI graph_ShouldOperationContinue(IFilterGraph2 *iface)
2326 ok(0, "Unexpected call.\n");
2327 return E_NOTIMPL;
2330 static HRESULT WINAPI graph_AddSourceFilterForMoniker(IFilterGraph2 *iface,
2331 IMoniker *moniker, IBindCtx *bind_ctx, const WCHAR *filter_name, IBaseFilter **filter)
2333 ok(0, "Unexpected call.\n");
2334 return E_NOTIMPL;
2337 static HRESULT WINAPI graph_ReconnectEx(IFilterGraph2 *iface, IPin *pin, const AM_MEDIA_TYPE *mt)
2339 ok(0, "Unexpected call.\n");
2340 return E_NOTIMPL;
2343 static HRESULT WINAPI graph_RenderEx(IFilterGraph2 *iface, IPin *pin, DWORD flags, DWORD *context)
2345 ok(0, "Unexpected call.\n");
2346 return E_NOTIMPL;
2349 static const IFilterGraph2Vtbl graph_vtbl =
2351 graph_QueryInterface,
2352 graph_AddRef,
2353 graph_Release,
2354 graph_AddFilter,
2355 graph_RemoveFilter,
2356 graph_EnumFilters,
2357 graph_FindFilterByName,
2358 graph_ConnectDirect,
2359 graph_Reconnect,
2360 graph_Disconnect,
2361 graph_SetDefaultSyncSource,
2362 graph_Connect,
2363 graph_Render,
2364 graph_RenderFile,
2365 graph_AddSourceFilter,
2366 graph_SetLogFile,
2367 graph_Abort,
2368 graph_ShouldOperationContinue,
2369 graph_AddSourceFilterForMoniker,
2370 graph_ReconnectEx,
2371 graph_RenderEx,
2374 static HRESULT WINAPI event_sink_QueryInterface(IMediaEventSink *iface, REFIID iid, void **out)
2376 struct graph *graph = impl_from_IMediaEventSink(iface);
2377 return IFilterGraph2_QueryInterface(&graph->IFilterGraph2_iface, iid, out);
2380 static ULONG WINAPI event_sink_AddRef(IMediaEventSink *iface)
2382 struct graph *graph = impl_from_IMediaEventSink(iface);
2383 return IFilterGraph2_AddRef(&graph->IFilterGraph2_iface);
2386 static ULONG WINAPI event_sink_Release(IMediaEventSink *iface)
2388 struct graph *graph = impl_from_IMediaEventSink(iface);
2389 return IFilterGraph2_Release(&graph->IFilterGraph2_iface);
2392 static HRESULT WINAPI event_sink_Notify(IMediaEventSink *iface,
2393 LONG code, LONG_PTR param1, LONG_PTR param2)
2395 struct graph *graph = impl_from_IMediaEventSink(iface);
2396 ++graph->got_notify;
2397 graph->event_code = code;
2398 graph->event_param1 = param1;
2399 graph->event_param2 = param2;
2400 return IMediaEventSink_Notify(graph->inner_event_sink, code, param1, param2);
2403 static const IMediaEventSinkVtbl event_sink_vtbl =
2405 event_sink_QueryInterface,
2406 event_sink_AddRef,
2407 event_sink_Release,
2408 event_sink_Notify,
2411 static void graph_init(struct graph *graph)
2413 HRESULT hr;
2415 memset(graph, 0, sizeof(*graph));
2416 graph->IFilterGraph2_iface.lpVtbl = &graph_vtbl;
2417 graph->IMediaEventSink_iface.lpVtbl = &event_sink_vtbl;
2418 graph->refcount = 1;
2419 hr = CoCreateInstance(&CLSID_FilterGraph, (IUnknown *)&graph->IFilterGraph2_iface, CLSCTX_INPROC_SERVER,
2420 &IID_IUnknown, (void **)&graph->inner_unk);
2421 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2422 hr = IUnknown_QueryInterface(graph->inner_unk, &IID_IFilterGraph2, (void **)&graph->inner);
2423 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2424 hr = IUnknown_QueryInterface(graph->inner_unk, &IID_IMediaEventSink, (void **)&graph->inner_event_sink);
2425 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2428 static void graph_destroy(struct graph *graph)
2430 ULONG ref;
2432 IMediaEventSink_Release(graph->inner_event_sink);
2433 IFilterGraph2_Release(graph->inner);
2434 ref = IUnknown_Release(graph->inner_unk);
2435 ok(!ref, "Got outstanding refcount %ld.\n", ref);
2438 static void test_initialize(void)
2440 IAMMultiMediaStream *mmstream = create_ammultimediastream();
2441 IMediaStreamFilter *filter;
2442 IGraphBuilder *ret_graph;
2443 IMediaStream *stream;
2444 struct graph graph;
2445 STREAM_TYPE type;
2446 HRESULT hr;
2447 ULONG ref;
2449 ret_graph = (IGraphBuilder *)0xdeadbeef;
2450 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &ret_graph);
2451 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2452 ok(!ret_graph, "Got unexpected graph %p.\n", ret_graph);
2454 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
2455 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2456 ok(!!filter, "Expected a non-NULL filter.");
2457 IMediaStreamFilter_Release(filter);
2459 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
2460 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2462 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
2463 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2464 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_WRITE, 0, NULL);
2465 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
2466 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_TRANSFORM, 0, NULL);
2467 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
2469 ret_graph = (IGraphBuilder *)0xdeadbeef;
2470 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &ret_graph);
2471 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2472 ok(!ret_graph, "Got unexpected graph %p.\n", ret_graph);
2474 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
2475 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2476 type = 0xdeadbeef;
2477 hr = IMediaStream_GetInformation(stream, NULL, &type);
2478 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2479 ok(type == STREAMTYPE_READ, "Got type %u.\n", type);
2480 IMediaStream_Release(stream);
2482 ret_graph = NULL;
2483 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &ret_graph);
2484 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2485 ok(!!ret_graph, "Got unexpected graph %p.\n", ret_graph);
2486 IGraphBuilder_Release(ret_graph);
2488 ref = IAMMultiMediaStream_Release(mmstream);
2489 ok(!ref, "Got outstanding refcount %ld.\n", ref);
2491 mmstream = create_ammultimediastream();
2493 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_WRITE, 0, NULL);
2494 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2496 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_WRITE, 0, NULL);
2497 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2498 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
2499 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
2500 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_TRANSFORM, 0, NULL);
2501 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
2503 ret_graph = (IGraphBuilder *)0xdeadbeef;
2504 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &ret_graph);
2505 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2506 ok(!ret_graph, "Got unexpected graph %p.\n", ret_graph);
2508 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
2509 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2510 type = 0xdeadbeef;
2511 hr = IMediaStream_GetInformation(stream, NULL, &type);
2512 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2513 ok(type == STREAMTYPE_WRITE, "Got type %u.\n", type);
2514 IMediaStream_Release(stream);
2516 ref = IAMMultiMediaStream_Release(mmstream);
2517 ok(!ref, "Got outstanding refcount %ld.\n", ref);
2519 mmstream = create_ammultimediastream();
2521 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_TRANSFORM, 0, NULL);
2522 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2524 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_TRANSFORM, 0, NULL);
2525 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2526 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
2527 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
2528 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_WRITE, 0, NULL);
2529 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
2531 ret_graph = (IGraphBuilder *)0xdeadbeef;
2532 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &ret_graph);
2533 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2534 ok(!ret_graph, "Got unexpected graph %p.\n", ret_graph);
2536 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
2537 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2538 type = 0xdeadbeef;
2539 hr = IMediaStream_GetInformation(stream, NULL, &type);
2540 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2541 ok(type == STREAMTYPE_TRANSFORM, "Got type %u.\n", type);
2542 IMediaStream_Release(stream);
2544 ref = IAMMultiMediaStream_Release(mmstream);
2545 ok(!ref, "Got outstanding refcount %ld.\n", ref);
2547 mmstream = create_ammultimediastream();
2549 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
2550 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2552 type = 0xdeadbeef;
2553 hr = IMediaStream_GetInformation(stream, NULL, &type);
2554 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2555 ok(type == STREAMTYPE_READ, "Got type %u.\n", type);
2557 ret_graph = NULL;
2558 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &ret_graph);
2559 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2560 ok(!!ret_graph, "Got unexpected graph %p.\n", ret_graph);
2561 IGraphBuilder_Release(ret_graph);
2563 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_TRANSFORM, 0, NULL);
2564 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2566 type = 0xdeadbeef;
2567 hr = IMediaStream_GetInformation(stream, NULL, &type);
2568 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2569 ok(type == STREAMTYPE_READ, "Got type %u.\n", type);
2571 IMediaStream_Release(stream);
2572 ref = IAMMultiMediaStream_Release(mmstream);
2573 ok(!ref, "Got outstanding refcount %ld.\n", ref);
2575 /* Test with a custom filter graph. */
2577 mmstream = create_ammultimediastream();
2579 graph_init(&graph);
2581 ret_graph = (IGraphBuilder *)0xdeadbeef;
2582 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &ret_graph);
2583 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2584 ok(!ret_graph, "Got unexpected graph %p.\n", ret_graph);
2586 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
2587 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2588 ok(!!filter, "Expected a non-NULL filter.");
2590 graph.got_add_filter = 0;
2591 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, (IGraphBuilder *)&graph.IFilterGraph2_iface);
2592 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2593 ok(graph.got_add_filter == 1, "Got %d calls to IGraphBuilder::AddFilter().\n", graph.got_add_filter);
2594 ok(graph.filter == (IBaseFilter *)filter, "Got filter %p.\n", filter);
2595 ok(!wcscmp(graph.filter_name, L"MediaStreamFilter"), "Got unexpected name %s.\n", wine_dbgstr_w(graph.filter_name));
2597 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &ret_graph);
2598 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2599 ok(ret_graph == (IGraphBuilder *)&graph, "Got unexpected graph %p.\n", ret_graph);
2600 IGraphBuilder_Release(ret_graph);
2602 graph.got_add_filter = 0;
2603 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, NULL);
2604 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2605 ok(!graph.got_add_filter, "Got %d calls to IGraphBuilder::AddFilter().\n", graph.got_add_filter);
2607 graph.got_add_filter = 0;
2608 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, NULL);
2609 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2610 ok(!graph.got_add_filter, "Got %d calls to IGraphBuilder::AddFilter().\n", graph.got_add_filter);
2612 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, (IGraphBuilder *)&graph);
2613 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
2614 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
2615 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2616 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_WRITE, 0, NULL);
2617 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
2618 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_TRANSFORM, 0, NULL);
2619 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
2621 IMediaStreamFilter_Release(filter);
2622 ref = IAMMultiMediaStream_Release(mmstream);
2623 ok(!ref, "Got outstanding refcount %ld.\n", ref);
2625 graph_destroy(&graph);
2628 static IAMMultiMediaStream *mmstream_mmstream;
2629 static STREAM_STATE mmstream_state;
2631 static DWORD CALLBACK mmstream_set_state(void *param)
2633 HRESULT hr;
2635 hr = IAMMultiMediaStream_SetState(mmstream_mmstream, mmstream_state);
2636 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2638 return 0;
2641 static void test_set_state(void)
2643 IAMMultiMediaStream *mmstream = create_ammultimediastream();
2644 IMediaControl *media_control;
2645 struct testfilter source;
2646 IGraphBuilder *graph;
2647 STREAM_STATE state;
2648 HANDLE thread;
2649 HRESULT hr;
2650 ULONG ref;
2652 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
2653 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2654 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, NULL);
2655 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2656 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
2657 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2658 ok(graph != NULL, "Expected non-NULL graph.\n");
2659 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void **)&media_control);
2660 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2661 testfilter_init(&source);
2663 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
2664 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2666 source.init_stream_hr = E_FAIL;
2667 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
2668 ok(hr == E_FAIL, "Got hr %#lx.\n", hr);
2669 source.init_stream_hr = S_OK;
2670 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
2671 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2673 source.init_stream_hr = S_FALSE;
2674 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
2675 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2676 source.init_stream_hr = S_OK;
2677 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
2678 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2680 source.wait_state_hr = E_FAIL;
2681 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
2682 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2683 source.wait_state_hr = S_OK;
2684 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
2685 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2687 source.wait_state_hr = VFW_S_STATE_INTERMEDIATE;
2688 ResetEvent(source.wait_state_event);
2690 mmstream_mmstream = mmstream;
2691 mmstream_state = STREAMSTATE_RUN;
2692 thread = CreateThread(NULL, 0, mmstream_set_state, NULL, 0, NULL);
2694 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "SetState returned prematurely.\n");
2696 EnterCriticalSection(&source.filter.filter_cs);
2697 source.wait_state_hr = S_OK;
2698 SetEvent(source.wait_state_event);
2699 LeaveCriticalSection(&source.filter.filter_cs);
2701 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
2702 CloseHandle(thread);
2704 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
2705 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2707 source.init_stream_hr = E_FAIL;
2708 source.wait_state_hr = VFW_S_STATE_INTERMEDIATE;
2709 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
2710 ok(hr == E_FAIL, "Got hr %#lx.\n", hr);
2711 source.init_stream_hr = S_OK;
2712 source.wait_state_hr = S_OK;
2713 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
2714 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2716 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
2717 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2718 source.cleanup_stream_hr = E_FAIL;
2719 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
2720 ok(hr == E_FAIL, "Got hr %#lx.\n", hr);
2721 source.cleanup_stream_hr = S_OK;
2722 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
2723 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2725 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
2726 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2727 source.cleanup_stream_hr = S_FALSE;
2728 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
2729 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
2730 source.cleanup_stream_hr = S_OK;
2732 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
2733 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2734 source.wait_state_hr = VFW_S_STATE_INTERMEDIATE;
2735 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
2736 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2737 source.wait_state_hr = S_OK;
2739 /* Crashes on native. */
2740 if (0)
2742 hr = IAMMultiMediaStream_GetState(mmstream, NULL);
2743 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
2746 state = 0xdeadbeef;
2747 hr = IAMMultiMediaStream_GetState(mmstream, &state);
2748 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2749 ok(state == STREAMSTATE_STOP, "Got state %#x.\n", state);
2751 hr = IMediaControl_Run(media_control);
2752 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2754 state = 0xdeadbeef;
2755 hr = IAMMultiMediaStream_GetState(mmstream, &state);
2756 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2757 ok(state == STREAMSTATE_STOP, "Got state %#x.\n", state);
2759 hr = IMediaControl_Stop(media_control);
2760 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2762 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
2763 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2765 state = 0xdeadbeef;
2766 hr = IAMMultiMediaStream_GetState(mmstream, &state);
2767 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2768 ok(state == STREAMSTATE_RUN, "Got state %#x.\n", state);
2770 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
2771 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2773 state = 0xdeadbeef;
2774 hr = IAMMultiMediaStream_GetState(mmstream, &state);
2775 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2776 ok(state == STREAMSTATE_STOP, "Got state %#x.\n", state);
2778 source.init_stream_hr = E_FAIL;
2779 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
2780 ok(hr == E_FAIL, "Got hr %#lx.\n", hr);
2782 state = 0xdeadbeef;
2783 hr = IAMMultiMediaStream_GetState(mmstream, &state);
2784 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2785 ok(state == STREAMSTATE_STOP, "Got state %#x.\n", state);
2787 ref = IAMMultiMediaStream_Release(mmstream);
2788 ok(!ref, "Got outstanding refcount %ld.\n", ref);
2789 IMediaControl_Release(media_control);
2790 ref = IGraphBuilder_Release(graph);
2791 ok(!ref, "Got outstanding refcount %ld.\n", ref);
2794 static void test_enum_media_types(void)
2796 IAMMultiMediaStream *mmstream = create_ammultimediastream();
2797 IEnumMediaTypes *enum1, *enum2;
2798 AM_MEDIA_TYPE *mts[2];
2799 IMediaStream *stream;
2800 ULONG ref, count;
2801 HRESULT hr;
2802 IPin *pin;
2804 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
2805 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2806 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
2807 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2809 hr = IPin_EnumMediaTypes(pin, &enum1);
2810 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2812 hr = IEnumMediaTypes_Next(enum1, 1, mts, NULL);
2813 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
2815 hr = IEnumMediaTypes_Next(enum1, 0, mts, &count);
2816 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2817 ok(!count, "Got count %lu.\n", count);
2819 hr = IEnumMediaTypes_Next(enum1, 1, mts, &count);
2820 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2821 ok(count == 1, "Got count %lu.\n", count);
2822 CoTaskMemFree(mts[0]);
2824 hr = IEnumMediaTypes_Next(enum1, 1, mts, &count);
2825 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
2826 ok(!count, "Got count %lu.\n", count);
2828 hr = IEnumMediaTypes_Reset(enum1);
2829 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2831 hr = IEnumMediaTypes_Next(enum1, 2, mts, &count);
2832 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
2833 ok(count == 1, "Got count %lu.\n", count);
2834 CoTaskMemFree(mts[0]);
2836 hr = IEnumMediaTypes_Reset(enum1);
2837 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2839 hr = IEnumMediaTypes_Clone(enum1, &enum2);
2840 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2842 hr = IEnumMediaTypes_Skip(enum1, 2);
2843 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2845 hr = IEnumMediaTypes_Next(enum1, 1, mts, &count);
2846 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
2847 ok(!count, "Got count %lu.\n", count);
2849 hr = IEnumMediaTypes_Next(enum2, 1, mts, &count);
2850 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2851 ok(count == 1, "Got count %lu.\n", count);
2852 CoTaskMemFree(mts[0]);
2854 IEnumMediaTypes_Release(enum2);
2855 IEnumMediaTypes_Release(enum1);
2856 IPin_Release(pin);
2857 IMediaStream_Release(stream);
2859 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
2860 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2861 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
2862 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2864 hr = IPin_EnumMediaTypes(pin, &enum1);
2865 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2867 hr = IEnumMediaTypes_Next(enum1, 1, mts, NULL);
2868 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
2870 hr = IEnumMediaTypes_Next(enum1, 0, mts, &count);
2871 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2872 ok(!count, "Got count %lu.\n", count);
2874 hr = IEnumMediaTypes_Next(enum1, 1, mts, &count);
2875 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2876 ok(count == 1, "Got count %lu.\n", count);
2877 CoTaskMemFree(mts[0]->pbFormat);
2878 CoTaskMemFree(mts[0]);
2880 hr = IEnumMediaTypes_Next(enum1, 1, mts, &count);
2881 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
2882 ok(!count, "Got count %lu.\n", count);
2884 hr = IEnumMediaTypes_Reset(enum1);
2885 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2887 hr = IEnumMediaTypes_Next(enum1, 2, mts, &count);
2888 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
2889 ok(count == 1, "Got count %lu.\n", count);
2890 CoTaskMemFree(mts[0]->pbFormat);
2891 CoTaskMemFree(mts[0]);
2893 hr = IEnumMediaTypes_Reset(enum1);
2894 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2896 hr = IEnumMediaTypes_Clone(enum1, &enum2);
2897 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2899 hr = IEnumMediaTypes_Skip(enum1, 2);
2900 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2902 hr = IEnumMediaTypes_Next(enum1, 1, mts, &count);
2903 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
2904 ok(!count, "Got count %lu.\n", count);
2906 hr = IEnumMediaTypes_Next(enum2, 1, mts, &count);
2907 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2908 ok(count == 1, "Got count %lu.\n", count);
2909 CoTaskMemFree(mts[0]->pbFormat);
2910 CoTaskMemFree(mts[0]);
2912 IEnumMediaTypes_Release(enum2);
2913 IEnumMediaTypes_Release(enum1);
2914 IPin_Release(pin);
2915 IMediaStream_Release(stream);
2917 ref = IAMMultiMediaStream_Release(mmstream);
2918 ok(!ref, "Got outstanding refcount %ld.\n", ref);
2921 static void test_media_types(void)
2923 static const VIDEOINFOHEADER2 req_vih2;
2924 static const VIDEOINFOHEADER req_vih;
2925 static const MPEG2VIDEOINFO req_m2vi;
2926 static const MPEG1VIDEOINFO req_m1vi;
2927 static const WAVEFORMATEX req_wfx;
2928 static const WAVEFORMATEX expect_wfx =
2930 .wFormatTag = WAVE_FORMAT_PCM,
2931 .nChannels = 1,
2932 .nSamplesPerSec = 11025,
2933 .nAvgBytesPerSec = 11025 * 2,
2934 .nBlockAlign = 2,
2935 .wBitsPerSample = 16,
2936 .cbSize = 0,
2938 IAMMultiMediaStream *mmstream = create_ammultimediastream();
2939 IEnumMediaTypes *enummt;
2940 IMediaStream *stream;
2941 AM_MEDIA_TYPE *pmt;
2942 ULONG ref, count;
2943 unsigned int i;
2944 HRESULT hr;
2945 IPin *pin;
2947 static const struct
2949 const GUID *type;
2950 BYTE *format;
2951 ULONG size;
2953 tests[] =
2955 {&GUID_NULL, NULL, 0 },
2956 {&FORMAT_None, NULL, 0 },
2957 {&FORMAT_WaveFormatEx, (BYTE *)&req_wfx, sizeof(WAVEFORMATEX)},
2958 {&FORMAT_MPEG2Video, (BYTE *)&req_m2vi, sizeof(MPEG2VIDEOINFO)},
2959 {&FORMAT_MPEGVideo, (BYTE *)&req_m1vi, sizeof(MPEG2VIDEOINFO)},
2960 {&FORMAT_VideoInfo2, (BYTE *)&req_vih2, sizeof(VIDEOINFOHEADER2)},
2961 {&FORMAT_VideoInfo, (BYTE *)&req_vih, sizeof(VIDEOINFOHEADER)},
2964 static const GUID *rejected_subtypes[] =
2966 &MEDIASUBTYPE_RGB1,
2967 &MEDIASUBTYPE_RGB4,
2968 &MEDIASUBTYPE_RGB565,
2969 &MEDIASUBTYPE_RGB555,
2970 &MEDIASUBTYPE_RGB24,
2971 &MEDIASUBTYPE_RGB32,
2972 &MEDIASUBTYPE_ARGB32,
2973 &MEDIASUBTYPE_ARGB1555,
2974 &MEDIASUBTYPE_ARGB4444,
2975 &MEDIASUBTYPE_Avi,
2976 &MEDIASUBTYPE_I420,
2977 &MEDIASUBTYPE_AYUV,
2978 &MEDIASUBTYPE_YV12,
2979 &MEDIASUBTYPE_YUY2,
2980 &MEDIASUBTYPE_UYVY,
2981 &MEDIASUBTYPE_YVYU,
2982 &MEDIASUBTYPE_NV12,
2983 &GUID_NULL,
2986 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
2987 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2988 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
2989 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2991 hr = IPin_EnumMediaTypes(pin, &enummt);
2992 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2994 hr = IEnumMediaTypes_Next(enummt, 1, &pmt, NULL);
2995 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
2997 hr = IEnumMediaTypes_Next(enummt, 1, &pmt, &count);
2998 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2999 ok(count == 1, "Got count %lu.\n", count);
3000 ok(IsEqualGUID(&pmt->majortype, &MEDIATYPE_Video), "Got major type %s\n",
3001 wine_dbgstr_guid(&pmt->majortype));
3002 ok(IsEqualGUID(&pmt->subtype, &MEDIASUBTYPE_RGB8), "Got subtype %s\n",
3003 wine_dbgstr_guid(&pmt->subtype));
3004 ok(pmt->bFixedSizeSamples == TRUE, "Got fixed size %d.\n", pmt->bFixedSizeSamples);
3005 ok(!pmt->bTemporalCompression, "Got temporal compression %d.\n", pmt->bTemporalCompression);
3006 ok(pmt->lSampleSize == 10000, "Got sample size %lu.\n", pmt->lSampleSize);
3007 ok(IsEqualGUID(&pmt->formattype, &GUID_NULL), "Got format type %s.\n",
3008 wine_dbgstr_guid(&pmt->formattype));
3009 ok(!pmt->pUnk, "Got pUnk %p.\n", pmt->pUnk);
3011 for (i = 0; i < ARRAY_SIZE(tests); ++i)
3013 pmt->formattype = *tests[i].type;
3014 pmt->cbFormat = tests[i].size;
3015 pmt->pbFormat = tests[i].format;
3016 hr = IPin_QueryAccept(pin, pmt);
3017 ok(hr == (i == 6 ? S_OK : VFW_E_TYPE_NOT_ACCEPTED), "Got hr %#lx.\n", hr);
3020 pmt->bFixedSizeSamples = FALSE;
3021 pmt->bTemporalCompression = TRUE;
3022 pmt->lSampleSize = 123;
3023 hr = IPin_QueryAccept(pin, pmt);
3024 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3026 pmt->majortype = MEDIATYPE_NULL;
3027 hr = IPin_QueryAccept(pin, pmt);
3028 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
3029 pmt->majortype = MEDIATYPE_Audio;
3030 hr = IPin_QueryAccept(pin, pmt);
3031 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
3032 pmt->majortype = MEDIATYPE_Stream;
3033 hr = IPin_QueryAccept(pin, pmt);
3034 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
3035 pmt->majortype = MEDIATYPE_Video;
3037 for (i = 0; i < ARRAY_SIZE(rejected_subtypes); ++i)
3039 pmt->subtype = *rejected_subtypes[i];
3040 hr = IPin_QueryAccept(pin, pmt);
3041 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#lx for subtype %s.\n",
3042 hr, wine_dbgstr_guid(rejected_subtypes[i]));
3045 CoTaskMemFree(pmt);
3047 hr = IEnumMediaTypes_Next(enummt, 1, &pmt, &count);
3048 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
3050 IEnumMediaTypes_Release(enummt);
3051 IPin_Release(pin);
3052 IMediaStream_Release(stream);
3054 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
3055 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3056 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
3057 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3059 hr = IPin_EnumMediaTypes(pin, &enummt);
3060 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3062 hr = IEnumMediaTypes_Next(enummt, 1, &pmt, NULL);
3063 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
3065 hr = IEnumMediaTypes_Next(enummt, 1, &pmt, &count);
3066 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3067 ok(count == 1, "Got count %lu.\n", count);
3068 ok(IsEqualGUID(&pmt->majortype, &MEDIATYPE_Audio), "Got major type %s\n",
3069 wine_dbgstr_guid(&pmt->majortype));
3070 ok(IsEqualGUID(&pmt->subtype, &GUID_NULL), "Got subtype %s\n",
3071 wine_dbgstr_guid(&pmt->subtype));
3072 ok(pmt->bFixedSizeSamples == TRUE, "Got fixed size %d.\n", pmt->bFixedSizeSamples);
3073 ok(!pmt->bTemporalCompression, "Got temporal compression %d.\n", pmt->bTemporalCompression);
3074 ok(pmt->lSampleSize == 2, "Got sample size %lu.\n", pmt->lSampleSize);
3075 ok(IsEqualGUID(&pmt->formattype, &FORMAT_WaveFormatEx), "Got format type %s.\n",
3076 wine_dbgstr_guid(&pmt->formattype));
3077 ok(!pmt->pUnk, "Got pUnk %p.\n", pmt->pUnk);
3078 ok(pmt->cbFormat == sizeof(WAVEFORMATEX), "Got format size %lu.\n", pmt->cbFormat);
3079 ok(!memcmp(pmt->pbFormat, &expect_wfx, pmt->cbFormat), "Format blocks didn't match.\n");
3081 hr = IPin_QueryAccept(pin, pmt);
3082 ok(hr == E_NOTIMPL, "Got hr %#lx.\n", hr);
3084 CoTaskMemFree(pmt->pbFormat);
3085 CoTaskMemFree(pmt);
3087 hr = IEnumMediaTypes_Next(enummt, 1, &pmt, &count);
3088 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
3090 IEnumMediaTypes_Release(enummt);
3091 IPin_Release(pin);
3092 IMediaStream_Release(stream);
3094 ref = IAMMultiMediaStream_Release(mmstream);
3095 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3098 static void test_get_end_of_stream_event_handle(void)
3100 IAMMultiMediaStream *mmstream = create_ammultimediastream();
3101 IMediaStreamFilter *filter;
3102 struct testfilter source;
3103 IGraphBuilder *graph;
3104 IMediaStream *stream;
3105 HANDLE event;
3106 HRESULT hr;
3107 ULONG ref;
3108 IPin *pin;
3110 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
3111 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3112 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
3113 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3114 ok(!!filter, "Expected non-null filter.\n");
3115 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
3116 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3117 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
3118 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3119 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
3120 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3121 ok(!!graph, "Expected non-NULL graph.\n");
3122 testfilter_init(&source);
3123 source.IMediaSeeking_iface.lpVtbl = &testsource_seeking_vtbl;
3124 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
3125 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3127 hr = IAMMultiMediaStream_GetEndOfStreamEventHandle(mmstream, NULL);
3128 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
3130 event = INVALID_HANDLE_VALUE;
3131 hr = IAMMultiMediaStream_GetEndOfStreamEventHandle(mmstream, &event);
3132 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3134 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &rgb32_mt);
3135 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3137 hr = IMediaStreamFilter_SupportSeeking(filter, TRUE);
3138 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3140 ok(WaitForSingleObject(event, 0) == WAIT_TIMEOUT, "Event should not be signaled.\n");
3142 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
3143 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3145 ok(WaitForSingleObject(event, 0) == WAIT_TIMEOUT, "Event should not be signaled.\n");
3147 hr = IPin_EndOfStream(pin);
3148 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3150 ok(WaitForSingleObject(event, 0) == 0, "Event should be signaled.\n");
3152 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
3153 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3155 ok(WaitForSingleObject(event, 0) == 0, "Event should be signaled.\n");
3157 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
3158 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3160 ok(WaitForSingleObject(event, 0) == WAIT_TIMEOUT, "Event should not be signaled.\n");
3162 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
3163 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3165 IGraphBuilder_Disconnect(graph, pin);
3166 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
3168 ref = IAMMultiMediaStream_Release(mmstream);
3169 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3170 ref = IGraphBuilder_Release(graph);
3171 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3172 ref = IMediaStreamFilter_Release(filter);
3173 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3174 IPin_Release(pin);
3175 ref = IMediaStream_Release(stream);
3176 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3179 static IUnknown *create_audio_data(void)
3181 IUnknown *audio_data = NULL;
3182 HRESULT result = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER,
3183 &IID_IUnknown, (void **)&audio_data);
3184 ok(S_OK == result, "got 0x%08lx\n", result);
3185 return audio_data;
3188 static void test_audiodata_query_interface(void)
3190 IUnknown *unknown = create_audio_data();
3191 IMemoryData *memory_data = NULL;
3192 IAudioData *audio_data = NULL;
3194 HRESULT result;
3196 result = IUnknown_QueryInterface(unknown, &IID_IMemoryData, (void **)&memory_data);
3197 ok(E_NOINTERFACE == result, "got 0x%08lx\n", result);
3199 result = IUnknown_QueryInterface(unknown, &IID_IAudioData, (void **)&audio_data);
3200 ok(S_OK == result, "got 0x%08lx\n", result);
3201 if (S_OK == result)
3203 result = IAudioData_QueryInterface(audio_data, &IID_IMemoryData, (void **)&memory_data);
3204 ok(E_NOINTERFACE == result, "got 0x%08lx\n", result);
3206 IAudioData_Release(audio_data);
3209 IUnknown_Release(unknown);
3212 static void test_audiodata_get_info(void)
3214 IUnknown *unknown = create_audio_data();
3215 IAudioData *audio_data = NULL;
3217 HRESULT result;
3219 result = IUnknown_QueryInterface(unknown, &IID_IAudioData, (void **)&audio_data);
3220 if (FAILED(result))
3222 /* test_audiodata_query_interface handles this case */
3223 skip("No IAudioData\n");
3224 goto out_unknown;
3227 result = IAudioData_GetInfo(audio_data, NULL, NULL, NULL);
3228 ok(MS_E_NOTINIT == result, "got 0x%08lx\n", result);
3230 IAudioData_Release(audio_data);
3232 out_unknown:
3233 IUnknown_Release(unknown);
3236 static void test_audiodata_set_buffer(void)
3238 IUnknown *unknown = create_audio_data();
3239 IAudioData *audio_data = NULL;
3240 BYTE buffer[100] = {0};
3241 DWORD length = 0;
3242 BYTE *data = NULL;
3244 HRESULT result;
3246 result = IUnknown_QueryInterface(unknown, &IID_IAudioData, (void **)&audio_data);
3247 if (FAILED(result))
3249 /* test_audiodata_query_interface handles this case */
3250 skip("No IAudioData\n");
3251 goto out_unknown;
3254 result = IAudioData_SetBuffer(audio_data, 100, NULL, 0);
3255 ok(S_OK == result, "got 0x%08lx\n", result);
3257 data = (BYTE *)0xdeadbeef;
3258 length = 0xdeadbeef;
3259 result = IAudioData_GetInfo(audio_data, &length, &data, NULL);
3260 ok(S_OK == result, "got 0x%08lx\n", result);
3261 ok(100 == length, "got %lu\n", length);
3262 ok(NULL != data, "got %p\n", data);
3264 result = IAudioData_SetBuffer(audio_data, 0, buffer, 0);
3265 ok(E_INVALIDARG == result, "got 0x%08lx\n", result);
3267 result = IAudioData_SetBuffer(audio_data, sizeof(buffer), buffer, 0);
3268 ok(S_OK == result, "got 0x%08lx\n", result);
3270 data = (BYTE *)0xdeadbeef;
3271 length = 0xdeadbeef;
3272 result = IAudioData_GetInfo(audio_data, &length, &data, NULL);
3273 ok(S_OK == result, "got 0x%08lx\n", result);
3274 ok(sizeof(buffer) == length, "got %lu\n", length);
3275 ok(buffer == data, "got %p\n", data);
3277 IAudioData_Release(audio_data);
3279 out_unknown:
3280 IUnknown_Release(unknown);
3283 static void test_audiodata_set_actual(void)
3285 IUnknown *unknown = create_audio_data();
3286 IAudioData *audio_data = NULL;
3287 BYTE buffer[100] = {0};
3288 DWORD actual_data = 0;
3290 HRESULT result;
3292 result = IUnknown_QueryInterface(unknown, &IID_IAudioData, (void **)&audio_data);
3293 if (FAILED(result))
3295 /* test_audiodata_query_interface handles this case */
3296 skip("No IAudioData\n");
3297 goto out_unknown;
3300 result = IAudioData_SetActual(audio_data, 0);
3301 ok(S_OK == result, "got 0x%08lx\n", result);
3303 result = IAudioData_SetBuffer(audio_data, sizeof(buffer), buffer, 0);
3304 ok(S_OK == result, "got 0x%08lx\n", result);
3306 result = IAudioData_SetActual(audio_data, sizeof(buffer) + 1);
3307 ok(E_INVALIDARG == result, "got 0x%08lx\n", result);
3309 result = IAudioData_SetActual(audio_data, sizeof(buffer));
3310 ok(S_OK == result, "got 0x%08lx\n", result);
3312 actual_data = 0xdeadbeef;
3313 result = IAudioData_GetInfo(audio_data, NULL, NULL, &actual_data);
3314 ok(S_OK == result, "got 0x%08lx\n", result);
3315 ok(sizeof(buffer) == actual_data, "got %lu\n", actual_data);
3317 result = IAudioData_SetActual(audio_data, 0);
3318 ok(S_OK == result, "got 0x%08lx\n", result);
3320 actual_data = 0xdeadbeef;
3321 result = IAudioData_GetInfo(audio_data, NULL, NULL, &actual_data);
3322 ok(S_OK == result, "got 0x%08lx\n", result);
3323 ok(0 == actual_data, "got %lu\n", actual_data);
3325 IAudioData_Release(audio_data);
3327 out_unknown:
3328 IUnknown_Release(unknown);
3331 static void test_audiodata_get_format(void)
3333 IUnknown *unknown = create_audio_data();
3334 IAudioData *audio_data = NULL;
3335 WAVEFORMATEX wave_format = {0};
3337 HRESULT result;
3339 result = IUnknown_QueryInterface(unknown, &IID_IAudioData, (void **)&audio_data);
3340 if (FAILED(result))
3342 /* test_audiodata_query_interface handles this case */
3343 skip("No IAudioData\n");
3344 goto out_unknown;
3347 result = IAudioData_GetFormat(audio_data, NULL);
3348 ok(E_POINTER == result, "got 0x%08lx\n", result);
3350 wave_format.wFormatTag = 0xdead;
3351 wave_format.nChannels = 0xdead;
3352 wave_format.nSamplesPerSec = 0xdeadbeef;
3353 wave_format.nAvgBytesPerSec = 0xdeadbeef;
3354 wave_format.nBlockAlign = 0xdead;
3355 wave_format.wBitsPerSample = 0xdead;
3356 wave_format.cbSize = 0xdead;
3357 result = IAudioData_GetFormat(audio_data, &wave_format);
3358 ok(S_OK == result, "got 0x%08lx\n", result);
3359 ok(WAVE_FORMAT_PCM == wave_format.wFormatTag, "got %u\n", wave_format.wFormatTag);
3360 ok(1 == wave_format.nChannels, "got %u\n", wave_format.nChannels);
3361 ok(11025 == wave_format.nSamplesPerSec, "got %lu\n", wave_format.nSamplesPerSec);
3362 ok(22050 == wave_format.nAvgBytesPerSec, "got %lu\n", wave_format.nAvgBytesPerSec);
3363 ok(2 == wave_format.nBlockAlign, "got %u\n", wave_format.nBlockAlign);
3364 ok(16 == wave_format.wBitsPerSample, "got %u\n", wave_format.wBitsPerSample);
3365 ok(0 == wave_format.cbSize, "got %u\n", wave_format.cbSize);
3367 IAudioData_Release(audio_data);
3369 out_unknown:
3370 IUnknown_Release(unknown);
3373 static void test_audiodata_set_format(void)
3375 IUnknown *unknown = create_audio_data();
3376 IAudioData *audio_data = NULL;
3377 WAVEFORMATPCMEX wave_format = {{0}};
3379 HRESULT result;
3381 result = IUnknown_QueryInterface(unknown, &IID_IAudioData, (void **)&audio_data);
3382 if (FAILED(result))
3384 /* test_audiodata_query_interface handles this case */
3385 skip("No IAudioData\n");
3386 goto out_unknown;
3389 result = IAudioData_SetFormat(audio_data, NULL);
3390 ok(E_POINTER == result, "got 0x%08lx\n", result);
3392 wave_format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
3393 wave_format.Format.nChannels = 2;
3394 wave_format.Format.nSamplesPerSec = 44100;
3395 wave_format.Format.nAvgBytesPerSec = 176400;
3396 wave_format.Format.nBlockAlign = 4;
3397 wave_format.Format.wBitsPerSample = 16;
3398 wave_format.Format.cbSize = 22;
3399 wave_format.Samples.wValidBitsPerSample = 16;
3400 wave_format.dwChannelMask = KSAUDIO_SPEAKER_STEREO;
3401 wave_format.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
3402 result = IAudioData_SetFormat(audio_data, &wave_format.Format);
3403 ok(E_INVALIDARG == result, "got 0x%08lx\n", result);
3405 wave_format.Format.wFormatTag = WAVE_FORMAT_PCM;
3406 wave_format.Format.nChannels = 2;
3407 wave_format.Format.nSamplesPerSec = 44100;
3408 wave_format.Format.nAvgBytesPerSec = 176400;
3409 wave_format.Format.nBlockAlign = 4;
3410 wave_format.Format.wBitsPerSample = 16;
3411 wave_format.Format.cbSize = 0;
3412 result = IAudioData_SetFormat(audio_data, &wave_format.Format);
3413 ok(S_OK == result, "got 0x%08lx\n", result);
3415 wave_format.Format.wFormatTag = 0xdead;
3416 wave_format.Format.nChannels = 0xdead;
3417 wave_format.Format.nSamplesPerSec = 0xdeadbeef;
3418 wave_format.Format.nAvgBytesPerSec = 0xdeadbeef;
3419 wave_format.Format.nBlockAlign = 0xdead;
3420 wave_format.Format.wBitsPerSample = 0xdead;
3421 wave_format.Format.cbSize = 0xdead;
3422 result = IAudioData_GetFormat(audio_data, &wave_format.Format);
3423 ok(S_OK == result, "got 0x%08lx\n", result);
3424 ok(WAVE_FORMAT_PCM == wave_format.Format.wFormatTag, "got %u\n", wave_format.Format.wFormatTag);
3425 ok(2 == wave_format.Format.nChannels, "got %u\n", wave_format.Format.nChannels);
3426 ok(44100 == wave_format.Format.nSamplesPerSec, "got %lu\n", wave_format.Format.nSamplesPerSec);
3427 ok(176400 == wave_format.Format.nAvgBytesPerSec, "got %lu\n", wave_format.Format.nAvgBytesPerSec);
3428 ok(4 == wave_format.Format.nBlockAlign, "got %u\n", wave_format.Format.nBlockAlign);
3429 ok(16 == wave_format.Format.wBitsPerSample, "got %u\n", wave_format.Format.wBitsPerSample);
3430 ok(0 == wave_format.Format.cbSize, "got %u\n", wave_format.Format.cbSize);
3432 IAudioData_Release(audio_data);
3434 out_unknown:
3435 IUnknown_Release(unknown);
3438 struct advise_time_cookie
3440 LONGLONG base;
3441 LONGLONG offset;
3442 HANDLE event;
3443 HANDLE advise_time_called_event;
3444 BOOL unadvise_called;
3447 struct testclock
3449 IReferenceClock IReferenceClock_iface;
3450 LONG refcount;
3451 LONGLONG time;
3452 struct advise_time_cookie *advise_time_cookie;
3453 HRESULT get_time_hr;
3456 static inline struct testclock *impl_from_IReferenceClock(IReferenceClock *iface)
3458 return CONTAINING_RECORD(iface, struct testclock, IReferenceClock_iface);
3461 static HRESULT WINAPI testclock_QueryInterface(IReferenceClock *iface, REFIID iid, void **out)
3463 if (winetest_debug > 1) trace("QueryInterface(%s)\n", wine_dbgstr_guid(iid));
3464 if (IsEqualGUID(iid, &IID_IReferenceClock)
3465 || IsEqualGUID(iid, &IID_IUnknown))
3467 *out = iface;
3468 IReferenceClock_AddRef(iface);
3469 return S_OK;
3471 return E_NOINTERFACE;
3474 static ULONG WINAPI testclock_AddRef(IReferenceClock *iface)
3476 struct testclock *clock = impl_from_IReferenceClock(iface);
3477 return InterlockedIncrement(&clock->refcount);
3480 static ULONG WINAPI testclock_Release(IReferenceClock *iface)
3482 struct testclock *clock = impl_from_IReferenceClock(iface);
3483 return InterlockedDecrement(&clock->refcount);
3486 static HRESULT WINAPI testclock_GetTime(IReferenceClock *iface, REFERENCE_TIME *time)
3488 struct testclock *clock = impl_from_IReferenceClock(iface);
3489 if (SUCCEEDED(clock->get_time_hr))
3490 *time = clock->time;
3491 return clock->get_time_hr;
3494 static HRESULT WINAPI testclock_AdviseTime(IReferenceClock *iface, REFERENCE_TIME base, REFERENCE_TIME offset, HEVENT event, DWORD_PTR *cookie)
3496 struct testclock *clock = impl_from_IReferenceClock(iface);
3497 if (clock->advise_time_cookie)
3499 clock->advise_time_cookie->base = base;
3500 clock->advise_time_cookie->offset = offset;
3501 clock->advise_time_cookie->event = (HANDLE)event;
3502 SetEvent(clock->advise_time_cookie->advise_time_called_event);
3504 else
3506 SetEvent((HANDLE)event);
3508 *cookie = (DWORD_PTR)clock->advise_time_cookie;
3509 return S_OK;
3512 static HRESULT WINAPI testclock_AdvisePeriodic(IReferenceClock *iface, REFERENCE_TIME start, REFERENCE_TIME period, HSEMAPHORE semaphore, DWORD_PTR *cookie)
3514 ok(0, "Unexpected call.\n");
3515 return E_NOTIMPL;
3518 static HRESULT WINAPI testclock_Unadvise(IReferenceClock *iface, DWORD_PTR cookie)
3520 if (cookie)
3521 ((struct advise_time_cookie *)cookie)->unadvise_called = TRUE;
3522 return S_OK;
3525 static IReferenceClockVtbl testclock_vtbl =
3527 testclock_QueryInterface,
3528 testclock_AddRef,
3529 testclock_Release,
3530 testclock_GetTime,
3531 testclock_AdviseTime,
3532 testclock_AdvisePeriodic,
3533 testclock_Unadvise,
3536 static void testclock_init(struct testclock *clock)
3538 memset(clock, 0, sizeof(*clock));
3539 clock->IReferenceClock_iface.lpVtbl = &testclock_vtbl;
3542 static void test_audiostream_get_format(void)
3544 static const WAVEFORMATEX pin_format =
3546 .wFormatTag = WAVE_FORMAT_PCM,
3547 .nChannels = 2,
3548 .nSamplesPerSec = 44100,
3549 .wBitsPerSample = 16,
3550 .nBlockAlign = 4,
3551 .nAvgBytesPerSec = 4 * 44100,
3553 AM_MEDIA_TYPE mt =
3555 .majortype = MEDIATYPE_Audio,
3556 .subtype = MEDIASUBTYPE_PCM,
3557 .formattype = FORMAT_WaveFormatEx,
3558 .cbFormat = sizeof(WAVEFORMATEX),
3559 .pbFormat = (BYTE *)&pin_format,
3561 IAMMultiMediaStream *mmstream = create_ammultimediastream();
3562 IAudioMediaStream *audio_stream;
3563 struct testfilter source;
3564 IGraphBuilder *graph;
3565 IMediaStream *stream;
3566 WAVEFORMATEX format;
3567 HRESULT hr;
3568 ULONG ref;
3569 IPin *pin;
3571 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
3572 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3573 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
3574 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3575 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
3576 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3578 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
3579 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3580 ok(!!graph, "Expected non-NULL graph.\n");
3582 testfilter_init(&source);
3584 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, L"source");
3585 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3587 hr = IAudioMediaStream_GetFormat(audio_stream, NULL);
3588 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
3590 hr = IAudioMediaStream_GetFormat(audio_stream, &format);
3591 ok(hr == MS_E_NOSTREAM, "Got hr %#lx.\n", hr);
3593 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
3594 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3596 memset(&format, 0xcc, sizeof(format));
3597 hr = IAudioMediaStream_GetFormat(audio_stream, &format);
3598 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3599 ok(format.wFormatTag == WAVE_FORMAT_PCM, "Got tag %#x.\n", format.wFormatTag);
3600 ok(format.nChannels == 2, "Got %u channels.\n", format.nChannels);
3601 ok(format.nSamplesPerSec == 44100, "Got sample rate %lu.\n", format.nSamplesPerSec);
3602 ok(format.nAvgBytesPerSec == 176400, "Got %lu bytes/sec.\n", format.nAvgBytesPerSec);
3603 ok(format.nBlockAlign == 4, "Got alignment %u.\n", format.nBlockAlign);
3604 ok(format.wBitsPerSample == 16, "Got %u bits/sample.\n", format.wBitsPerSample);
3605 ok(!format.cbSize, "Got extra size %u.\n", format.cbSize);
3607 hr = IGraphBuilder_Disconnect(graph, pin);
3608 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3609 hr = IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
3610 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3612 hr = IAudioMediaStream_GetFormat(audio_stream, &format);
3613 ok(hr == MS_E_NOSTREAM, "Got hr %#lx.\n", hr);
3615 ref = IAMMultiMediaStream_Release(mmstream);
3616 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3617 ref = IGraphBuilder_Release(graph);
3618 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3619 IPin_Release(pin);
3620 IAudioMediaStream_Release(audio_stream);
3621 ref = IMediaStream_Release(stream);
3622 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3623 ref = IBaseFilter_Release(&source.filter.IBaseFilter_iface);
3624 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3627 static HRESULT set_audiostream_format(const WAVEFORMATEX *format)
3629 IAMMultiMediaStream *mmstream = create_ammultimediastream();
3630 IAudioMediaStream *audio_stream;
3631 IMediaStream *stream;
3632 HRESULT hr;
3633 ULONG ref;
3635 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
3636 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3637 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
3638 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3640 hr = IAudioMediaStream_SetFormat(audio_stream, format);
3642 ref = IAMMultiMediaStream_Release(mmstream);
3643 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3644 IAudioMediaStream_Release(audio_stream);
3645 ref = IMediaStream_Release(stream);
3646 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3648 return hr;
3651 static void test_audiostream_set_format(void)
3653 static const WAVEFORMATEX valid_format =
3655 .wFormatTag = WAVE_FORMAT_PCM,
3656 .nChannels = 2,
3657 .nSamplesPerSec = 44100,
3658 .wBitsPerSample = 16,
3659 .nBlockAlign = 4,
3660 .nAvgBytesPerSec = 4 * 44100,
3663 const AM_MEDIA_TYPE mt =
3665 .majortype = MEDIATYPE_Audio,
3666 .subtype = MEDIASUBTYPE_PCM,
3667 .formattype = FORMAT_WaveFormatEx,
3668 .cbFormat = sizeof(WAVEFORMATEX),
3669 .pbFormat = (BYTE *)&valid_format,
3672 WAVEFORMATEXTENSIBLE extensible_format;
3673 IAudioMediaStream *audio_stream;
3674 IAMMultiMediaStream *mmstream;
3675 struct testfilter source;
3676 IGraphBuilder *graph;
3677 IMediaStream *stream;
3678 WAVEFORMATEX format;
3679 HRESULT hr;
3680 ULONG ref;
3681 IPin *pin;
3683 hr = set_audiostream_format(&valid_format);
3684 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3685 hr = set_audiostream_format(NULL);
3686 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
3688 extensible_format.Format = valid_format;
3689 extensible_format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
3690 extensible_format.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
3691 extensible_format.Samples.wValidBitsPerSample = valid_format.wBitsPerSample;
3692 extensible_format.dwChannelMask = KSAUDIO_SPEAKER_STEREO;
3693 extensible_format.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
3694 hr = set_audiostream_format(&extensible_format.Format);
3695 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
3697 format = valid_format;
3698 format.nBlockAlign = 1;
3699 hr = set_audiostream_format(&format);
3700 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3702 format = valid_format;
3703 format.nAvgBytesPerSec = 1234;
3704 hr = set_audiostream_format(&format);
3705 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3707 mmstream = create_ammultimediastream();
3709 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
3710 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3711 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
3712 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3714 hr = IAudioMediaStream_SetFormat(audio_stream, &valid_format);
3715 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3717 hr = IAudioMediaStream_GetFormat(audio_stream, &format);
3718 ok(hr == MS_E_NOSTREAM, "Got hr %#lx.\n", hr);
3720 format = valid_format;
3721 format.nChannels = 1;
3722 hr = IAudioMediaStream_SetFormat(audio_stream, &format);
3723 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
3725 format = valid_format;
3726 format.nSamplesPerSec = 11025;
3727 hr = IAudioMediaStream_SetFormat(audio_stream, &format);
3728 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
3730 format = valid_format;
3731 format.nAvgBytesPerSec = 1234;
3732 hr = IAudioMediaStream_SetFormat(audio_stream, &format);
3733 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
3735 format = valid_format;
3736 format.nBlockAlign = 1;
3737 hr = IAudioMediaStream_SetFormat(audio_stream, &format);
3738 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
3740 format = valid_format;
3741 format.wBitsPerSample = 8;
3742 hr = IAudioMediaStream_SetFormat(audio_stream, &format);
3743 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
3745 format = valid_format;
3746 format.cbSize = 1;
3747 hr = IAudioMediaStream_SetFormat(audio_stream, &format);
3748 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
3750 hr = IAudioMediaStream_SetFormat(audio_stream, &valid_format);
3751 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3753 ref = IAMMultiMediaStream_Release(mmstream);
3754 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3755 IAudioMediaStream_Release(audio_stream);
3756 ref = IMediaStream_Release(stream);
3757 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3759 mmstream = create_ammultimediastream();
3761 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
3762 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3763 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
3764 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3765 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
3766 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3768 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
3769 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3770 ok(!!graph, "Expected non-NULL graph.\n");
3772 testfilter_init(&source);
3774 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
3775 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3777 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
3778 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3780 format = valid_format;
3781 format.nChannels = 1;
3782 hr = IAudioMediaStream_SetFormat(audio_stream, &format);
3783 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
3785 hr = IGraphBuilder_Disconnect(graph, pin);
3786 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3787 hr = IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
3788 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3790 format = valid_format;
3791 format.nChannels = 1;
3792 hr = IAudioMediaStream_SetFormat(audio_stream, &format);
3793 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3795 ref = IAMMultiMediaStream_Release(mmstream);
3796 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3797 ref = IGraphBuilder_Release(graph);
3798 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3799 IPin_Release(pin);
3800 IAudioMediaStream_Release(audio_stream);
3801 ref = IMediaStream_Release(stream);
3802 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3803 ref = IBaseFilter_Release(&source.filter.IBaseFilter_iface);
3804 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3807 static void test_audiostream_receive_connection(void)
3809 WAVEFORMATEXTENSIBLE extensible_format;
3810 IAudioMediaStream *audio_stream;
3811 IAMMultiMediaStream *mmstream;
3812 struct testfilter source;
3813 IGraphBuilder *graph;
3814 IMediaStream *stream;
3815 WAVEFORMATEX format;
3816 AM_MEDIA_TYPE mt;
3817 HRESULT hr;
3818 ULONG ref;
3819 IPin *pin;
3821 mmstream = create_ammultimediastream();
3822 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
3823 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3824 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
3825 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3826 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
3827 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3828 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
3829 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3830 ok(graph != NULL, "Expected non-null graph\n");
3831 testfilter_init(&source);
3832 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
3833 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3835 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &audio_mt);
3836 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3837 IGraphBuilder_Disconnect(graph, pin);
3838 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
3840 mt = audio_mt;
3841 mt.majortype = GUID_NULL;
3842 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &mt);
3843 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
3845 mt = audio_mt;
3846 mt.subtype = MEDIASUBTYPE_RGB24;
3847 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
3848 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3849 IGraphBuilder_Disconnect(graph, pin);
3850 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
3852 mt = audio_mt;
3853 mt.formattype = GUID_NULL;
3854 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &mt);
3855 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
3857 mt = audio_mt;
3858 mt.cbFormat = sizeof(WAVEFORMATEX) - 1;
3859 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
3860 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
3862 extensible_format.Format = audio_format;
3863 extensible_format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
3864 extensible_format.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
3865 extensible_format.Samples.wValidBitsPerSample = audio_format.wBitsPerSample;
3866 extensible_format.dwChannelMask = KSAUDIO_SPEAKER_STEREO;
3867 extensible_format.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
3868 mt = audio_mt;
3869 mt.cbFormat = sizeof(extensible_format);
3870 mt.pbFormat = (BYTE *)&extensible_format;
3871 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
3872 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
3874 hr = IAudioMediaStream_SetFormat(audio_stream, &audio_format);
3875 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3877 format = audio_format;
3878 format.nChannels = 2;
3879 mt = audio_mt;
3880 mt.pbFormat = (BYTE *)&format;
3881 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
3882 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
3884 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &audio_mt);
3885 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3886 IGraphBuilder_Disconnect(graph, pin);
3887 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
3889 ref = IAMMultiMediaStream_Release(mmstream);
3890 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3891 ref = IGraphBuilder_Release(graph);
3892 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3893 IPin_Release(pin);
3894 IAudioMediaStream_Release(audio_stream);
3895 ref = IMediaStream_Release(stream);
3896 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3897 ref = IBaseFilter_Release(&source.filter.IBaseFilter_iface);
3898 ok(!ref, "Got outstanding refcount %ld.\n", ref);
3901 static void test_ddrawstream_receive_connection(void)
3903 static const VIDEOINFOHEADER req_vih;
3904 IDirectDrawMediaStream *ddraw_stream;
3905 IAMMultiMediaStream *mmstream;
3906 struct testfilter source;
3907 DDSURFACEDESC format;
3908 IMediaStream *stream;
3909 VIDEOINFO video_info;
3910 AM_MEDIA_TYPE mt;
3911 HRESULT hr;
3912 ULONG ref;
3913 IPin *pin;
3914 int i;
3916 static const VIDEOINFO yuy2_video_info =
3918 .bmiHeader.biSize = sizeof(BITMAPINFOHEADER),
3919 .bmiHeader.biWidth = 333,
3920 .bmiHeader.biHeight = -444,
3921 .bmiHeader.biPlanes = 1,
3922 .bmiHeader.biBitCount = 16,
3923 .bmiHeader.biCompression = MAKEFOURCC('Y', 'U', 'Y', '2'),
3926 const AM_MEDIA_TYPE yuy2_mt =
3928 .majortype = MEDIATYPE_Video,
3929 .subtype = MEDIASUBTYPE_YUY2,
3930 .formattype = FORMAT_VideoInfo,
3931 .cbFormat = sizeof(VIDEOINFOHEADER),
3932 .pbFormat = (BYTE *)&yuy2_video_info,
3935 const AM_MEDIA_TYPE video_mt =
3937 .majortype = MEDIATYPE_Video,
3938 .subtype = MEDIASUBTYPE_RGB8,
3939 .formattype = FORMAT_VideoInfo,
3940 .cbFormat = sizeof(VIDEOINFOHEADER),
3941 .pbFormat = (BYTE *)&req_vih,
3944 static const GUID *subtypes[] =
3946 &MEDIASUBTYPE_RGB24,
3947 &MEDIASUBTYPE_RGB32,
3948 &MEDIASUBTYPE_RGB555,
3949 &MEDIASUBTYPE_RGB565,
3950 &MEDIASUBTYPE_RGB1,
3951 &MEDIASUBTYPE_RGB4,
3952 &MEDIASUBTYPE_ARGB32,
3953 &MEDIASUBTYPE_ARGB1555,
3954 &MEDIASUBTYPE_ARGB4444,
3955 &MEDIASUBTYPE_Avi,
3956 &MEDIASUBTYPE_I420,
3957 &MEDIASUBTYPE_AYUV,
3958 &MEDIASUBTYPE_YV12,
3959 &MEDIASUBTYPE_YUY2,
3960 &MEDIASUBTYPE_UYVY,
3961 &MEDIASUBTYPE_YVYU,
3962 &MEDIASUBTYPE_NV12,
3963 &GUID_NULL,
3966 mmstream = create_ammultimediastream();
3967 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
3968 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3969 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
3970 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3971 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
3972 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3974 testfilter_init(&source);
3976 mt = video_mt;
3977 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &mt);
3978 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3979 hr = IPin_Disconnect(pin);
3980 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3982 for (i = 0; i < ARRAY_SIZE(subtypes); ++i)
3984 mt = video_mt;
3985 mt.subtype = *subtypes[i];
3986 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &mt);
3987 ok(hr == (i < 4 ? S_OK : VFW_E_TYPE_NOT_ACCEPTED), "Got hr %#lx.\n", hr);
3988 if (hr == S_OK)
3990 hr = IPin_Disconnect(pin);
3991 ok(hr == S_OK, "Got hr %#lx.\n", hr);
3995 format = rgb8_format;
3996 format.dwFlags = DDSD_WIDTH;
3997 format.dwWidth = 222;
3998 format.dwHeight = 555;
3999 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &format, NULL);
4000 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4002 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb32_mt);
4003 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4004 hr = IPin_Disconnect(pin);
4005 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4007 format = rgb8_format;
4008 format.dwFlags = DDSD_HEIGHT;
4009 format.dwWidth = 333;
4010 format.dwHeight = 444;
4011 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &format, NULL);
4012 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4014 video_info = rgb555_video_info;
4015 video_info.bmiHeader.biWidth = 333;
4016 video_info.bmiHeader.biHeight = 444;
4017 mt = rgb555_mt;
4018 mt.pbFormat = (BYTE *)&video_info;
4019 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &mt);
4020 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4021 hr = IPin_Disconnect(pin);
4022 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4024 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb32_mt);
4025 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4026 hr = IPin_Disconnect(pin);
4027 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4029 video_info = rgb32_video_info;
4030 video_info.bmiHeader.biWidth = 332;
4031 video_info.bmiHeader.biHeight = 444;
4032 mt = rgb32_mt;
4033 mt.pbFormat = (BYTE *)&video_info;
4034 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &mt);
4035 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
4037 video_info = rgb32_video_info;
4038 video_info.bmiHeader.biWidth = 333;
4039 video_info.bmiHeader.biHeight = 443;
4040 mt = rgb32_mt;
4041 mt.pbFormat = (BYTE *)&video_info;
4042 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &mt);
4043 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
4045 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb8_format, NULL);
4046 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4048 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb555_mt);
4049 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
4051 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb8_mt);
4052 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4053 hr = IPin_Disconnect(pin);
4054 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4056 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb555_format, NULL);
4057 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4059 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb565_mt);
4060 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
4062 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb555_mt);
4063 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4064 hr = IPin_Disconnect(pin);
4065 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4067 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb565_format, NULL);
4068 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4070 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb24_mt);
4071 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
4073 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb565_mt);
4074 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4075 hr = IPin_Disconnect(pin);
4076 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4078 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb24_format, NULL);
4079 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4081 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb32_mt);
4082 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
4084 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb24_mt);
4085 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4086 hr = IPin_Disconnect(pin);
4087 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4089 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb32_format, NULL);
4090 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4092 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb8_mt);
4093 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
4095 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb32_mt);
4096 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4097 hr = IPin_Disconnect(pin);
4098 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4100 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &yuy2_format, NULL);
4101 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4103 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &yuy2_mt);
4104 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
4106 format = yuy2_format;
4107 format.ddpfPixelFormat.u2.dwRBitMask = 0xf800;
4108 format.ddpfPixelFormat.u3.dwGBitMask = 0x07e0;
4109 format.ddpfPixelFormat.u4.dwBBitMask = 0x001f;
4110 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &format, NULL);
4111 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4113 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb565_mt);
4114 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
4116 format = rgb8_format;
4117 format.dwFlags = 0;
4118 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &format, NULL);
4119 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4121 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb565_mt);
4122 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4123 hr = IPin_Disconnect(pin);
4124 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4126 ref = IAMMultiMediaStream_Release(mmstream);
4127 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4128 IPin_Release(pin);
4129 IDirectDrawMediaStream_Release(ddraw_stream);
4130 ref = IMediaStream_Release(stream);
4131 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4132 ref = IBaseFilter_Release(&source.filter.IBaseFilter_iface);
4133 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4136 static void test_audiostream_receive(void)
4138 ALLOCATOR_PROPERTIES properties =
4140 .cBuffers = 3,
4141 .cbBuffer = 16,
4142 .cbAlign = 1,
4145 IAMMultiMediaStream *mmstream = create_ammultimediastream();
4146 ALLOCATOR_PROPERTIES actual;
4147 struct testfilter source;
4148 IMemAllocator *allocator;
4149 IGraphBuilder *graph;
4150 IMediaStream *stream;
4151 IMediaSample *sample1;
4152 IMediaSample *sample2;
4153 IMediaSample *sample3;
4154 HRESULT hr;
4155 ULONG ref;
4156 IPin *pin;
4158 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
4159 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4160 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
4161 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4162 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
4163 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4164 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
4165 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4166 ok(graph != NULL, "Expected non-NULL graph.\n");
4167 testfilter_init(&source);
4168 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
4169 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4170 hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER, &IID_IMemAllocator, (void **)&allocator);
4171 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4172 hr = IMemAllocator_SetProperties(allocator, &properties, &actual);
4173 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4174 hr = IMemAllocator_Commit(allocator);
4175 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4177 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &audio_mt);
4178 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4180 hr = IMemAllocator_GetBuffer(allocator, &sample1, NULL, NULL, 0);
4181 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4182 hr = IMemInputPin_Receive(source.source.pMemInputPin, sample1);
4183 ok(hr == VFW_E_WRONG_STATE, "Got hr %#lx.\n", hr);
4184 ref = IMediaSample_Release(sample1);
4185 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4187 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4188 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4190 hr = IMemAllocator_GetBuffer(allocator, &sample1, NULL, NULL, 0);
4191 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4192 hr = IMemInputPin_Receive(source.source.pMemInputPin, sample1);
4193 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4194 ref = get_refcount(sample1);
4195 ok(ref == 2, "Got unexpected refcount %ld.\n", ref);
4197 hr = IMemAllocator_GetBuffer(allocator, &sample2, NULL, NULL, 0);
4198 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4199 hr = IMemInputPin_Receive(source.source.pMemInputPin, sample2);
4200 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4201 ref = get_refcount(sample2);
4202 ok(ref == 2, "Got unexpected refcount %ld.\n", ref);
4204 hr = IPin_EndOfStream(pin);
4205 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4207 hr = IMemAllocator_GetBuffer(allocator, &sample3, NULL, NULL, 0);
4208 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4209 hr = IMemInputPin_Receive(source.source.pMemInputPin, sample3);
4210 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4211 ref = get_refcount(sample3);
4212 ok(ref == 2, "Got unexpected refcount %ld.\n", ref);
4214 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4215 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4217 ref = IMediaSample_Release(sample1);
4218 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4219 ref = IMediaSample_Release(sample2);
4220 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4221 ref = IMediaSample_Release(sample3);
4222 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4224 hr = IMemAllocator_GetBuffer(allocator, &sample1, NULL, NULL, 0);
4225 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4226 hr = IMemInputPin_Receive(source.source.pMemInputPin, sample1);
4227 ok(hr == VFW_E_WRONG_STATE, "Got hr %#lx.\n", hr);
4228 ref = IMediaSample_Release(sample1);
4229 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4231 IGraphBuilder_Disconnect(graph, pin);
4232 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
4234 hr = IMemAllocator_Decommit(allocator);
4235 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4237 ref = IAMMultiMediaStream_Release(mmstream);
4238 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4239 ref = IGraphBuilder_Release(graph);
4240 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4241 IPin_Release(pin);
4242 ref = IMediaStream_Release(stream);
4243 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4244 ref = IMemAllocator_Release(allocator);
4245 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4248 static void test_audiostream_initialize(void)
4250 IAMMediaStream *stream;
4251 STREAM_TYPE type;
4252 MSPID mspid;
4253 HRESULT hr;
4254 ULONG ref;
4256 hr = CoCreateInstance(&CLSID_AMAudioStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream);
4257 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4259 /* Crashes on native. */
4260 if (0)
4262 hr = IAMMediaStream_Initialize(stream, NULL, 0, NULL, STREAMTYPE_WRITE);
4263 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
4266 hr = IAMMediaStream_Initialize(stream, NULL, 0, &test_mspid, STREAMTYPE_WRITE);
4267 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4269 hr = IAMMediaStream_GetInformation(stream, &mspid, &type);
4270 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4271 ok(IsEqualGUID(&mspid, &test_mspid), "Got mspid %s.\n", wine_dbgstr_guid(&mspid));
4272 ok(type == STREAMTYPE_WRITE, "Got type %u.\n", type);
4274 hr = IAMMediaStream_Initialize(stream, NULL, 0, &MSPID_PrimaryAudio, STREAMTYPE_READ);
4275 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4277 hr = IAMMediaStream_GetInformation(stream, &mspid, &type);
4278 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4279 ok(IsEqualGUID(&mspid, &MSPID_PrimaryAudio), "Got mspid %s.\n", wine_dbgstr_guid(&mspid));
4280 ok(type == STREAMTYPE_READ, "Got type %u.\n", type);
4282 ref = IAMMediaStream_Release(stream);
4283 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4286 static void test_audiostream_begin_flush_end_flush(void)
4288 IAMMultiMediaStream *mmstream = create_ammultimediastream();
4289 static const MSPID mspid = {0x88888888, 1};
4290 IAudioStreamSample *stream_sample;
4291 IAudioMediaStream *audio_stream;
4292 IMediaStreamFilter *filter;
4293 IMediaSample *media_sample;
4294 struct testfilter source2;
4295 struct testfilter source;
4296 IAMMediaStream *stream2;
4297 IAudioData *audio_data;
4298 IMediaStream *stream;
4299 struct graph graph;
4300 HRESULT hr;
4301 IPin *pin2;
4302 ULONG ref;
4303 IPin *pin;
4305 graph_init(&graph);
4306 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, (IGraphBuilder *)&graph.IFilterGraph2_iface);
4307 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4308 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
4309 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4310 hr = CoCreateInstance(&CLSID_AMAudioStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream2);
4311 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4312 hr = IAMMediaStream_Initialize(stream2, NULL, 0, &mspid, STREAMTYPE_READ);
4313 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4314 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)stream2, &mspid, 0, NULL);
4315 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4316 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
4317 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4318 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
4319 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4320 hr = IAMMediaStream_QueryInterface(stream2, &IID_IPin, (void **)&pin2);
4321 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4322 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
4323 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4324 testfilter_init(&source);
4325 testfilter_init(&source2);
4326 source.IMediaSeeking_iface.lpVtbl = &testsource_seeking_vtbl;
4327 hr = IFilterGraph2_AddFilter(&graph.IFilterGraph2_iface, &source.filter.IBaseFilter_iface, NULL);
4328 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4329 hr = IFilterGraph2_AddFilter(&graph.IFilterGraph2_iface, &source2.filter.IBaseFilter_iface, NULL);
4330 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4331 hr = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER, &IID_IAudioData, (void **)&audio_data);
4332 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4333 hr = IAudioData_SetBuffer(audio_data, 16, NULL, 0);
4334 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4335 hr = IAudioMediaStream_CreateSample(audio_stream, audio_data, 0, &stream_sample);
4336 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4338 hr = IFilterGraph2_ConnectDirect(&graph.IFilterGraph2_iface, &source.source.pin.IPin_iface, pin, &audio_mt);
4339 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4340 hr = IFilterGraph2_ConnectDirect(&graph.IFilterGraph2_iface, &source2.source.pin.IPin_iface, pin2, &audio_mt);
4341 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4343 hr = IMediaStreamFilter_SupportSeeking(filter, TRUE);
4344 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4346 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4347 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4349 hr = IMemAllocator_GetBuffer(source.source.pAllocator, &media_sample, NULL, NULL, 0);
4350 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4351 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
4352 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4353 ref = get_refcount(media_sample);
4354 ok(ref == 2, "Got unexpected refcount %ld.\n", ref);
4356 hr = IPin_EndOfStream(pin);
4357 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4359 hr = IPin_BeginFlush(pin);
4360 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4362 ref = IMediaSample_Release(media_sample);
4363 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4365 hr = IMemAllocator_GetBuffer(source.source.pAllocator, &media_sample, NULL, NULL, 0);
4366 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4367 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
4368 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
4370 ref = IMediaSample_Release(media_sample);
4371 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4373 hr = IAudioStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
4374 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
4376 hr = IPin_EndOfStream(pin);
4377 ok(hr == E_FAIL, "Got hr %#lx.\n", hr);
4379 hr = IPin_EndFlush(pin);
4380 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4382 hr = IMemAllocator_GetBuffer(source.source.pAllocator, &media_sample, NULL, NULL, 0);
4383 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4384 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
4385 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4386 ref = IMediaSample_Release(media_sample);
4387 ok(ref == 1, "Got outstanding refcount %ld.\n", ref);
4389 hr = IPin_EndOfStream(pin);
4390 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4392 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4393 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4394 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4395 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4397 hr = IPin_BeginFlush(pin);
4398 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4399 hr = IPin_EndFlush(pin);
4400 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4402 hr = IPin_EndOfStream(pin);
4403 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4405 graph.got_notify = 0;
4407 hr = IPin_EndOfStream(pin2);
4408 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4410 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
4411 ok(graph.event_code == EC_COMPLETE, "Got event code %ld.\n", graph.event_code);
4413 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4414 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4415 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4416 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4418 hr = IPin_EndOfStream(pin);
4419 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4421 hr = IPin_BeginFlush(pin);
4422 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4423 hr = IPin_EndFlush(pin);
4424 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4426 graph.got_notify = 0;
4427 graph.event_code = 0xcc;
4429 hr = IPin_EndOfStream(pin2);
4430 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4432 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
4434 hr = IPin_EndOfStream(pin);
4435 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4437 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
4438 ok(graph.event_code == EC_COMPLETE, "Got event code %ld.\n", graph.event_code);
4440 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4441 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4442 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4443 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4445 hr = IPin_EndOfStream(pin);
4446 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4448 hr = IPin_BeginFlush(pin);
4449 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4450 hr = IPin_EndFlush(pin);
4451 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4452 hr = IPin_BeginFlush(pin);
4453 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4454 hr = IPin_EndFlush(pin);
4455 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4457 hr = IPin_EndOfStream(pin);
4458 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4460 graph.got_notify = 0;
4461 graph.event_code = 0xcc;
4463 hr = IPin_EndOfStream(pin2);
4464 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4466 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
4467 ok(graph.event_code == EC_COMPLETE, "Got event code %ld.\n", graph.event_code);
4469 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4470 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4472 IFilterGraph2_Disconnect(&graph.IFilterGraph2_iface, pin);
4473 IFilterGraph2_Disconnect(&graph.IFilterGraph2_iface, &source.source.pin.IPin_iface);
4474 IFilterGraph2_Disconnect(&graph.IFilterGraph2_iface, pin2);
4475 IFilterGraph2_Disconnect(&graph.IFilterGraph2_iface, &source2.source.pin.IPin_iface);
4477 ref = IAudioStreamSample_Release(stream_sample);
4478 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4479 ref = IAudioData_Release(audio_data);
4480 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4481 ref = IAMMultiMediaStream_Release(mmstream);
4482 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4483 graph_destroy(&graph);
4484 ref = IMediaStreamFilter_Release(filter);
4485 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4486 IPin_Release(pin);
4487 IAudioMediaStream_Release(audio_stream);
4488 ref = IMediaStream_Release(stream);
4489 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4490 IPin_Release(pin2);
4491 ref = IAMMediaStream_Release(stream2);
4492 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4495 static IMediaSample *ammediastream_allocate_sample(struct testfilter *source, const BYTE *input_data, DWORD input_length)
4497 IMediaSample *sample;
4498 BYTE *sample_data;
4499 HRESULT hr;
4501 hr = IMemAllocator_GetBuffer(source->source.pAllocator, &sample, NULL, NULL, 0);
4502 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4504 hr = IMediaSample_GetPointer(sample, &sample_data);
4505 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4507 hr = IMediaSample_SetActualDataLength(sample, input_length);
4508 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4510 memcpy(sample_data, input_data, input_length);
4512 return sample;
4515 static void test_audiostream_new_segment(void)
4517 IAMMultiMediaStream *mmstream = create_ammultimediastream();
4518 static const BYTE test_data[8] = { 0 };
4519 IAudioStreamSample *stream_sample;
4520 IAudioMediaStream *audio_stream;
4521 IMemInputPin *mem_input_pin;
4522 IMediaSample *media_sample;
4523 struct testfilter source;
4524 IAudioData *audio_data;
4525 STREAM_TIME start_time;
4526 STREAM_TIME end_time;
4527 IGraphBuilder *graph;
4528 IMediaStream *stream;
4529 HRESULT hr;
4530 ULONG ref;
4531 IPin *pin;
4533 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
4534 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4535 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
4536 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4537 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
4538 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4539 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
4540 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4541 hr = IMediaStream_QueryInterface(stream, &IID_IMemInputPin, (void **)&mem_input_pin);
4542 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4543 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
4544 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4545 ok(graph != NULL, "Expected non-NULL graph.\n");
4546 testfilter_init(&source);
4547 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
4548 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4549 hr = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER, &IID_IAudioData, (void **)&audio_data);
4550 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4551 hr = IAudioMediaStream_CreateSample(audio_stream, audio_data, 0, &stream_sample);
4552 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4553 hr = IAudioData_SetBuffer(audio_data, 5, NULL, 0);
4554 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4556 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &audio_mt);
4557 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4558 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4559 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4561 hr = IPin_NewSegment(pin, 11111111, 22222222, 1.0);
4562 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4564 media_sample = ammediastream_allocate_sample(&source, test_data, 5);
4565 start_time = 12345678;
4566 end_time = 23456789;
4567 hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
4568 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4569 hr = IMemInputPin_Receive(mem_input_pin, media_sample);
4570 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4571 IMediaSample_Release(media_sample);
4573 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4574 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4576 start_time = 0xdeadbeefdeadbeef;
4577 end_time = 0xdeadbeefdeadbeef;
4578 hr = IAudioStreamSample_GetSampleTimes(stream_sample, &start_time, &end_time, NULL);
4579 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4580 ok(start_time == 23456789, "Got start time %s.\n", wine_dbgstr_longlong(start_time));
4581 ok(end_time == 23459057, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
4583 hr = IPin_NewSegment(pin, 11111111, 22222222, 2.0);
4584 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4586 media_sample = ammediastream_allocate_sample(&source, test_data, 5);
4587 start_time = 12345678;
4588 end_time = 23456789;
4589 hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
4590 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4591 hr = IMemInputPin_Receive(mem_input_pin, media_sample);
4592 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4593 IMediaSample_Release(media_sample);
4595 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4596 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4598 start_time = 0xdeadbeefdeadbeef;
4599 end_time = 0xdeadbeefdeadbeef;
4600 hr = IAudioStreamSample_GetSampleTimes(stream_sample, &start_time, &end_time, NULL);
4601 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4602 ok(start_time == 23456789, "Got start time %s.\n", wine_dbgstr_longlong(start_time));
4603 ok(end_time == 23459057, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
4605 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4606 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4607 IGraphBuilder_Disconnect(graph, pin);
4608 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
4610 ref = IAudioStreamSample_Release(stream_sample);
4611 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4612 ref = IAudioData_Release(audio_data);
4613 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4614 ref = IAMMultiMediaStream_Release(mmstream);
4615 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4616 ref = IGraphBuilder_Release(graph);
4617 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4618 IPin_Release(pin);
4619 IMemInputPin_Release(mem_input_pin);
4620 IAudioMediaStream_Release(audio_stream);
4621 ref = IMediaStream_Release(stream);
4622 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4625 static void CALLBACK apc_func(ULONG_PTR param)
4629 static IPin *ammediastream_pin;
4630 static IMemInputPin *ammediastream_mem_input_pin;
4631 static IMediaSample *ammediastream_media_sample;
4632 static DWORD ammediastream_sleep_time;
4633 static HRESULT ammediastream_expected_hr;
4635 static DWORD CALLBACK ammediastream_end_of_stream(void *param)
4637 HRESULT hr;
4639 Sleep(ammediastream_sleep_time);
4640 hr = IPin_EndOfStream(ammediastream_pin);
4641 ok(hr == ammediastream_expected_hr, "Got hr %#lx.\n", hr);
4643 return 0;
4646 static DWORD CALLBACK ammediastream_receive(void *param)
4648 HRESULT hr;
4650 Sleep(ammediastream_sleep_time);
4651 hr = IMemInputPin_Receive(ammediastream_mem_input_pin, ammediastream_media_sample);
4652 ok(hr == ammediastream_expected_hr, "Got hr %#lx.\n", hr);
4654 return 0;
4657 struct ammediastream_receive_release_param
4659 IMemInputPin *mem_input_pin;
4660 IMediaSample *media_sample;
4663 static DWORD CALLBACK ammediastream_receive_release(void *p)
4665 struct ammediastream_receive_release_param *param = (struct ammediastream_receive_release_param *)p;
4666 HRESULT hr;
4667 ULONG ref;
4669 hr = IMemInputPin_Receive(param->mem_input_pin, param->media_sample);
4670 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4672 ref = IMediaSample_Release(param->media_sample);
4673 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4675 free(p);
4677 return 0;
4680 static HANDLE ammediastream_async_receive_time(struct testfilter *source,
4681 REFERENCE_TIME start_time, REFERENCE_TIME end_time, const BYTE *input_data, DWORD input_length)
4683 struct ammediastream_receive_release_param *param;
4684 IMediaSample *sample;
4685 HRESULT hr;
4687 sample = ammediastream_allocate_sample(source, input_data, input_length);
4688 hr = IMediaSample_SetTime(sample, &start_time, &end_time);
4689 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4691 param = calloc(1, sizeof(*param));
4692 param->mem_input_pin = source->source.pMemInputPin;
4693 param->media_sample = sample;
4694 return CreateThread(NULL, 0, ammediastream_receive_release, param, 0, NULL);
4697 static IStreamSample *streamsample_sample;
4698 static DWORD streamsample_flags;
4699 static DWORD streamsample_timeout;
4700 static HRESULT streamsample_expected_hr;
4702 static DWORD CALLBACK streamsample_completion_status(void *param)
4704 HRESULT hr;
4706 hr = IStreamSample_CompletionStatus(streamsample_sample, streamsample_flags, streamsample_timeout);
4707 ok(hr == streamsample_expected_hr, "Got hr %#lx.\n", hr);
4709 return 0;
4712 static void test_audiostreamsample_update(void)
4714 static const BYTE test_data[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
4715 IAMMultiMediaStream *mmstream = create_ammultimediastream();
4716 IAudioStreamSample *stream_sample;
4717 IAudioMediaStream *audio_stream;
4718 IMediaControl *media_control;
4719 IMemInputPin *mem_input_pin;
4720 IMediaSample *media_sample1;
4721 IMediaSample *media_sample2;
4722 struct testfilter source;
4723 IAudioData *audio_data;
4724 IGraphBuilder *graph;
4725 IMediaStream *stream;
4726 DWORD actual_length;
4727 BYTE buffer[6];
4728 HANDLE thread;
4729 HANDLE event;
4730 HRESULT hr;
4731 ULONG ref;
4732 IPin *pin;
4734 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
4735 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4736 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
4737 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4738 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
4739 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4740 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
4741 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4742 hr = IMediaStream_QueryInterface(stream, &IID_IMemInputPin, (void **)&mem_input_pin);
4743 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4744 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
4745 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4746 ok(graph != NULL, "Expected non-NULL graph.\n");
4747 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void **)&media_control);
4748 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4749 testfilter_init(&source);
4750 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
4751 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4752 hr = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER, &IID_IAudioData, (void **)&audio_data);
4753 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4754 hr = IAudioMediaStream_CreateSample(audio_stream, audio_data, 0, &stream_sample);
4755 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4756 event = CreateEventW(NULL, FALSE, FALSE, NULL);
4757 ok(event != NULL, "Expected non-NULL event.");
4759 hr = IAudioStreamSample_Update(stream_sample, 0, event, apc_func, 0);
4760 ok(hr == MS_E_NOTINIT, "Got hr %#lx.\n", hr);
4762 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4763 ok(hr == MS_E_NOTINIT, "Got hr %#lx.\n", hr);
4765 hr = IAudioData_SetBuffer(audio_data, sizeof(buffer), buffer, 0);
4766 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4768 hr = IAudioStreamSample_Update(stream_sample, 0, event, apc_func, 0);
4769 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
4771 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4772 ok(hr == MS_E_NOTRUNNING, "Got hr %#lx.\n", hr);
4774 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4775 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4777 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4778 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#lx.\n", hr);
4780 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4781 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4782 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &audio_mt);
4783 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4784 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4785 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4787 media_sample1 = ammediastream_allocate_sample(&source, test_data, 8);
4788 hr = IMemInputPin_Receive(mem_input_pin, media_sample1);
4789 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4790 ref = get_refcount(media_sample1);
4791 ok(ref == 2, "Got unexpected refcount %ld.\n", ref);
4793 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4794 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4796 hr = IAudioData_GetInfo(audio_data, NULL, NULL, &actual_length);
4797 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4798 ok(actual_length == 6, "Got actual length %lu.\n", actual_length);
4800 ok(memcmp(buffer, test_data, 6) == 0, "Sample data didn't match.\n");
4802 ref = get_refcount(media_sample1);
4803 ok(ref == 2, "Got unexpected refcount %ld.\n", ref);
4805 media_sample2 = ammediastream_allocate_sample(&source, test_data, 8);
4806 hr = IMemInputPin_Receive(mem_input_pin, media_sample2);
4807 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4808 ref = get_refcount(media_sample2);
4809 ok(ref == 2, "Got unexpected refcount %ld.\n", ref);
4811 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4812 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4814 hr = IAudioData_GetInfo(audio_data, NULL, NULL, &actual_length);
4815 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4816 ok(actual_length == 6, "Got actual length %lu.\n", actual_length);
4818 ok(memcmp(buffer, &test_data[6], 2) == 0, "Sample data didn't match.\n");
4819 ok(memcmp(&buffer[2], test_data, 4) == 0, "Sample data didn't match.\n");
4821 ref = IMediaSample_Release(media_sample1);
4822 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4824 hr = IPin_EndOfStream(pin);
4825 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4827 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4828 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4830 hr = IAudioData_GetInfo(audio_data, NULL, NULL, &actual_length);
4831 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4832 ok(actual_length == 4, "Got actual length %lu.\n", actual_length);
4834 ok(memcmp(buffer, &test_data[4], 4) == 0, "Sample data didn't match.\n");
4836 ref = IMediaSample_Release(media_sample2);
4837 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4839 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4840 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#lx.\n", hr);
4842 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4843 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4844 hr = IMediaControl_Pause(media_control);
4845 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4847 media_sample1 = ammediastream_allocate_sample(&source, test_data, 6);
4848 hr = IMemInputPin_Receive(mem_input_pin, media_sample1);
4849 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4850 ref = IMediaSample_Release(media_sample1);
4851 ok(ref == 1, "Got outstanding refcount %ld.\n", ref);
4853 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4854 ok(hr == MS_E_NOTRUNNING, "Got hr %#lx.\n", hr);
4856 hr = IMediaControl_Stop(media_control);
4857 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4858 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4859 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4861 media_sample1 = ammediastream_allocate_sample(&source, test_data, 6);
4863 ammediastream_mem_input_pin = mem_input_pin;
4864 ammediastream_media_sample = media_sample1;
4865 ammediastream_sleep_time = 100;
4866 ammediastream_expected_hr = S_OK;
4867 thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
4869 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4870 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4872 hr = IAudioData_GetInfo(audio_data, NULL, NULL, &actual_length);
4873 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4874 ok(actual_length == 6, "Got actual length %lu.\n", actual_length);
4876 ok(memcmp(buffer, test_data, 6) == 0, "Sample data didn't match.\n");
4878 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
4879 CloseHandle(thread);
4881 ref = IMediaSample_Release(media_sample1);
4882 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4884 ammediastream_pin = pin;
4885 ammediastream_sleep_time = 100;
4886 ammediastream_expected_hr = S_OK;
4887 thread = CreateThread(NULL, 0, ammediastream_end_of_stream, NULL, 0, NULL);
4889 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4890 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#lx.\n", hr);
4892 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
4893 CloseHandle(thread);
4895 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4896 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4897 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4898 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4900 hr = IAudioStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
4901 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
4903 IAudioStreamSample_AddRef(stream_sample);
4904 ref = IAudioStreamSample_Release(stream_sample);
4905 ok(ref == 1, "Got outstanding refcount %ld.\n", ref);
4907 hr = IAudioStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
4908 ok(hr == MS_E_BUSY, "Got hr %#lx.\n", hr);
4910 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4911 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4912 IGraphBuilder_Disconnect(graph, pin);
4913 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
4914 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4915 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4917 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4918 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#lx.\n", hr);
4920 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4922 CloseHandle(event);
4923 ref = IAudioStreamSample_Release(stream_sample);
4924 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4925 ref = IAudioData_Release(audio_data);
4926 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4927 ref = IAMMultiMediaStream_Release(mmstream);
4928 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4929 IMediaControl_Release(media_control);
4930 ref = IGraphBuilder_Release(graph);
4931 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4932 IPin_Release(pin);
4933 IMemInputPin_Release(mem_input_pin);
4934 IAudioMediaStream_Release(audio_stream);
4935 ref = IMediaStream_Release(stream);
4936 ok(!ref, "Got outstanding refcount %ld.\n", ref);
4939 void test_audiostreamsample_completion_status(void)
4941 static const BYTE test_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
4942 IAMMultiMediaStream *mmstream = create_ammultimediastream();
4943 IAudioStreamSample *stream_sample1;
4944 IAudioStreamSample *stream_sample2;
4945 IAudioMediaStream *audio_stream;
4946 IMediaSample *media_sample;
4947 struct testfilter source;
4948 IAudioData *audio_data1;
4949 IAudioData *audio_data2;
4950 IGraphBuilder *graph;
4951 IMediaStream *stream;
4952 HANDLE event;
4953 HRESULT hr;
4954 ULONG ref;
4955 IPin *pin;
4957 event = CreateEventW(NULL, FALSE, FALSE, NULL);
4958 ok(event != NULL, "Expected non-NULL event.");
4960 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
4961 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4962 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
4963 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4964 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
4965 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4966 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
4967 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4968 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
4969 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4970 ok(graph != NULL, "Expected non-NULL graph.\n");
4971 testfilter_init(&source);
4972 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
4973 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4974 hr = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER, &IID_IAudioData, (void **)&audio_data1);
4975 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4976 hr = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER, &IID_IAudioData, (void **)&audio_data2);
4977 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4978 hr = IAudioData_SetBuffer(audio_data1, 6, NULL, 0);
4979 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4980 hr = IAudioData_SetBuffer(audio_data2, 6, NULL, 0);
4981 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4982 hr = IAudioMediaStream_CreateSample(audio_stream, audio_data1, 0, &stream_sample1);
4983 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4984 hr = IAudioMediaStream_CreateSample(audio_stream, audio_data2, 0, &stream_sample2);
4985 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4987 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &audio_mt);
4988 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4989 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4990 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4992 hr = IAudioStreamSample_CompletionStatus(stream_sample1, 0, 0);
4993 ok(hr == S_OK, "Got hr %#lx.\n", hr);
4995 hr = IAudioStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
4996 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
4998 hr = IAudioStreamSample_CompletionStatus(stream_sample1, 0, 0);
4999 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
5001 media_sample = ammediastream_allocate_sample(&source, test_data, 6);
5002 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
5003 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5004 ref = IMediaSample_Release(media_sample);
5005 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5007 hr = IAudioStreamSample_CompletionStatus(stream_sample1, 0, 0);
5008 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5010 hr = IAudioStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
5011 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
5013 hr = IAudioStreamSample_Update(stream_sample2, SSUPDATE_ASYNC, NULL, NULL, 0);
5014 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
5016 media_sample = ammediastream_allocate_sample(&source, test_data, 12);
5017 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
5018 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5019 ref = IMediaSample_Release(media_sample);
5020 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5022 hr = IAudioStreamSample_CompletionStatus(stream_sample1, 0, 0);
5023 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5025 hr = IAudioStreamSample_CompletionStatus(stream_sample2, 0, 0);
5026 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5028 hr = IAudioStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
5029 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
5031 hr = IPin_EndOfStream(pin);
5032 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5034 hr = IAudioStreamSample_CompletionStatus(stream_sample1, 0, 0);
5035 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#lx.\n", hr);
5037 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
5038 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5039 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
5040 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5042 hr = IAudioStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
5043 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
5045 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
5046 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5048 hr = IAudioStreamSample_CompletionStatus(stream_sample1, 0, 0);
5049 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
5051 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
5052 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5054 media_sample = ammediastream_allocate_sample(&source, test_data, 6);
5055 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
5056 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5057 ref = IMediaSample_Release(media_sample);
5058 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5060 hr = IAudioStreamSample_CompletionStatus(stream_sample1, 0, 0);
5061 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5063 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
5064 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5066 IGraphBuilder_Disconnect(graph, pin);
5067 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
5069 ref = IAudioStreamSample_Release(stream_sample1);
5070 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5071 ref = IAudioStreamSample_Release(stream_sample2);
5072 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5073 ref = IAudioData_Release(audio_data1);
5074 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5075 ref = IAudioData_Release(audio_data2);
5076 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5077 ref = IAMMultiMediaStream_Release(mmstream);
5078 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5079 ref = IGraphBuilder_Release(graph);
5080 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5081 IPin_Release(pin);
5082 IAudioMediaStream_Release(audio_stream);
5083 ref = IMediaStream_Release(stream);
5084 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5086 CloseHandle(event);
5089 static void test_audiostreamsample_get_sample_times(void)
5091 IAMMultiMediaStream *mmstream = create_ammultimediastream();
5092 static const BYTE test_data[8] = { 0 };
5093 IAudioStreamSample *stream_sample;
5094 IMediaFilter *graph_media_filter;
5095 IAudioMediaStream *audio_stream;
5096 STREAM_TIME filter_start_time;
5097 IMemInputPin *mem_input_pin;
5098 IMediaStreamFilter *filter;
5099 IMediaSample *media_sample;
5100 struct testfilter source;
5101 STREAM_TIME current_time;
5102 struct testclock clock;
5103 IAudioData *audio_data;
5104 STREAM_TIME start_time;
5105 STREAM_TIME end_time;
5106 IGraphBuilder *graph;
5107 IMediaStream *stream;
5108 HRESULT hr;
5109 ULONG ref;
5110 IPin *pin;
5112 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
5113 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5114 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
5115 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5116 ok(!!filter, "Expected non-null filter.\n");
5117 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
5118 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5119 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
5120 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5121 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
5122 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5123 hr = IMediaStream_QueryInterface(stream, &IID_IMemInputPin, (void **)&mem_input_pin);
5124 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5125 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
5126 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5127 ok(graph != NULL, "Expected non-NULL graph.\n");
5128 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void **)&graph_media_filter);
5129 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5130 testfilter_init(&source);
5131 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
5132 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5133 hr = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER, &IID_IAudioData, (void **)&audio_data);
5134 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5135 hr = IAudioMediaStream_CreateSample(audio_stream, audio_data, 0, &stream_sample);
5136 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5137 hr = IAudioData_SetBuffer(audio_data, 5, NULL, 0);
5138 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5139 testclock_init(&clock);
5141 clock.time = 12345678;
5143 current_time = 0xdeadbeefdeadbeef;
5144 hr = IAudioStreamSample_GetSampleTimes(stream_sample, NULL, NULL, &current_time);
5145 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5146 ok(current_time == 0, "Got current time %s.\n", wine_dbgstr_longlong(current_time));
5148 hr = IMediaFilter_SetSyncSource(graph_media_filter, &clock.IReferenceClock_iface);
5149 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5151 current_time = 0xdeadbeefdeadbeef;
5152 hr = IAudioStreamSample_GetSampleTimes(stream_sample, NULL, NULL, &current_time);
5153 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5154 ok(current_time == 0, "Got current time %s.\n", wine_dbgstr_longlong(current_time));
5156 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &audio_mt);
5157 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5158 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
5159 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5161 hr = IMediaStreamFilter_GetCurrentStreamTime(filter, &filter_start_time);
5162 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5164 clock.get_time_hr = E_FAIL;
5166 current_time = 0xdeadbeefdeadbeef;
5167 hr = IAudioStreamSample_GetSampleTimes(stream_sample, NULL, NULL, &current_time);
5168 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5169 ok(current_time == 0xdeadbeefddf15da1 + filter_start_time, "Expected current time %s, got %s.\n",
5170 wine_dbgstr_longlong(0xdeadbeefddf15da1 + filter_start_time), wine_dbgstr_longlong(current_time));
5172 clock.get_time_hr = S_OK;
5174 current_time = 0xdeadbeefdeadbeef;
5175 hr = IAudioStreamSample_GetSampleTimes(stream_sample, NULL, NULL, &current_time);
5176 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5177 ok(current_time == filter_start_time, "Expected current time %s, got %s.\n",
5178 wine_dbgstr_longlong(filter_start_time), wine_dbgstr_longlong(current_time));
5180 clock.time = 23456789;
5182 current_time = 0xdeadbeefdeadbeef;
5183 hr = IAudioStreamSample_GetSampleTimes(stream_sample, NULL, NULL, &current_time);
5184 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5185 ok(current_time == filter_start_time + 11111111, "Expected current time %s, got %s.\n",
5186 wine_dbgstr_longlong(filter_start_time + 11111111), wine_dbgstr_longlong(current_time));
5188 start_time = 0xdeadbeefdeadbeef;
5189 end_time = 0xdeadbeefdeadbeef;
5190 hr = IAudioStreamSample_GetSampleTimes(stream_sample, &start_time, &end_time, NULL);
5191 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5192 ok(start_time == 0, "Got start time %s.\n", wine_dbgstr_longlong(start_time));
5193 ok(end_time == 0, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
5195 media_sample = ammediastream_allocate_sample(&source, test_data, 8);
5196 start_time = 12345678;
5197 end_time = 23456789;
5198 hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
5199 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5200 hr = IMemInputPin_Receive(mem_input_pin, media_sample);
5201 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5202 IMediaSample_Release(media_sample);
5204 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
5205 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5207 start_time = 0xdeadbeefdeadbeef;
5208 end_time = 0xdeadbeefdeadbeef;
5209 hr = IAudioStreamSample_GetSampleTimes(stream_sample, &start_time, &end_time, NULL);
5210 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5211 ok(start_time == 12345678, "Got start time %s.\n", wine_dbgstr_longlong(start_time));
5212 ok(end_time == 12347946, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
5214 media_sample = ammediastream_allocate_sample(&source, test_data, 6);
5215 start_time = 12345678;
5216 end_time = 23456789;
5217 hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
5218 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5219 hr = IMemInputPin_Receive(mem_input_pin, media_sample);
5220 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5221 IMediaSample_Release(media_sample);
5223 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
5224 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5226 start_time = 0xdeadbeefdeadbeef;
5227 end_time = 0xdeadbeefdeadbeef;
5228 hr = IAudioStreamSample_GetSampleTimes(stream_sample, &start_time, &end_time, NULL);
5229 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5230 ok(start_time == 12347946, "Got start time %s.\n", wine_dbgstr_longlong(start_time));
5231 ok(end_time == 12346585, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
5233 hr = IPin_EndOfStream(pin);
5234 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5236 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
5237 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5239 start_time = 0xdeadbeefdeadbeef;
5240 end_time = 0xdeadbeefdeadbeef;
5241 hr = IAudioStreamSample_GetSampleTimes(stream_sample, &start_time, &end_time, NULL);
5242 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5243 ok(start_time == 12346585, "Got start time %s.\n", wine_dbgstr_longlong(start_time));
5244 ok(end_time == 12348399, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
5246 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
5247 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5248 IGraphBuilder_Disconnect(graph, pin);
5249 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
5251 ref = IAudioStreamSample_Release(stream_sample);
5252 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5253 ref = IAudioData_Release(audio_data);
5254 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5255 ref = IAMMultiMediaStream_Release(mmstream);
5256 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5257 IMediaFilter_Release(graph_media_filter);
5258 ref = IGraphBuilder_Release(graph);
5259 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5260 ref = IMediaStreamFilter_Release(filter);
5261 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5262 IPin_Release(pin);
5263 IMemInputPin_Release(mem_input_pin);
5264 IAudioMediaStream_Release(audio_stream);
5265 ref = IMediaStream_Release(stream);
5266 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5269 static void test_ddrawstream_initialize(void)
5271 IDirectDrawMediaStream *ddraw_stream;
5272 IAMMediaStream *stream;
5273 IDirectDraw *ddraw2;
5274 IDirectDraw *ddraw;
5275 STREAM_TYPE type;
5276 MSPID mspid;
5277 HRESULT hr;
5278 ULONG ref;
5280 hr = DirectDrawCreate(NULL, &ddraw, NULL);
5281 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5283 hr = CoCreateInstance(&CLSID_AMDirectDrawStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream);
5284 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5286 hr = IAMMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
5287 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5289 /* Crashes on native. */
5290 if (0)
5292 hr = IAMMediaStream_Initialize(stream, NULL, 0, NULL, STREAMTYPE_WRITE);
5293 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
5296 hr = IAMMediaStream_Initialize(stream, NULL, 0, &test_mspid, STREAMTYPE_WRITE);
5297 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5299 hr = IAMMediaStream_GetInformation(stream, &mspid, &type);
5300 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5301 ok(IsEqualGUID(&mspid, &test_mspid), "Got mspid %s.\n", wine_dbgstr_guid(&mspid));
5302 ok(type == STREAMTYPE_WRITE, "Got type %u.\n", type);
5304 hr = IAMMediaStream_Initialize(stream, (IUnknown *)ddraw, 0, &MSPID_PrimaryAudio, STREAMTYPE_READ);
5305 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5307 hr = IAMMediaStream_GetInformation(stream, &mspid, &type);
5308 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5309 ok(IsEqualGUID(&mspid, &MSPID_PrimaryAudio), "Got mspid %s.\n", wine_dbgstr_guid(&mspid));
5310 ok(type == STREAMTYPE_READ, "Got type %u.\n", type);
5312 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw2);
5313 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5314 ok(ddraw2 == ddraw, "Expected ddraw %p, got %p.\n", ddraw, ddraw2);
5316 IDirectDrawMediaStream_Release(ddraw_stream);
5317 ref = IAMMediaStream_Release(stream);
5318 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5319 IDirectDraw_Release(ddraw2);
5320 ref = IDirectDraw_Release(ddraw);
5321 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5324 #define check_ddrawstream_get_format(a,b,c) check_ddrawstream_get_format_(__LINE__,a,b,c)
5325 static void check_ddrawstream_get_format_(int line, IDirectDrawMediaStream *stream,
5326 const AM_MEDIA_TYPE *mt, const DDSURFACEDESC *expected_format)
5328 DDSURFACEDESC current_format;
5329 DDSURFACEDESC desired_format;
5330 struct testfilter source;
5331 FILTER_INFO filter_info;
5332 DDSURFACEDESC format;
5333 PIN_INFO pin_info;
5334 DWORD flags;
5335 HRESULT hr;
5336 IPin *pin;
5338 hr = IDirectDrawMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
5339 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
5340 hr = IPin_QueryPinInfo(pin, &pin_info);
5341 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
5342 hr = IBaseFilter_QueryFilterInfo(pin_info.pFilter, &filter_info);
5343 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
5345 testfilter_init(&source);
5347 hr = IFilterGraph_AddFilter(filter_info.pGraph, &source.filter.IBaseFilter_iface, L"source");
5348 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
5350 hr = IFilterGraph_ConnectDirect(filter_info.pGraph, &source.source.pin.IPin_iface, pin, mt);
5351 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
5353 hr = IDirectDrawMediaStream_GetFormat(stream, NULL, NULL, NULL, NULL);
5354 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
5356 memset(&current_format, 0xcc, sizeof(current_format));
5357 current_format.dwSize = sizeof(current_format);
5358 memset(&desired_format, 0xcc, sizeof(desired_format));
5359 desired_format.dwSize = sizeof(desired_format);
5360 flags = 0xdeadbeef;
5361 hr = IDirectDrawMediaStream_GetFormat(stream, &current_format, NULL, &desired_format, &flags);
5362 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
5363 memset(&format, 0xcc, sizeof(format));
5364 format.dwSize = sizeof(format);
5365 format.ddpfPixelFormat = expected_format->ddpfPixelFormat;
5366 format.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5367 format.dwWidth = 333;
5368 format.dwHeight = 444;
5369 format.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
5370 ok_(__FILE__, line)(memcmp(&current_format, &format, sizeof(DDSURFACEDESC)) == 0, "Current format didn't match.\n");
5371 format.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
5372 ok_(__FILE__, line)(memcmp(&desired_format, &format, sizeof(DDSURFACEDESC)) == 0, "Desired format didn't match.\n");
5374 hr = IFilterGraph_Disconnect(filter_info.pGraph, &source.source.pin.IPin_iface);
5375 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
5376 hr = IFilterGraph_Disconnect(filter_info.pGraph, pin);
5377 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
5379 hr = IFilterGraph_RemoveFilter(filter_info.pGraph, &source.filter.IBaseFilter_iface);
5380 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
5382 IFilterGraph_Release(filter_info.pGraph);
5383 IBaseFilter_Release(pin_info.pFilter);
5384 IPin_Release(pin);
5387 static void test_ddrawstream_get_format(void)
5389 IAMMultiMediaStream *mmstream = create_ammultimediastream();
5390 IDirectDrawMediaStream *ddraw_stream;
5391 DDSURFACEDESC current_format;
5392 DDSURFACEDESC desired_format;
5393 IDirectDrawPalette *palette;
5394 IMediaStream *stream;
5395 VIDEOINFO video_info;
5396 AM_MEDIA_TYPE mt;
5397 DWORD flags;
5398 HRESULT hr;
5399 ULONG ref;
5401 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
5402 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5403 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
5404 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5406 current_format.dwSize = sizeof(current_format);
5407 desired_format.dwSize = sizeof(desired_format);
5408 hr = IDirectDrawMediaStream_GetFormat(ddraw_stream, &current_format, &palette, &desired_format, &flags);
5409 ok(hr == MS_E_NOSTREAM, "Got hr %#lx.\n", hr);
5411 video_info = rgb32_video_info;
5412 video_info.rcSource.right = 222;
5413 video_info.rcSource.bottom = 333;
5414 video_info.rcTarget.right = 444;
5415 video_info.rcTarget.bottom = 666;
5416 mt = rgb32_mt;
5417 mt.pbFormat = (BYTE *)&video_info;
5418 check_ddrawstream_get_format(ddraw_stream, &mt, &rgb32_format);
5420 video_info = rgb32_video_info;
5421 video_info.bmiHeader.biHeight = 444;
5422 mt = rgb32_mt;
5423 mt.pbFormat = (BYTE *)&video_info;
5424 check_ddrawstream_get_format(ddraw_stream, &mt, &rgb32_format);
5426 check_ddrawstream_get_format(ddraw_stream, &rgb8_mt, &rgb8_format);
5427 check_ddrawstream_get_format(ddraw_stream, &rgb555_mt, &rgb555_format);
5428 check_ddrawstream_get_format(ddraw_stream, &rgb565_mt, &rgb565_format);
5429 check_ddrawstream_get_format(ddraw_stream, &rgb24_mt, &rgb24_format);
5430 check_ddrawstream_get_format(ddraw_stream, &rgb32_mt, &rgb32_format);
5432 current_format.dwSize = sizeof(current_format);
5433 desired_format.dwSize = sizeof(desired_format);
5434 hr = IDirectDrawMediaStream_GetFormat(ddraw_stream, &current_format, &palette, &desired_format, &flags);
5435 ok(hr == MS_E_NOSTREAM, "Got hr %#lx.\n", hr);
5437 ref = IAMMultiMediaStream_Release(mmstream);
5438 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5439 IDirectDrawMediaStream_Release(ddraw_stream);
5440 ref = IMediaStream_Release(stream);
5441 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5444 #define check_ddrawstream_set_format(a,b,c,d) check_ddrawstream_set_format_(__LINE__,a,b,c,d)
5445 static void check_ddrawstream_set_format_(int line, IDirectDrawMediaStream *stream,
5446 const DDSURFACEDESC *format, const AM_MEDIA_TYPE *mt, HRESULT expected_hr)
5448 struct testfilter source;
5449 FILTER_INFO filter_info;
5450 PIN_INFO pin_info;
5451 HRESULT hr;
5452 IPin *pin;
5454 hr = IDirectDrawMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
5455 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
5456 hr = IPin_QueryPinInfo(pin, &pin_info);
5457 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
5458 hr = IBaseFilter_QueryFilterInfo(pin_info.pFilter, &filter_info);
5459 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
5461 testfilter_init(&source);
5463 hr = IFilterGraph_AddFilter(filter_info.pGraph, &source.filter.IBaseFilter_iface, L"source");
5464 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
5466 hr = IDirectDrawMediaStream_SetFormat(stream, format, NULL);
5467 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#lx.\n", hr);
5469 if (mt)
5471 DDSURFACEDESC current_format;
5472 DDSURFACEDESC desired_format;
5473 DWORD flags;
5475 hr = IFilterGraph_ConnectDirect(filter_info.pGraph, &source.source.pin.IPin_iface, pin, mt);
5476 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
5478 memset(&current_format, 0xcc, sizeof(current_format));
5479 memset(&desired_format, 0xcc, sizeof(desired_format));
5480 flags = 0xdeadbeef;
5481 current_format.dwSize = sizeof(current_format);
5482 desired_format.dwSize = sizeof(desired_format);
5483 hr = IDirectDrawMediaStream_GetFormat(stream, &current_format, NULL, &desired_format, &flags);
5484 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
5485 if (format->dwFlags & DDSD_PIXELFORMAT)
5487 ok_(__FILE__, line)(current_format.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT),
5488 "Got current format flags %#lx.\n", current_format.dwFlags);
5489 ok_(__FILE__, line)(memcmp(&current_format.ddpfPixelFormat, &format->ddpfPixelFormat, sizeof(DDPIXELFORMAT)) == 0,
5490 "Current pixel format didn't match.\n");
5491 ok_(__FILE__, line)(memcmp(&desired_format.ddpfPixelFormat, &format->ddpfPixelFormat, sizeof(DDPIXELFORMAT)) == 0,
5492 "Desired pixel format didn't match.\n");
5494 else
5496 ok_(__FILE__, line)(current_format.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS),
5497 "Got flags %#lx.\n", current_format.dwFlags);
5499 ok_(__FILE__, line)(desired_format.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT),
5500 "Got desired format flags %#lx.\n", desired_format.dwFlags);
5501 ok_(__FILE__, line)(current_format.ddsCaps.dwCaps == (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY),
5502 "Got current format caps %#lx.\n", current_format.ddsCaps.dwCaps);
5503 ok_(__FILE__, line)(desired_format.ddsCaps.dwCaps == (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY),
5504 "Got desired format caps %#lx.\n", desired_format.ddsCaps.dwCaps);
5505 ok_(__FILE__, line)(flags == 0, "Got flags %#lx.\n", flags);
5507 hr = IFilterGraph_Disconnect(filter_info.pGraph, &source.source.pin.IPin_iface);
5508 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
5509 hr = IFilterGraph_Disconnect(filter_info.pGraph, pin);
5510 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
5513 hr = IFilterGraph_RemoveFilter(filter_info.pGraph, &source.filter.IBaseFilter_iface);
5514 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
5516 IFilterGraph_Release(filter_info.pGraph);
5517 IBaseFilter_Release(pin_info.pFilter);
5518 IPin_Release(pin);
5521 static void test_ddrawstream_set_format(void)
5523 static const DDSURFACEDESC rgb1_format =
5525 .dwSize = sizeof(DDSURFACEDESC),
5526 .dwFlags = DDSD_PIXELFORMAT,
5527 .ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT),
5528 .ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED1,
5529 .ddpfPixelFormat.u1.dwRGBBitCount = 1,
5531 static const DDSURFACEDESC rgb2_format =
5533 .dwSize = sizeof(DDSURFACEDESC),
5534 .dwFlags = DDSD_PIXELFORMAT,
5535 .ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT),
5536 .ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED2,
5537 .ddpfPixelFormat.u1.dwRGBBitCount = 2,
5539 static const DDSURFACEDESC rgb4_format =
5541 .dwSize = sizeof(DDSURFACEDESC),
5542 .dwFlags = DDSD_PIXELFORMAT,
5543 .ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT),
5544 .ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED4,
5545 .ddpfPixelFormat.u1.dwRGBBitCount = 4,
5547 static const DDSURFACEDESC rgb4to8_format =
5549 .dwSize = sizeof(DDSURFACEDESC),
5550 .dwFlags = DDSD_PIXELFORMAT,
5551 .ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT),
5552 .ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXEDTO8,
5553 .ddpfPixelFormat.u1.dwRGBBitCount = 4,
5555 static const DDSURFACEDESC rgb332_format =
5557 .dwSize = sizeof(DDSURFACEDESC),
5558 .dwFlags = DDSD_PIXELFORMAT,
5559 .ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT),
5560 .ddpfPixelFormat.dwFlags = DDPF_RGB,
5561 .ddpfPixelFormat.u1.dwRGBBitCount = 8,
5562 .ddpfPixelFormat.u2.dwRBitMask = 0xe0,
5563 .ddpfPixelFormat.u3.dwGBitMask = 0x1c,
5564 .ddpfPixelFormat.u4.dwBBitMask = 0x03,
5567 IDirectDrawMediaStream *ddraw_stream;
5568 IAMMultiMediaStream *mmstream;
5569 DDSURFACEDESC current_format;
5570 DDSURFACEDESC desired_format;
5571 struct testfilter source;
5572 IGraphBuilder *graph;
5573 DDSURFACEDESC format;
5574 IMediaStream *stream;
5575 VIDEOINFO video_info;
5576 AM_MEDIA_TYPE mt;
5577 HRESULT hr;
5578 ULONG ref;
5579 IPin *pin;
5581 mmstream = create_ammultimediastream();
5583 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
5584 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5585 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
5586 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5588 check_ddrawstream_set_format(ddraw_stream, &rgb8_format, &rgb8_mt, S_OK);
5589 check_ddrawstream_set_format(ddraw_stream, &rgb555_format, &rgb555_mt, S_OK);
5590 check_ddrawstream_set_format(ddraw_stream, &rgb565_format, &rgb565_mt, S_OK);
5591 check_ddrawstream_set_format(ddraw_stream, &rgb24_format, &rgb24_mt, S_OK);
5592 check_ddrawstream_set_format(ddraw_stream, &rgb32_format, &rgb32_mt, S_OK);
5593 check_ddrawstream_set_format(ddraw_stream, &argb32_format, &rgb32_mt, S_OK);
5594 check_ddrawstream_set_format(ddraw_stream, &yuy2_format, NULL, S_OK);
5595 check_ddrawstream_set_format(ddraw_stream, &yv12_format, NULL, S_OK);
5597 format = rgb32_format;
5598 format.ddpfPixelFormat.dwFlags |= DDPF_ALPHAPIXELS | DDPF_ALPHA
5599 | DDPF_COMPRESSED | DDPF_RGBTOYUV | DDPF_ZBUFFER | DDPF_ZPIXELS | DDPF_STENCILBUFFER
5600 | DDPF_ALPHAPREMULT | DDPF_LUMINANCE | DDPF_BUMPLUMINANCE | DDPF_BUMPDUDV;
5601 check_ddrawstream_set_format(ddraw_stream, &format, &rgb32_mt, S_OK);
5603 format = yuy2_format;
5604 format.ddpfPixelFormat.dwFlags |= DDPF_ALPHAPIXELS | DDPF_ALPHA
5605 | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXEDTO8 | DDPF_PALETTEINDEXED8
5606 | DDPF_RGB | DDPF_COMPRESSED | DDPF_RGBTOYUV | DDPF_YUV | DDPF_ZBUFFER
5607 | DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 | DDPF_ZPIXELS
5608 | DDPF_STENCILBUFFER | DDPF_ALPHAPREMULT | DDPF_LUMINANCE
5609 | DDPF_BUMPLUMINANCE | DDPF_BUMPDUDV;
5610 check_ddrawstream_set_format(ddraw_stream, &format, NULL, S_OK);
5612 format = rgb32_format;
5613 format.dwFlags |= DDSD_CAPS;
5614 format.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
5615 check_ddrawstream_set_format(ddraw_stream, &format, &rgb32_mt, S_OK);
5617 format = rgb8_format;
5618 format.dwFlags = 0;
5619 check_ddrawstream_set_format(ddraw_stream, &format, &rgb32_mt, S_OK);
5621 check_ddrawstream_set_format(ddraw_stream, &rgb1_format, NULL, DDERR_INVALIDSURFACETYPE);
5622 check_ddrawstream_set_format(ddraw_stream, &rgb2_format, NULL, DDERR_INVALIDSURFACETYPE);
5623 check_ddrawstream_set_format(ddraw_stream, &rgb4_format, NULL, DDERR_INVALIDSURFACETYPE);
5624 check_ddrawstream_set_format(ddraw_stream, &rgb4to8_format, NULL, DDERR_INVALIDSURFACETYPE);
5625 check_ddrawstream_set_format(ddraw_stream, &rgb332_format, NULL, DDERR_INVALIDSURFACETYPE);
5627 format = rgb8_format;
5628 format.ddpfPixelFormat.dwFlags &= ~DDPF_RGB;
5629 check_ddrawstream_set_format(ddraw_stream, &format, NULL, DDERR_INVALIDSURFACETYPE);
5631 format = rgb8_format;
5632 format.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED1;
5633 check_ddrawstream_set_format(ddraw_stream, &format, NULL, DDERR_INVALIDSURFACETYPE);
5635 format = rgb32_format;
5636 format.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED8;
5637 check_ddrawstream_set_format(ddraw_stream, &format, NULL, DDERR_INVALIDSURFACETYPE);
5639 format = rgb32_format;
5640 format.ddpfPixelFormat.dwFlags |= DDPF_YUV;
5641 check_ddrawstream_set_format(ddraw_stream, &format, NULL, DDERR_INVALIDSURFACETYPE);
5643 format = rgb565_format;
5644 format.ddpfPixelFormat.u2.dwRBitMask = 0x001f;
5645 format.ddpfPixelFormat.u3.dwGBitMask = 0x07e0;
5646 format.ddpfPixelFormat.u4.dwBBitMask = 0xf800;
5647 check_ddrawstream_set_format(ddraw_stream, &format, NULL, DDERR_INVALIDSURFACETYPE);
5649 format = rgb32_format;
5650 format.ddpfPixelFormat.u2.dwRBitMask = 0x00ff00;
5651 format.ddpfPixelFormat.u3.dwGBitMask = 0x0000ff;
5652 format.ddpfPixelFormat.u4.dwBBitMask = 0xff0000;
5653 check_ddrawstream_set_format(ddraw_stream, &format, NULL, DDERR_INVALIDSURFACETYPE);
5655 format = yuy2_format;
5656 format.ddpfPixelFormat.u1.dwYUVBitCount = 0;
5657 check_ddrawstream_set_format(ddraw_stream, &format, NULL, E_INVALIDARG);
5659 format = rgb32_format;
5660 format.dwSize = sizeof(DDSURFACEDESC) + 1;
5661 check_ddrawstream_set_format(ddraw_stream, &format, NULL, E_INVALIDARG);
5663 format = rgb32_format;
5664 format.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT) + 1;
5665 check_ddrawstream_set_format(ddraw_stream, &format, NULL, DDERR_INVALIDSURFACETYPE);
5667 ref = IAMMultiMediaStream_Release(mmstream);
5668 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5669 IDirectDrawMediaStream_Release(ddraw_stream);
5670 ref = IMediaStream_Release(stream);
5671 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5673 mmstream = create_ammultimediastream();
5675 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
5676 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5677 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
5678 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5679 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
5680 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5682 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
5683 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5684 ok(!!graph, "Expected non-NULL graph.\n");
5686 testfilter_init(&source);
5688 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, L"source");
5689 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5691 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &rgb8_mt);
5692 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5694 source.preferred_mt = NULL;
5696 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb555_format, NULL);
5697 ok(hr == DDERR_INVALIDSURFACETYPE, "Got hr %#lx.\n", hr);
5698 ok(IsEqualGUID(&source.source.pin.mt.subtype, &MEDIASUBTYPE_RGB8),
5699 "Got subtype %s.\n", wine_dbgstr_guid(&source.source.pin.mt.subtype));
5700 hr = IDirectDrawMediaStream_GetFormat(ddraw_stream, &current_format, NULL, &desired_format, NULL);
5701 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5702 ok(current_format.ddpfPixelFormat.u1.dwRGBBitCount == 8,
5703 "Got rgb bit count %lu.\n", current_format.ddpfPixelFormat.u1.dwRGBBitCount);
5704 ok(desired_format.ddpfPixelFormat.u1.dwRGBBitCount == 8,
5705 "Got rgb bit count %lu.\n", desired_format.ddpfPixelFormat.u1.dwRGBBitCount);
5707 format = rgb555_format;
5708 format.dwFlags = 0;
5709 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &format, NULL);
5710 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5711 ok(IsEqualGUID(&source.source.pin.mt.subtype, &MEDIASUBTYPE_RGB8),
5712 "Got subtype %s.\n", wine_dbgstr_guid(&source.source.pin.mt.subtype));
5714 source.preferred_mt = &rgb555_mt;
5716 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb8_format, NULL);
5717 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5719 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb555_format, NULL);
5720 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5721 ok(IsEqualGUID(&source.source.pin.mt.subtype, &MEDIASUBTYPE_RGB555),
5722 "Got subtype %s.\n", wine_dbgstr_guid(&source.source.pin.mt.subtype));
5723 hr = IDirectDrawMediaStream_GetFormat(ddraw_stream, &current_format, NULL, &desired_format, NULL);
5724 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5725 ok(current_format.ddpfPixelFormat.u1.dwRGBBitCount == 16,
5726 "Got rgb bit count %lu.\n", current_format.ddpfPixelFormat.u1.dwRGBBitCount);
5727 ok(desired_format.ddpfPixelFormat.u1.dwRGBBitCount == 16,
5728 "Got rgb bit count %lu.\n", desired_format.ddpfPixelFormat.u1.dwRGBBitCount);
5730 video_info = rgb555_video_info;
5731 video_info.bmiHeader.biWidth = 222;
5732 video_info.bmiHeader.biHeight = -555;
5733 mt = rgb555_mt;
5734 mt.pbFormat = (BYTE *)&video_info;
5735 source.preferred_mt = &mt;
5737 format = rgb555_format;
5738 format.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
5739 format.dwWidth = 222;
5740 format.dwHeight = 555;
5741 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &format, NULL);
5742 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5743 ok(IsEqualGUID(&source.source.pin.mt.subtype, &MEDIASUBTYPE_RGB555),
5744 "Got subtype %s.\n", wine_dbgstr_guid(&source.source.pin.mt.subtype));
5745 ok(((VIDEOINFO *)source.source.pin.mt.pbFormat)->bmiHeader.biWidth == 222,
5746 "Got width %ld.\n", ((VIDEOINFO *)source.source.pin.mt.pbFormat)->bmiHeader.biWidth);
5747 ok(((VIDEOINFO *)source.source.pin.mt.pbFormat)->bmiHeader.biHeight == -555,
5748 "Got height %ld.\n", ((VIDEOINFO *)source.source.pin.mt.pbFormat)->bmiHeader.biHeight);
5750 hr = IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
5751 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5752 hr = IGraphBuilder_Disconnect(graph, pin);
5753 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5755 ref = IAMMultiMediaStream_Release(mmstream);
5756 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5757 ref = IGraphBuilder_Release(graph);
5758 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5759 IPin_Release(pin);
5760 IDirectDrawMediaStream_Release(ddraw_stream);
5761 ref = IMediaStream_Release(stream);
5762 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5765 static void test_ddrawstream_receive(void)
5767 ALLOCATOR_PROPERTIES properties =
5769 .cBuffers = 1,
5770 .cbBuffer = 16,
5771 .cbAlign = 1,
5774 IAMMultiMediaStream *mmstream = create_ammultimediastream();
5775 ALLOCATOR_PROPERTIES actual;
5776 IMediaStreamFilter *filter;
5777 struct testfilter source;
5778 IMemAllocator *allocator;
5779 IGraphBuilder *graph;
5780 IMediaStream *stream;
5781 IMediaSample *sample;
5782 HANDLE thread;
5783 HRESULT hr;
5784 ULONG ref;
5785 IPin *pin;
5787 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
5788 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5789 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
5790 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5791 ok(!!filter, "Expected non-null filter.\n");
5792 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
5793 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5794 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
5795 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5796 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
5797 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5798 ok(graph != NULL, "Expected non-NULL graph.\n");
5799 testfilter_init(&source);
5800 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
5801 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5802 hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER, &IID_IMemAllocator, (void **)&allocator);
5803 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5804 hr = IMemAllocator_SetProperties(allocator, &properties, &actual);
5805 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5806 hr = IMemAllocator_Commit(allocator);
5807 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5809 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &rgb32_mt);
5810 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5812 hr = IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0);
5813 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5814 hr = IMemInputPin_Receive(source.source.pMemInputPin, sample);
5815 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5816 ref = IMediaSample_Release(sample);
5817 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5819 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
5820 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5822 hr = IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0);
5823 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5825 ammediastream_mem_input_pin = source.source.pMemInputPin;
5826 ammediastream_media_sample = sample;
5827 ammediastream_sleep_time = 0;
5828 ammediastream_expected_hr = S_OK;
5829 thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
5831 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
5833 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
5834 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5836 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
5837 CloseHandle(thread);
5839 ref = IMediaSample_Release(sample);
5840 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5842 hr = IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0);
5843 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5844 hr = IMemInputPin_Receive(source.source.pMemInputPin, sample);
5845 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5846 ref = IMediaSample_Release(sample);
5847 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5849 IGraphBuilder_Disconnect(graph, pin);
5850 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
5852 hr = IMemAllocator_Decommit(allocator);
5853 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5855 ref = IAMMultiMediaStream_Release(mmstream);
5856 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5857 ref = IGraphBuilder_Release(graph);
5858 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5859 ref = IMediaStreamFilter_Release(filter);
5860 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5861 IPin_Release(pin);
5862 ref = IMediaStream_Release(stream);
5863 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5864 ref = IMemAllocator_Release(allocator);
5865 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5868 static void test_ddrawstream_begin_flush_end_flush(void)
5870 IAMMultiMediaStream *mmstream = create_ammultimediastream();
5871 static const MSPID mspid = {0x88888888, 1};
5872 IDirectDrawStreamSample *stream_sample;
5873 IDirectDrawMediaStream *ddraw_stream;
5874 IMediaStreamFilter *filter;
5875 IMediaSample *media_sample;
5876 IMediaFilter *media_filter;
5877 struct testfilter source2;
5878 struct testfilter source;
5879 IAMMediaStream *stream2;
5880 IMediaStream *stream;
5881 VIDEOINFO video_info;
5882 struct graph graph;
5883 AM_MEDIA_TYPE mt;
5884 HANDLE thread;
5885 HRESULT hr;
5886 IPin *pin2;
5887 ULONG ref;
5888 IPin *pin;
5890 graph_init(&graph);
5891 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, (IGraphBuilder *)&graph.IFilterGraph2_iface);
5892 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5893 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
5894 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5895 hr = CoCreateInstance(&CLSID_AMDirectDrawStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream2);
5896 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5897 hr = IAMMediaStream_Initialize(stream2, NULL, 0, &mspid, STREAMTYPE_READ);
5898 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5899 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)stream2, &mspid, 0, NULL);
5900 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5901 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
5902 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5903 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
5904 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5905 hr = IAMMediaStream_QueryInterface(stream2, &IID_IPin, (void **)&pin2);
5906 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5907 hr = IFilterGraph2_QueryInterface(&graph.IFilterGraph2_iface, &IID_IMediaFilter, (void **)&media_filter);
5908 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5909 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
5910 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5911 testfilter_init(&source);
5912 testfilter_init(&source2);
5913 source.IMediaSeeking_iface.lpVtbl = &testsource_seeking_vtbl;
5914 hr = IFilterGraph2_AddFilter(&graph.IFilterGraph2_iface, &source.filter.IBaseFilter_iface, NULL);
5915 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5916 hr = IFilterGraph2_AddFilter(&graph.IFilterGraph2_iface, &source2.filter.IBaseFilter_iface, NULL);
5917 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5919 hr = IMediaFilter_SetSyncSource(media_filter, NULL);
5920 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5922 video_info = rgb32_video_info;
5923 video_info.bmiHeader.biWidth = 3;
5924 video_info.bmiHeader.biHeight = 1;
5925 mt = rgb32_mt;
5926 mt.pbFormat = (BYTE *)&video_info;
5927 hr = IFilterGraph2_ConnectDirect(&graph.IFilterGraph2_iface, &source.source.pin.IPin_iface, pin, &mt);
5928 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5929 hr = IFilterGraph2_ConnectDirect(&graph.IFilterGraph2_iface, &source2.source.pin.IPin_iface, pin2, &mt);
5930 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5932 hr = IMediaStreamFilter_SupportSeeking(filter, TRUE);
5933 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5935 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &stream_sample);
5936 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5938 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
5939 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5941 hr = IMemAllocator_GetBuffer(source.source.pAllocator, &media_sample, NULL, NULL, 0);
5942 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5944 ammediastream_mem_input_pin = source.source.pMemInputPin;
5945 ammediastream_media_sample = media_sample;
5946 ammediastream_sleep_time = 0;
5947 ammediastream_expected_hr = S_FALSE;
5948 thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
5950 hr = IPin_BeginFlush(pin);
5951 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5953 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
5954 CloseHandle(thread);
5956 ref = IMediaSample_Release(media_sample);
5957 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5959 hr = IMemAllocator_GetBuffer(source.source.pAllocator, &media_sample, NULL, NULL, 0);
5960 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5961 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
5962 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
5964 ref = IMediaSample_Release(media_sample);
5965 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5967 hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
5968 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
5970 hr = IPin_EndOfStream(pin);
5971 ok(hr == E_FAIL, "Got hr %#lx.\n", hr);
5973 hr = IPin_EndFlush(pin);
5974 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5976 hr = IMemAllocator_GetBuffer(source.source.pAllocator, &media_sample, NULL, NULL, 0);
5977 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5978 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
5979 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5980 ref = IMediaSample_Release(media_sample);
5981 ok(!ref, "Got outstanding refcount %ld.\n", ref);
5983 hr = IPin_EndOfStream(pin);
5984 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5986 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
5987 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5988 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
5989 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5991 hr = IPin_BeginFlush(pin);
5992 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5993 hr = IPin_EndFlush(pin);
5994 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5996 hr = IPin_EndOfStream(pin);
5997 ok(hr == S_OK, "Got hr %#lx.\n", hr);
5999 graph.got_notify = 0;
6001 hr = IPin_EndOfStream(pin2);
6002 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6004 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
6005 ok(graph.event_code == EC_COMPLETE, "Got event code %ld.\n", graph.event_code);
6007 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
6008 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6009 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
6010 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6012 hr = IPin_EndOfStream(pin);
6013 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6015 hr = IPin_BeginFlush(pin);
6016 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6017 hr = IPin_EndFlush(pin);
6018 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6020 graph.got_notify = 0;
6021 graph.event_code = 0xcc;
6023 hr = IPin_EndOfStream(pin2);
6024 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6026 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
6028 hr = IPin_EndOfStream(pin);
6029 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6031 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
6032 ok(graph.event_code == EC_COMPLETE, "Got event code %ld.\n", graph.event_code);
6034 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
6035 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6036 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
6037 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6039 hr = IPin_EndOfStream(pin);
6040 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6042 hr = IPin_BeginFlush(pin);
6043 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6044 hr = IPin_EndFlush(pin);
6045 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6046 hr = IPin_BeginFlush(pin);
6047 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6048 hr = IPin_EndFlush(pin);
6049 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6051 hr = IPin_EndOfStream(pin);
6052 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6054 graph.got_notify = 0;
6055 graph.event_code = 0xcc;
6057 hr = IPin_EndOfStream(pin2);
6058 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6060 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
6061 ok(graph.event_code == EC_COMPLETE, "Got event code %ld.\n", graph.event_code);
6063 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
6064 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6066 IFilterGraph2_Disconnect(&graph.IFilterGraph2_iface, pin);
6067 IFilterGraph2_Disconnect(&graph.IFilterGraph2_iface, &source.source.pin.IPin_iface);
6068 IFilterGraph2_Disconnect(&graph.IFilterGraph2_iface, pin2);
6069 IFilterGraph2_Disconnect(&graph.IFilterGraph2_iface, &source2.source.pin.IPin_iface);
6071 ref = IDirectDrawStreamSample_Release(stream_sample);
6072 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6073 ref = IAMMultiMediaStream_Release(mmstream);
6074 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6075 IMediaFilter_Release(media_filter);
6076 graph_destroy(&graph);
6077 ref = IMediaStreamFilter_Release(filter);
6078 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6079 IPin_Release(pin);
6080 IDirectDrawMediaStream_Release(ddraw_stream);
6081 ref = IMediaStream_Release(stream);
6082 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6083 IPin_Release(pin2);
6084 ref = IAMMediaStream_Release(stream2);
6085 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6088 static void test_ddrawstream_new_segment(void)
6090 static const BYTE test_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
6091 IAMMultiMediaStream *mmstream = create_ammultimediastream();
6092 IDirectDrawStreamSample *stream_sample;
6093 IDirectDrawMediaStream *ddraw_stream;
6094 IMemInputPin *mem_input_pin;
6095 IMediaSample *media_sample;
6096 IMediaFilter *media_filter;
6097 struct testfilter source;
6098 STREAM_TIME start_time;
6099 STREAM_TIME end_time;
6100 IGraphBuilder *graph;
6101 IMediaStream *stream;
6102 VIDEOINFO video_info;
6103 AM_MEDIA_TYPE mt;
6104 HRESULT hr;
6105 ULONG ref;
6106 IPin *pin;
6108 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
6109 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6110 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
6111 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6112 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
6113 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6114 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
6115 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6116 hr = IMediaStream_QueryInterface(stream, &IID_IMemInputPin, (void **)&mem_input_pin);
6117 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6118 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
6119 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6120 ok(graph != NULL, "Expected non-NULL graph.\n");
6121 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void **)&media_filter);
6122 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6123 testfilter_init(&source);
6124 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
6125 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6127 hr = IMediaFilter_SetSyncSource(media_filter, NULL);
6128 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6130 video_info = rgb32_video_info;
6131 video_info.bmiHeader.biWidth = 3;
6132 video_info.bmiHeader.biHeight = 1;
6133 mt = rgb32_mt;
6134 mt.pbFormat = (BYTE *)&video_info;
6135 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
6136 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6138 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &stream_sample);
6139 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6141 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
6142 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6144 hr = IPin_NewSegment(pin, 11111111, 22222222, 1.0);
6145 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6147 hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
6148 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
6150 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
6151 start_time = 12345678;
6152 end_time = 23456789;
6153 hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
6154 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6155 hr = IMemInputPin_Receive(mem_input_pin, media_sample);
6156 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6157 IMediaSample_Release(media_sample);
6159 start_time = 0xdeadbeefdeadbeef;
6160 end_time = 0xdeadbeefdeadbeef;
6161 hr = IDirectDrawStreamSample_GetSampleTimes(stream_sample, &start_time, &end_time, NULL);
6162 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6163 ok(start_time == 23456789, "Got start time %s.\n", wine_dbgstr_longlong(start_time));
6164 ok(end_time == 34567900, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
6166 hr = IPin_NewSegment(pin, 11111111, 22222222, 2.0);
6167 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6169 hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
6170 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
6172 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
6173 start_time = 12345678;
6174 end_time = 23456789;
6175 hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
6176 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6177 hr = IMemInputPin_Receive(mem_input_pin, media_sample);
6178 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6179 IMediaSample_Release(media_sample);
6181 start_time = 0xdeadbeefdeadbeef;
6182 end_time = 0xdeadbeefdeadbeef;
6183 hr = IDirectDrawStreamSample_GetSampleTimes(stream_sample, &start_time, &end_time, NULL);
6184 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6185 ok(start_time == 23456789, "Got start time %s.\n", wine_dbgstr_longlong(start_time));
6186 ok(end_time == 34567900, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
6188 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
6189 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6190 IGraphBuilder_Disconnect(graph, pin);
6191 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
6193 ref = IDirectDrawStreamSample_Release(stream_sample);
6194 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6195 ref = IAMMultiMediaStream_Release(mmstream);
6196 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6197 IMediaFilter_Release(media_filter);
6198 ref = IGraphBuilder_Release(graph);
6199 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6200 IPin_Release(pin);
6201 IMemInputPin_Release(mem_input_pin);
6202 IDirectDrawMediaStream_Release(ddraw_stream);
6203 ref = IMediaStream_Release(stream);
6204 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6207 static void test_ddrawstream_get_time_per_frame(void)
6209 IAMMultiMediaStream *mmstream = create_ammultimediastream();
6210 IDirectDrawMediaStream *ddraw_stream;
6211 struct testfilter source;
6212 STREAM_TIME frame_time;
6213 IGraphBuilder *graph;
6214 IMediaStream *stream;
6215 VIDEOINFO video_info;
6216 AM_MEDIA_TYPE mt;
6217 HRESULT hr;
6218 ULONG ref;
6219 IPin *pin;
6221 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
6222 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6223 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
6224 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6225 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
6226 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6227 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
6228 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6229 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
6230 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6231 ok(graph != NULL, "Expected non-NULL graph.\n");
6232 testfilter_init(&source);
6233 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
6234 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6236 hr = IDirectDrawMediaStream_GetTimePerFrame(ddraw_stream, NULL);
6237 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
6239 hr = IDirectDrawMediaStream_GetTimePerFrame(ddraw_stream, &frame_time);
6240 ok(hr == MS_E_NOSTREAM, "Got hr %#lx.\n", hr);
6242 video_info = rgb32_video_info;
6243 video_info.AvgTimePerFrame = 12345678;
6244 mt = rgb32_mt;
6245 mt.pbFormat = (BYTE *)&video_info;
6246 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
6247 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6249 frame_time = 0xdeadbeefdeadbeef;
6250 hr = IDirectDrawMediaStream_GetTimePerFrame(ddraw_stream, &frame_time);
6251 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6252 ok(frame_time == 12345678, "Got frame time %s.\n", wine_dbgstr_longlong(frame_time));
6254 ref = IAMMultiMediaStream_Release(mmstream);
6255 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6256 ref = IGraphBuilder_Release(graph);
6257 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6258 IPin_Release(pin);
6259 IDirectDrawMediaStream_Release(ddraw_stream);
6260 ref = IMediaStream_Release(stream);
6261 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6264 static void check_ammediastream_join_am_multi_media_stream(const CLSID *clsid)
6266 IAMMultiMediaStream *mmstream = create_ammultimediastream();
6267 IMultiMediaStream *mmstream2;
6268 IAMMediaStream *stream;
6269 HRESULT hr;
6270 ULONG mmstream_ref;
6271 ULONG ref;
6273 hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream);
6274 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6276 mmstream_ref = get_refcount(mmstream);
6278 hr = IAMMediaStream_JoinAMMultiMediaStream(stream, mmstream);
6279 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6281 ref = get_refcount(mmstream);
6282 ok(ref == mmstream_ref, "Expected outstanding refcount %ld, got %ld.\n", mmstream_ref, ref);
6284 hr = IAMMediaStream_GetMultiMediaStream(stream, &mmstream2);
6285 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6286 ok(mmstream2 == (IMultiMediaStream *)mmstream, "Expected mmstream %p, got %p.\n", mmstream, mmstream2);
6288 IMultiMediaStream_Release(mmstream2);
6290 hr = IAMMediaStream_JoinAMMultiMediaStream(stream, NULL);
6291 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6293 hr = IAMMediaStream_GetMultiMediaStream(stream, &mmstream2);
6294 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6295 ok(mmstream2 == NULL, "Got mmstream %p.\n", mmstream2);
6297 ref = IAMMediaStream_Release(stream);
6298 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6299 ref = IAMMultiMediaStream_Release(mmstream);
6300 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6303 static void test_ammediastream_join_am_multi_media_stream(void)
6305 check_ammediastream_join_am_multi_media_stream(&CLSID_AMAudioStream);
6306 check_ammediastream_join_am_multi_media_stream(&CLSID_AMDirectDrawStream);
6309 static void check_ammediastream_join_filter(const CLSID *clsid)
6311 IAMMultiMediaStream *mmstream = create_ammultimediastream();
6312 IMediaStreamFilter *filter, *filter2, *filter3;
6313 IAMMediaStream *stream;
6314 HRESULT hr;
6315 ULONG ref;
6317 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
6318 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6319 ok(!!filter, "Expected non-null filter.\n");
6320 EXPECT_REF(filter, 3);
6322 hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream);
6323 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6324 EXPECT_REF(filter, 3);
6326 hr = CoCreateInstance(&CLSID_MediaStreamFilter, NULL, CLSCTX_INPROC_SERVER,
6327 &IID_IMediaStreamFilter, (void **)&filter2);
6328 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6329 EXPECT_REF(filter, 3);
6330 EXPECT_REF(filter2, 1);
6332 hr = IAMMediaStream_JoinFilter(stream, filter2);
6333 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6334 EXPECT_REF(filter, 3);
6335 EXPECT_REF(filter2, 1);
6337 /* Crashes on native. */
6338 if (0)
6340 hr = IAMMediaStream_JoinFilter(stream, NULL);
6341 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6344 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter3);
6345 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6346 ok(filter3 == filter, "Expected filter %p, got %p.\n", filter, filter3);
6347 EXPECT_REF(filter, 4);
6349 IMediaStreamFilter_Release(filter3);
6350 EXPECT_REF(filter, 3);
6352 ref = IMediaStreamFilter_Release(filter2);
6353 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6354 ref = IAMMediaStream_Release(stream);
6355 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6356 EXPECT_REF(filter, 3);
6357 ref = IAMMultiMediaStream_Release(mmstream);
6358 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6359 EXPECT_REF(filter, 1);
6360 ref = IMediaStreamFilter_Release(filter);
6361 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6364 static void test_ammediastream_join_filter(void)
6366 check_ammediastream_join_filter(&CLSID_AMAudioStream);
6367 check_ammediastream_join_filter(&CLSID_AMDirectDrawStream);
6370 static void check_ammediastream_join_filter_graph(const MSPID *id)
6372 IAMMultiMediaStream *mmstream = create_ammultimediastream();
6373 IGraphBuilder *builder, *builder2;
6374 IMediaStreamFilter *filter;
6375 IAMMediaStream *stream;
6376 IFilterGraph *graph;
6377 FILTER_INFO info;
6378 HRESULT hr;
6379 ULONG ref;
6381 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
6382 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6383 ok(!!filter, "Expected non-null filter.\n");
6385 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, id, 0, (IMediaStream **)&stream);
6386 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6388 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &builder);
6389 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6390 ok(!!builder, "Expected non-null graph.\n");
6391 EXPECT_REF(builder, 4);
6393 hr = IMediaStreamFilter_QueryFilterInfo(filter, &info);
6394 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6395 ok(info.pGraph == (IFilterGraph *)builder, "Expected graph %p, got %p.\n", (IFilterGraph *)builder, info.pGraph);
6396 EXPECT_REF(builder, 5);
6397 IFilterGraph_Release(info.pGraph);
6398 EXPECT_REF(builder, 4);
6400 hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterGraph, (void **)&graph);
6401 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6402 EXPECT_REF(builder, 4);
6403 EXPECT_REF(graph, 1);
6405 /* Crashes on native. */
6406 if (0)
6408 hr = IAMMediaStream_JoinFilterGraph(stream, NULL);
6409 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
6412 hr = IAMMediaStream_JoinFilterGraph(stream, graph);
6413 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6414 EXPECT_REF(builder, 4);
6415 EXPECT_REF(graph, 1);
6417 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &builder2);
6418 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6419 ok(builder2 == builder, "Expected graph %p, got %p.\n", builder, builder2);
6420 EXPECT_REF(builder, 5);
6421 EXPECT_REF(graph, 1);
6422 IGraphBuilder_Release(builder2);
6423 EXPECT_REF(builder, 4);
6424 EXPECT_REF(graph, 1);
6426 hr = IMediaStreamFilter_QueryFilterInfo(filter, &info);
6427 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6428 ok(info.pGraph == (IFilterGraph *)builder, "Expected graph %p, got %p.\n", (IFilterGraph *)builder, info.pGraph);
6429 EXPECT_REF(builder, 5);
6430 EXPECT_REF(graph, 1);
6431 IFilterGraph_Release(info.pGraph);
6432 EXPECT_REF(builder, 4);
6433 EXPECT_REF(graph, 1);
6435 ref = IFilterGraph_Release(graph);
6436 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6437 ref = IAMMultiMediaStream_Release(mmstream);
6438 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6439 ref = IGraphBuilder_Release(builder);
6440 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6441 ref = IMediaStreamFilter_Release(filter);
6442 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6443 ref = IAMMediaStream_Release(stream);
6444 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6447 static void test_ammediastream_join_filter_graph(void)
6449 check_ammediastream_join_filter_graph(&MSPID_PrimaryAudio);
6450 check_ammediastream_join_filter_graph(&MSPID_PrimaryVideo);
6453 static void check_ammediastream_set_state(const MSPID *id)
6455 IAMMultiMediaStream *mmstream = create_ammultimediastream();
6456 IAMMediaStream *am_stream;
6457 IMediaStream *stream;
6458 HRESULT hr;
6459 ULONG ref;
6461 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
6462 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6463 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, id, 0, &stream);
6464 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6465 hr = IMediaStream_QueryInterface(stream, &IID_IAMMediaStream, (void **)&am_stream);
6466 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6468 hr = IAMMediaStream_SetState(am_stream, 4);
6469 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6471 hr = IAMMediaStream_SetState(am_stream, State_Running);
6472 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6474 hr = IAMMediaStream_SetState(am_stream, State_Paused);
6475 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6477 hr = IAMMediaStream_SetState(am_stream, State_Stopped);
6478 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6480 ref = IAMMultiMediaStream_Release(mmstream);
6481 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6482 IAMMediaStream_Release(am_stream);
6483 ref = IMediaStream_Release(stream);
6484 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6487 static void test_ammediastream_set_state(void)
6489 check_ammediastream_set_state(&MSPID_PrimaryAudio);
6490 check_ammediastream_set_state(&MSPID_PrimaryVideo);
6493 static void check_ammediastream_end_of_stream(const CLSID *clsid, const MSPID *id, const AM_MEDIA_TYPE *mt)
6495 IAMMultiMediaStream *mmstream = create_ammultimediastream();
6496 IMediaStreamFilter *filter;
6497 struct testfilter source;
6498 IMediaStream *stream;
6499 struct graph graph;
6500 HRESULT hr;
6501 ULONG ref;
6502 IPin *pin;
6504 graph_init(&graph);
6506 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, (IGraphBuilder *)&graph.IFilterGraph2_iface);
6507 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6508 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, id, 0, &stream);
6509 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6510 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
6511 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6512 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
6513 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6514 testfilter_init(&source);
6515 source.IMediaSeeking_iface.lpVtbl = &testsource_seeking_vtbl;
6516 hr = IFilterGraph2_AddFilter(&graph.IFilterGraph2_iface, &source.filter.IBaseFilter_iface, NULL);
6517 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6519 hr = IFilterGraph2_ConnectDirect(&graph.IFilterGraph2_iface, &source.source.pin.IPin_iface, pin, mt);
6520 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6522 hr = IMediaStreamFilter_SupportSeeking(filter, TRUE);
6523 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6525 hr = IPin_EndOfStream(pin);
6526 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6528 hr = IPin_EndOfStream(pin);
6529 ok(hr == E_FAIL, "Got hr %#lx.\n", hr);
6531 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
6532 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6534 hr = IPin_EndOfStream(pin);
6535 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6537 hr = IPin_EndOfStream(pin);
6538 ok(hr == E_FAIL, "Got hr %#lx.\n", hr);
6540 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
6541 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6543 hr = IPin_EndOfStream(pin);
6544 ok(hr == E_FAIL, "Got hr %#lx.\n", hr);
6546 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
6547 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6549 graph.got_notify = 0;
6550 graph.event_code = 0xcc;
6552 hr = IPin_EndOfStream(pin);
6553 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6555 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
6556 ok(graph.event_code == EC_COMPLETE, "Got event code %ld.\n", graph.event_code);
6558 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
6559 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6561 IFilterGraph2_Disconnect(&graph.IFilterGraph2_iface, pin);
6562 IFilterGraph2_Disconnect(&graph.IFilterGraph2_iface, &source.source.pin.IPin_iface);
6564 ref = IAMMultiMediaStream_Release(mmstream);
6565 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6566 graph_destroy(&graph);
6567 ref = IMediaStreamFilter_Release(filter);
6568 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6569 IPin_Release(pin);
6570 ref = IMediaStream_Release(stream);
6571 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6574 static void test_ammediastream_end_of_stream(void)
6576 check_ammediastream_end_of_stream(&CLSID_AMAudioStream, &MSPID_PrimaryAudio, &audio_mt);
6577 check_ammediastream_end_of_stream(&CLSID_AMDirectDrawStream, &MSPID_PrimaryVideo, &rgb32_mt);
6580 void test_mediastreamfilter_get_state(void)
6582 IAMMultiMediaStream *mmstream = create_ammultimediastream();
6583 IMediaStreamFilter *filter;
6584 FILTER_STATE state;
6585 HRESULT hr;
6586 ULONG ref;
6588 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
6589 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6590 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
6591 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6592 ok(!!filter, "Expected non-null filter.\n");
6594 /* Crashes on native. */
6595 if (0)
6597 hr = IMediaStreamFilter_GetState(filter, 0, NULL);
6598 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
6601 state = 0xcc;
6602 hr = IMediaStreamFilter_GetState(filter, 0, &state);
6603 ok(state == State_Stopped, "Got state %#x.\n", state);
6605 ref = IAMMultiMediaStream_Release(mmstream);
6606 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6607 ref = IMediaStreamFilter_Release(filter);
6608 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6611 void check_mediastreamfilter_state(FILTER_STATE expected_state, HRESULT (*set_state)(IMediaStreamFilter *),
6612 HRESULT (*reset_state)(IMediaStreamFilter *))
6614 IAMMultiMediaStream *mmstream = create_ammultimediastream();
6615 struct teststream teststream, teststream2;
6616 IMediaStreamFilter *filter;
6617 FILTER_STATE state;
6618 HRESULT hr;
6619 ULONG ref;
6621 teststream_init(&teststream);
6622 teststream_init(&teststream2);
6624 teststream2.mspid.Data2 = 1;
6626 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
6627 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6628 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)&teststream, &teststream.mspid, 0, NULL);
6629 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6630 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)&teststream2, &teststream2.mspid, 0, NULL);
6631 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6632 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
6633 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6634 ok(filter != NULL, "Expected non-null filter\n");
6636 hr = reset_state(filter);
6637 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6639 teststream.state = 0xcc;
6640 teststream2.state = 0xcc;
6641 hr = set_state(filter);
6642 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6643 ok(teststream.state == expected_state, "Got state %#x.\n", teststream.state);
6644 ok(teststream2.state == expected_state, "Got state %#x.\n", teststream2.state);
6645 hr = IMediaStreamFilter_GetState(filter, 0, &state);
6646 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6647 ok(state == expected_state, "Got state %#x.\n", state);
6649 teststream.state = 0xcc;
6650 teststream2.state = 0xcc;
6651 hr = set_state(filter);
6652 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6653 ok(teststream.state == 0xcc, "Got state %#x.\n", teststream.state);
6654 ok(teststream2.state == 0xcc, "Got state %#x.\n", teststream2.state);
6656 hr = reset_state(filter);
6657 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6659 teststream.set_state_result = E_FAIL;
6660 teststream.state = 0xcc;
6661 teststream2.state = 0xcc;
6662 hr = set_state(filter);
6663 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6664 ok(teststream.state == 0xcc, "Got state %#x.\n", teststream.state);
6665 ok(teststream2.state == expected_state, "Got state %#x.\n", teststream2.state);
6666 hr = IMediaStreamFilter_GetState(filter, 0, &state);
6667 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6668 ok(state == expected_state, "Got state %#x.\n", state);
6670 hr = reset_state(filter);
6671 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6673 teststream.set_state_result = E_FAIL;
6674 teststream2.set_state_result = E_FAIL;
6675 teststream.state = 0xcc;
6676 teststream2.state = 0xcc;
6677 hr = set_state(filter);
6678 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6679 ok(teststream.state == 0xcc, "Got state %#x.\n", teststream.state);
6680 ok(teststream2.state == 0xcc, "Got state %#x.\n", teststream2.state);
6681 hr = IMediaStreamFilter_GetState(filter, 0, &state);
6682 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6683 ok(state == expected_state, "Got state %#x.\n", state);
6685 ref = IAMMultiMediaStream_Release(mmstream);
6686 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6687 ref = IMediaStreamFilter_Release(filter);
6688 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6689 ok(teststream.refcount == 1, "Got outstanding refcount %ld.\n", teststream.refcount);
6690 ok(teststream2.refcount == 1, "Got outstanding refcount %ld.\n", teststream2.refcount);
6693 static HRESULT mediastreamfilter_stop(IMediaStreamFilter *filter)
6695 return IMediaStreamFilter_Stop(filter);
6698 static HRESULT mediastreamfilter_pause(IMediaStreamFilter *filter)
6700 return IMediaStreamFilter_Pause(filter);
6703 static HRESULT mediastreamfilter_run(IMediaStreamFilter *filter)
6705 return IMediaStreamFilter_Run(filter, 0);
6708 void test_mediastreamfilter_stop_pause_run(void)
6710 check_mediastreamfilter_state(State_Stopped, mediastreamfilter_stop, mediastreamfilter_run);
6711 check_mediastreamfilter_state(State_Paused, mediastreamfilter_pause, mediastreamfilter_stop);
6712 check_mediastreamfilter_state(State_Running, mediastreamfilter_run, mediastreamfilter_stop);
6715 static void test_mediastreamfilter_support_seeking(void)
6717 IAMMultiMediaStream *mmstream = create_ammultimediastream();
6718 static const MSPID mspid1 = {0x88888888, 1};
6719 static const MSPID mspid2 = {0x88888888, 2};
6720 static const MSPID mspid3 = {0x88888888, 3};
6721 struct testfilter source1, source2, source3;
6722 IAMMediaStream *stream1, *stream2, *stream3;
6723 IMediaStreamFilter *filter;
6724 IPin *pin1, *pin2, *pin3;
6725 ULONG ref, seeking_ref;
6726 IGraphBuilder *graph;
6727 HRESULT hr;
6729 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
6730 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6731 hr = CoCreateInstance(&CLSID_AMAudioStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream1);
6732 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6733 hr = CoCreateInstance(&CLSID_AMAudioStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream2);
6734 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6735 hr = CoCreateInstance(&CLSID_AMAudioStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream3);
6736 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6737 hr = IAMMediaStream_Initialize(stream1, NULL, 0, &mspid1, STREAMTYPE_READ);
6738 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6739 hr = IAMMediaStream_Initialize(stream2, NULL, 0, &mspid2, STREAMTYPE_READ);
6740 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6741 hr = IAMMediaStream_Initialize(stream3, NULL, 0, &mspid3, STREAMTYPE_READ);
6742 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6743 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)stream1, &mspid1, 0, NULL);
6744 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6745 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)stream2, &mspid2, 0, NULL);
6746 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6747 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)stream3, &mspid3, 0, NULL);
6748 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6749 hr = IAMMediaStream_QueryInterface(stream1, &IID_IPin, (void **)&pin1);
6750 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6751 hr = IAMMediaStream_QueryInterface(stream2, &IID_IPin, (void **)&pin2);
6752 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6753 hr = IAMMediaStream_QueryInterface(stream3, &IID_IPin, (void **)&pin3);
6754 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6755 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
6756 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6757 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
6758 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6759 ok(graph != NULL, "Expected non-NULL graph.\n");
6760 testfilter_init(&source1);
6761 testfilter_init(&source2);
6762 testfilter_init(&source3);
6763 source2.IMediaSeeking_iface.lpVtbl = &testsource_seeking_vtbl;
6764 source3.IMediaSeeking_iface.lpVtbl = &testsource_seeking_vtbl;
6765 hr = IGraphBuilder_AddFilter(graph, &source1.filter.IBaseFilter_iface, NULL);
6766 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6767 hr = IGraphBuilder_AddFilter(graph, &source2.filter.IBaseFilter_iface, NULL);
6768 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6769 hr = IGraphBuilder_AddFilter(graph, &source3.filter.IBaseFilter_iface, NULL);
6770 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6772 hr = IMediaStreamFilter_SupportSeeking(filter, TRUE);
6773 ok(hr == E_NOINTERFACE, "Got hr %#lx.\n", hr);
6775 hr = IGraphBuilder_ConnectDirect(graph, &source1.source.pin.IPin_iface, pin1, &audio_mt);
6776 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6778 source2.get_duration_hr = E_FAIL;
6780 hr = IMediaStreamFilter_SupportSeeking(filter, TRUE);
6781 ok(hr == E_NOINTERFACE, "Got hr %#lx.\n", hr);
6783 hr = IGraphBuilder_ConnectDirect(graph, &source2.source.pin.IPin_iface, pin2, &audio_mt);
6784 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6786 hr = IMediaStreamFilter_SupportSeeking(filter, TRUE);
6787 ok(hr == E_NOINTERFACE, "Got hr %#lx.\n", hr);
6789 hr = IGraphBuilder_ConnectDirect(graph, &source3.source.pin.IPin_iface, pin3, &audio_mt);
6790 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6792 check_interface(filter, &IID_IMediaSeeking, FALSE);
6794 seeking_ref = get_refcount(&source3.IMediaSeeking_iface);
6796 hr = IMediaStreamFilter_SupportSeeking(filter, TRUE);
6797 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6799 check_interface(filter, &IID_IMediaSeeking, TRUE);
6801 ref = get_refcount(&source3.IMediaSeeking_iface);
6802 ok(ref == seeking_ref, "Expected outstanding refcount %ld, got %ld.\n", seeking_ref, ref);
6804 hr = IMediaStreamFilter_SupportSeeking(filter, TRUE);
6805 ok(hr == HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED), "Got hr %#lx.\n", hr);
6807 IGraphBuilder_Disconnect(graph, pin1);
6808 IGraphBuilder_Disconnect(graph, &source1.source.pin.IPin_iface);
6810 IGraphBuilder_Disconnect(graph, pin2);
6811 IGraphBuilder_Disconnect(graph, &source2.source.pin.IPin_iface);
6813 IGraphBuilder_Disconnect(graph, pin3);
6814 IGraphBuilder_Disconnect(graph, &source3.source.pin.IPin_iface);
6816 ref = IAMMultiMediaStream_Release(mmstream);
6817 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6818 ref = IGraphBuilder_Release(graph);
6819 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6820 ref = IMediaStreamFilter_Release(filter);
6821 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6822 IPin_Release(pin1);
6823 ref = IAMMediaStream_Release(stream1);
6824 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6825 IPin_Release(pin2);
6826 ref = IAMMediaStream_Release(stream2);
6827 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6828 IPin_Release(pin3);
6829 ref = IAMMediaStream_Release(stream3);
6830 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6833 static void check_mediastreamfilter_seeking(void (*check)(IMediaSeeking *seeking, struct testfilter *source1,
6834 struct testfilter *source2, struct testfilter *source3, HRESULT source2_hr, HRESULT expected_hr))
6836 IAMMultiMediaStream *mmstream = create_ammultimediastream();
6837 static const MSPID mspid1 = {0x88888888, 1};
6838 static const MSPID mspid2 = {0x88888888, 2};
6839 static const MSPID mspid3 = {0x88888888, 3};
6840 IMediaStreamFilter *filter;
6841 struct testfilter source1;
6842 struct testfilter source2;
6843 struct testfilter source3;
6844 IAMMediaStream *stream1;
6845 IAMMediaStream *stream2;
6846 IAMMediaStream *stream3;
6847 IMediaSeeking *seeking;
6848 IGraphBuilder *graph;
6849 IPin *pin1;
6850 IPin *pin2;
6851 IPin *pin3;
6852 HRESULT hr;
6853 ULONG ref;
6855 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
6856 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6857 hr = CoCreateInstance(&CLSID_AMAudioStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream1);
6858 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6859 hr = CoCreateInstance(&CLSID_AMAudioStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream2);
6860 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6861 hr = CoCreateInstance(&CLSID_AMAudioStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream3);
6862 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6863 hr = IAMMediaStream_Initialize(stream1, NULL, 0, &mspid1, STREAMTYPE_READ);
6864 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6865 hr = IAMMediaStream_Initialize(stream2, NULL, 0, &mspid2, STREAMTYPE_READ);
6866 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6867 hr = IAMMediaStream_Initialize(stream3, NULL, 0, &mspid3, STREAMTYPE_READ);
6868 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6869 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)stream1, &mspid1, 0, NULL);
6870 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6871 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)stream2, &mspid2, 0, NULL);
6872 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6873 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)stream3, &mspid3, 0, NULL);
6874 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6875 hr = IAMMediaStream_QueryInterface(stream1, &IID_IPin, (void **)&pin1);
6876 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6877 hr = IAMMediaStream_QueryInterface(stream2, &IID_IPin, (void **)&pin2);
6878 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6879 hr = IAMMediaStream_QueryInterface(stream3, &IID_IPin, (void **)&pin3);
6880 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6881 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
6882 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6883 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
6884 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6885 ok(graph != NULL, "Expected non-NULL graph.\n");
6886 testfilter_init(&source1);
6887 testfilter_init(&source2);
6888 testfilter_init(&source3);
6889 source1.IMediaSeeking_iface.lpVtbl = &testsource_seeking_vtbl;
6890 source2.IMediaSeeking_iface.lpVtbl = &testsource_seeking_vtbl;
6891 source3.IMediaSeeking_iface.lpVtbl = &testsource_seeking_vtbl;
6892 hr = IGraphBuilder_AddFilter(graph, &source1.filter.IBaseFilter_iface, NULL);
6893 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6894 hr = IGraphBuilder_AddFilter(graph, &source2.filter.IBaseFilter_iface, NULL);
6895 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6896 hr = IGraphBuilder_AddFilter(graph, &source3.filter.IBaseFilter_iface, NULL);
6897 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6899 hr = IGraphBuilder_ConnectDirect(graph, &source2.source.pin.IPin_iface, pin2, &audio_mt);
6900 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6901 hr = IGraphBuilder_ConnectDirect(graph, &source3.source.pin.IPin_iface, pin3, &audio_mt);
6902 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6904 hr = IMediaStreamFilter_SupportSeeking(filter, TRUE);
6905 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6907 hr = IGraphBuilder_ConnectDirect(graph, &source1.source.pin.IPin_iface, pin1, &audio_mt);
6908 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6910 hr = IMediaStreamFilter_QueryInterface(filter, &IID_IMediaSeeking, (void **)&seeking);
6911 ok(hr == S_OK, "Got hr %#lx.\n", hr);
6913 check(seeking, &source1, &source2, &source3, S_OK, S_OK);
6914 check(seeking, &source1, &source2, &source3, E_FAIL, E_FAIL);
6915 check(seeking, &source1, &source2, &source3, E_NOTIMPL, E_NOTIMPL);
6917 source2.IMediaSeeking_iface.lpVtbl = NULL;
6919 check(seeking, &source1, &source2, &source3, S_OK, E_NOTIMPL);
6921 source2.IMediaSeeking_iface.lpVtbl = &testsource_seeking_vtbl;
6923 IGraphBuilder_Disconnect(graph, pin2);
6924 IGraphBuilder_Disconnect(graph, &source2.source.pin.IPin_iface);
6926 check(seeking, &source1, &source2, &source3, S_OK, E_NOTIMPL);
6928 IGraphBuilder_Disconnect(graph, pin2);
6929 IGraphBuilder_Disconnect(graph, &source2.source.pin.IPin_iface);
6930 IGraphBuilder_Disconnect(graph, pin3);
6931 IGraphBuilder_Disconnect(graph, &source3.source.pin.IPin_iface);
6933 ref = IAMMultiMediaStream_Release(mmstream);
6934 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6935 ref = IGraphBuilder_Release(graph);
6936 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6937 IMediaSeeking_Release(seeking);
6938 ref = IMediaStreamFilter_Release(filter);
6939 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6940 IPin_Release(pin1);
6941 ref = IAMMediaStream_Release(stream1);
6942 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6943 IPin_Release(pin2);
6944 ref = IAMMediaStream_Release(stream2);
6945 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6946 IPin_Release(pin3);
6947 ref = IAMMediaStream_Release(stream3);
6948 ok(!ref, "Got outstanding refcount %ld.\n", ref);
6951 static void check_mediastreamfilter_set_positions(IMediaSeeking *seeking, struct testfilter *source1,
6952 struct testfilter *source2, struct testfilter *source3, HRESULT source2_hr, HRESULT expected_hr)
6954 LONGLONG current_position = 12345678;
6955 LONGLONG stop_position = 87654321;
6956 HRESULT hr;
6958 source2->set_positions_hr = source2_hr;
6959 source1->current_position = 0xdeadbeefdeadbeefULL;
6960 source1->stop_position = 0xdeadbeefdeadbeefULL;
6961 source2->current_position = 0xdeadbeefdeadbeefULL;
6962 source2->stop_position = 0xdeadbeefdeadbeefULL;
6963 source3->current_position = 0xdeadbeefdeadbeefULL;
6964 source3->stop_position = 0xdeadbeefdeadbeefULL;
6965 hr = IMediaSeeking_SetPositions(seeking, &current_position, AM_SEEKING_AbsolutePositioning,
6966 &stop_position, AM_SEEKING_AbsolutePositioning);
6967 ok(hr == expected_hr, "Got hr %#lx.\n", hr);
6968 ok(source1->current_position == 0xdeadbeefdeadbeefULL, "Got current position %s.\n",
6969 wine_dbgstr_longlong(source1->current_position));
6970 ok(source1->stop_position == 0xdeadbeefdeadbeefULL, "Got stop position %s.\n",
6971 wine_dbgstr_longlong(source1->stop_position));
6972 if (SUCCEEDED(expected_hr))
6974 ok(source2->current_position == 12345678, "Got current position %s.\n",
6975 wine_dbgstr_longlong(source2->current_position));
6976 ok(source2->stop_position == 87654321, "Got stop position %s.\n",
6977 wine_dbgstr_longlong(source2->stop_position));
6979 ok(source3->current_position == 0xdeadbeefdeadbeefULL, "Got current position %s.\n",
6980 wine_dbgstr_longlong(source3->current_position));
6981 ok(source3->stop_position == 0xdeadbeefdeadbeefULL, "Got stop position %s.\n",
6982 wine_dbgstr_longlong(source3->stop_position));
6985 static void check_mediastreamfilter_get_duration(IMediaSeeking *seeking, struct testfilter *source1,
6986 struct testfilter *source2, struct testfilter *source3, HRESULT source2_hr, HRESULT expected_hr)
6988 LONGLONG duration = 0xdeadbeefdeadbeefULL;
6989 HRESULT hr;
6991 source2->get_duration_hr = source2_hr;
6992 hr = IMediaSeeking_GetDuration(seeking, &duration);
6993 ok(hr == expected_hr, "Got hr %#lx.\n", hr);
6994 if (SUCCEEDED(expected_hr))
6995 ok(duration == 0x8000000000000000ULL, "Got duration %s.\n", wine_dbgstr_longlong(duration));
6996 else
6997 ok(duration == 0xdeadbeefdeadbeefULL, "Got duration %s.\n", wine_dbgstr_longlong(duration));
7000 static void check_mediastreamfilter_get_stop_position(IMediaSeeking *seeking, struct testfilter *source1,
7001 struct testfilter *source2, struct testfilter *source3, HRESULT source2_hr, HRESULT expected_hr)
7003 LONGLONG stop = 0xdeadbeefdeadbeefULL;
7004 HRESULT hr;
7006 source2->get_stop_position_hr = source2_hr;
7007 hr = IMediaSeeking_GetStopPosition(seeking, &stop);
7008 ok(hr == expected_hr, "Got hr %#lx.\n", hr);
7009 if (SUCCEEDED(expected_hr))
7010 ok(stop == 0x8000000000000000ULL, "Got stop position %s.\n", wine_dbgstr_longlong(stop));
7011 else
7012 ok(stop == 0xdeadbeefdeadbeefULL, "Got stop position %s.\n", wine_dbgstr_longlong(stop));
7015 static void check_mediastreamfilter_is_format_supported(IMediaSeeking *seeking, struct testfilter *source1,
7016 struct testfilter *source2, struct testfilter *source3, HRESULT source2_hr, HRESULT expected_hr)
7018 HRESULT hr;
7020 source2->is_format_supported_hr = source2_hr;
7021 hr = IMediaSeeking_IsFormatSupported(seeking, &TIME_FORMAT_MEDIA_TIME);
7022 ok(hr == expected_hr, "Got hr %#lx.\n", hr);
7025 static void test_mediastreamfilter_seeking(void)
7027 check_mediastreamfilter_seeking(check_mediastreamfilter_set_positions);
7028 check_mediastreamfilter_seeking(check_mediastreamfilter_get_duration);
7029 check_mediastreamfilter_seeking(check_mediastreamfilter_get_stop_position);
7030 check_mediastreamfilter_seeking(check_mediastreamfilter_is_format_supported);
7033 static void test_mediastreamfilter_get_current_stream_time(void)
7035 IAMMultiMediaStream *mmstream = create_ammultimediastream();
7036 STREAM_TIME filter_start_time;
7037 IMediaStreamFilter *filter;
7038 IMediaFilter *media_filter;
7039 struct testclock clock;
7040 IGraphBuilder *graph;
7041 STREAM_TIME time;
7042 HRESULT hr;
7043 ULONG ref;
7045 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
7046 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7047 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
7048 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7049 ok(!!filter, "Expected non-null filter.\n");
7050 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, NULL);
7051 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7052 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
7053 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7054 ok(graph != NULL, "Expected non-NULL graph.\n");
7055 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void **)&media_filter);
7056 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7057 testclock_init(&clock);
7059 /* Crashes on native. */
7060 if (0)
7062 hr = IMediaStreamFilter_GetCurrentStreamTime(filter, NULL);
7063 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
7064 hr = IAMMultiMediaStream_GetTime(mmstream, NULL);
7065 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
7068 time = 0xdeadbeefdeadbeef;
7069 hr = IMediaStreamFilter_GetCurrentStreamTime(filter, &time);
7070 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
7071 ok(time == 0, "Got time %s.\n", wine_dbgstr_longlong(time));
7072 time = 0xdeadbeefdeadbeef;
7073 hr = IAMMultiMediaStream_GetTime(mmstream, &time);
7074 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
7075 ok(time == 0, "Got time %s.\n", wine_dbgstr_longlong(time));
7077 hr = IMediaFilter_SetSyncSource(media_filter, &clock.IReferenceClock_iface);
7078 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7080 clock.get_time_hr = E_FAIL;
7082 time = 0xdeadbeefdeadbeef;
7083 hr = IMediaStreamFilter_GetCurrentStreamTime(filter, &time);
7084 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
7085 ok(time == 0, "Got time %s.\n", wine_dbgstr_longlong(time));
7086 time = 0xdeadbeefdeadbeef;
7087 hr = IAMMultiMediaStream_GetTime(mmstream, &time);
7088 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
7089 ok(time == 0, "Got time %s.\n", wine_dbgstr_longlong(time));
7091 clock.time = 23456789;
7092 clock.get_time_hr = S_OK;
7094 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
7095 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7097 hr = IMediaStreamFilter_GetCurrentStreamTime(filter, &filter_start_time);
7098 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7100 clock.time = 34567890;
7102 time = 0xdeadbeefdeadbeef;
7103 hr = IMediaStreamFilter_GetCurrentStreamTime(filter, &time);
7104 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7105 ok(time == 11111101 + filter_start_time, "Got time %s.\n", wine_dbgstr_longlong(time));
7106 time = 0xdeadbeefdeadbeef;
7107 hr = IAMMultiMediaStream_GetTime(mmstream, &time);
7108 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7109 ok(time == 11111101 + filter_start_time, "Got time %s.\n", wine_dbgstr_longlong(time));
7111 ref = IAMMultiMediaStream_Release(mmstream);
7112 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7113 IMediaFilter_Release(media_filter);
7114 ref = IGraphBuilder_Release(graph);
7115 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7116 ref = IMediaStreamFilter_Release(filter);
7117 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7120 static void test_mediastreamfilter_reference_time_to_stream_time(void)
7122 IMediaStreamFilter *filter;
7123 struct testclock clock;
7124 REFERENCE_TIME time;
7125 HRESULT hr;
7126 ULONG ref;
7128 hr = CoCreateInstance(&CLSID_MediaStreamFilter, NULL, CLSCTX_INPROC_SERVER,
7129 &IID_IMediaStreamFilter, (void **)&filter);
7130 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7131 testclock_init(&clock);
7133 hr = IMediaStreamFilter_ReferenceTimeToStreamTime(filter, NULL);
7134 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
7136 time = 0xdeadbeefdeadbeef;
7137 hr = IMediaStreamFilter_ReferenceTimeToStreamTime(filter, &time);
7138 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
7139 ok(time == 0xdeadbeefdeadbeef, "Got time %s.\n", wine_dbgstr_longlong(time));
7141 hr = IMediaStreamFilter_SetSyncSource(filter, &clock.IReferenceClock_iface);
7142 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7144 clock.get_time_hr = E_FAIL;
7146 /* Crashes on native. */
7147 if (0)
7149 hr = IMediaStreamFilter_ReferenceTimeToStreamTime(filter, NULL);
7150 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
7153 time = 0xdeadbeefdeadbeef;
7154 hr = IMediaStreamFilter_ReferenceTimeToStreamTime(filter, &time);
7155 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7156 ok(time == 0xdeadbeefdeadbeef, "Got time %s.\n", wine_dbgstr_longlong(time));
7158 hr = IMediaStreamFilter_Run(filter, 23456789);
7159 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7161 time = 0xdeadbeefdeadbeef;
7162 hr = IMediaStreamFilter_ReferenceTimeToStreamTime(filter, &time);
7163 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7164 ok(time == 0xdeadbeefdd47d2da, "Got time %s.\n", wine_dbgstr_longlong(time));
7166 clock.time = 34567890;
7167 clock.get_time_hr = S_OK;
7169 time = 0xdeadbeefdeadbeef;
7170 hr = IMediaStreamFilter_ReferenceTimeToStreamTime(filter, &time);
7171 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7172 ok(time == 0xdeadbeefdd47d2da, "Got time %s.\n", wine_dbgstr_longlong(time));
7174 ref = IMediaStreamFilter_Release(filter);
7175 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7178 struct mediastreamfilter_wait_until_params
7180 IMediaStreamFilter *filter;
7181 REFERENCE_TIME time;
7182 HRESULT expected_hr;
7185 static DWORD CALLBACK mediastreamfilter_wait_until(void *p)
7187 struct mediastreamfilter_wait_until_params *params = (struct mediastreamfilter_wait_until_params *)p;
7188 HRESULT hr;
7190 hr = IMediaStreamFilter_WaitUntil(params->filter, params->time);
7191 ok(hr == params->expected_hr, "Got hr %#lx.\n", hr);
7193 return 0;
7196 static void test_mediastreamfilter_wait_until(void)
7198 struct mediastreamfilter_wait_until_params params1;
7199 struct mediastreamfilter_wait_until_params params2;
7200 struct advise_time_cookie cookie1 = { 0 };
7201 struct advise_time_cookie cookie2 = { 0 };
7202 IMediaStreamFilter *filter;
7203 struct testclock clock;
7204 HANDLE thread1;
7205 HANDLE thread2;
7206 HRESULT hr;
7207 ULONG ref;
7209 hr = CoCreateInstance(&CLSID_MediaStreamFilter, NULL, CLSCTX_INPROC_SERVER,
7210 &IID_IMediaStreamFilter, (void **)&filter);
7211 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7212 testclock_init(&clock);
7213 cookie1.advise_time_called_event = CreateEventW(NULL, FALSE, FALSE, NULL);
7214 cookie2.advise_time_called_event = CreateEventW(NULL, FALSE, FALSE, NULL);
7216 hr = IMediaStreamFilter_Run(filter, 12345678);
7217 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7219 hr = IMediaStreamFilter_WaitUntil(filter, 23456789);
7220 ok(hr == E_FAIL, "Got hr %#lx.\n", hr);
7222 hr = IMediaStreamFilter_Stop(filter);
7223 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7225 hr = IMediaStreamFilter_SetSyncSource(filter, &clock.IReferenceClock_iface);
7226 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7228 clock.advise_time_cookie = &cookie1;
7230 params1.filter = filter;
7231 params1.time = 23456789;
7232 params1.expected_hr = S_OK;
7233 thread1 = CreateThread(NULL, 0, mediastreamfilter_wait_until, &params1, 0, NULL);
7234 ok(!WaitForSingleObject(cookie1.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
7235 ok(WaitForSingleObject(thread1, 100) == WAIT_TIMEOUT, "WaitUntil returned prematurely.\n");
7237 ok(cookie1.base == 23456789, "Got base %s.\n", wine_dbgstr_longlong(cookie1.base));
7238 ok(cookie1.offset == 12345678, "Got offset %s.\n", wine_dbgstr_longlong(cookie1.offset));
7239 ok(!!cookie1.event, "Expected non-NULL event.\n");
7241 SetEvent(cookie1.event);
7243 ok(!WaitForSingleObject(thread1, 2000), "Wait timed out.\n");
7244 CloseHandle(thread1);
7246 ok(!cookie1.unadvise_called, "Unexpected Unadvise call.\n");
7248 hr = IMediaStreamFilter_Run(filter, 12345678);
7249 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7251 clock.time = 30000000;
7253 clock.advise_time_cookie = &cookie1;
7255 params1.filter = filter;
7256 params1.time = 23456789;
7257 params1.expected_hr = S_OK;
7258 thread1 = CreateThread(NULL, 0, mediastreamfilter_wait_until, &params1, 0, NULL);
7259 ok(!WaitForSingleObject(cookie1.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
7260 ok(WaitForSingleObject(thread1, 100) == WAIT_TIMEOUT, "WaitUntil returned prematurely.\n");
7262 ok(cookie1.base == 23456789, "Got base %s.\n", wine_dbgstr_longlong(cookie1.base));
7263 ok(cookie1.offset == 12345678, "Got offset %s.\n", wine_dbgstr_longlong(cookie1.offset));
7264 ok(!!cookie1.event, "Expected non-NULL event.\n");
7266 clock.advise_time_cookie = &cookie2;
7268 params2.filter = filter;
7269 params2.time = 11111111;
7270 params2.expected_hr = S_OK;
7271 thread2 = CreateThread(NULL, 0, mediastreamfilter_wait_until, &params2, 0, NULL);
7272 ok(!WaitForSingleObject(cookie2.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
7273 ok(WaitForSingleObject(thread2, 100) == WAIT_TIMEOUT, "WaitUntil returned prematurely.\n");
7275 ok(cookie2.base == 11111111, "Got base %s.\n", wine_dbgstr_longlong(cookie2.base));
7276 ok(cookie2.offset == 12345678, "Got offset %s.\n", wine_dbgstr_longlong(cookie2.offset));
7277 ok(!!cookie2.event, "Expected non-NULL event.\n");
7279 SetEvent(cookie1.event);
7281 ok(!WaitForSingleObject(thread1, 2000), "Wait timed out.\n");
7282 CloseHandle(thread1);
7284 ok(WaitForSingleObject(thread2, 100) == WAIT_TIMEOUT, "WaitUntil returned prematurely.\n");
7286 SetEvent(cookie2.event);
7288 ok(!WaitForSingleObject(thread2, 2000), "Wait timed out.\n");
7289 CloseHandle(thread2);
7291 clock.advise_time_cookie = &cookie1;
7293 params1.filter = filter;
7294 params1.time = 23456789;
7295 params1.expected_hr = S_FALSE;
7296 thread1 = CreateThread(NULL, 0, mediastreamfilter_wait_until, &params1, 0, NULL);
7297 ok(!WaitForSingleObject(cookie1.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
7298 ok(WaitForSingleObject(thread1, 100) == WAIT_TIMEOUT, "WaitUntil returned prematurely.\n");
7300 clock.advise_time_cookie = &cookie2;
7302 params2.filter = filter;
7303 params2.time = 23456789;
7304 params2.expected_hr = S_FALSE;
7305 thread2 = CreateThread(NULL, 0, mediastreamfilter_wait_until, &params2, 0, NULL);
7306 ok(!WaitForSingleObject(cookie2.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
7307 ok(WaitForSingleObject(thread2, 100) == WAIT_TIMEOUT, "WaitUntil returned prematurely.\n");
7309 hr = IMediaStreamFilter_Flush(filter, FALSE);
7310 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7312 ok(cookie1.unadvise_called, "Expected Unadvise to be called.\n");
7313 ok(cookie2.unadvise_called, "Expected Unadvise to be called.\n");
7315 ok(!WaitForSingleObject(thread1, 2000), "Wait timed out.\n");
7316 CloseHandle(thread1);
7317 ok(!WaitForSingleObject(thread2, 2000), "Wait timed out.\n");
7318 CloseHandle(thread2);
7320 clock.advise_time_cookie = &cookie1;
7322 params1.filter = filter;
7323 params1.time = 23456789;
7324 params1.expected_hr = S_FALSE;
7325 thread1 = CreateThread(NULL, 0, mediastreamfilter_wait_until, &params1, 0, NULL);
7326 ok(!WaitForSingleObject(cookie1.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
7327 ok(WaitForSingleObject(thread1, 100) == WAIT_TIMEOUT, "WaitUntil returned prematurely.\n");
7329 clock.advise_time_cookie = &cookie2;
7331 params2.filter = filter;
7332 params2.time = 23456789;
7333 params2.expected_hr = S_FALSE;
7334 thread2 = CreateThread(NULL, 0, mediastreamfilter_wait_until, &params2, 0, NULL);
7335 ok(!WaitForSingleObject(cookie2.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
7336 ok(WaitForSingleObject(thread2, 100) == WAIT_TIMEOUT, "WaitUntil returned prematurely.\n");
7338 hr = IMediaStreamFilter_Stop(filter);
7339 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7341 ok(cookie1.unadvise_called, "Expected Unadvise to be called.\n");
7342 ok(cookie2.unadvise_called, "Expected Unadvise to be called.\n");
7344 ok(!WaitForSingleObject(thread1, 2000), "Wait timed out.\n");
7345 CloseHandle(thread1);
7346 ok(!WaitForSingleObject(thread2, 2000), "Wait timed out.\n");
7347 CloseHandle(thread2);
7349 CloseHandle(cookie1.advise_time_called_event);
7350 CloseHandle(cookie2.advise_time_called_event);
7352 ref = IMediaStreamFilter_Release(filter);
7353 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7356 static void test_mediastreamfilter_end_of_stream(void)
7358 IAMMultiMediaStream *mmstream = create_ammultimediastream();
7359 struct testfilter source1, source2;
7360 IMediaStream *stream1, *stream2;
7361 IMediaControl *media_control;
7362 IMediaStreamFilter *filter;
7363 struct graph graph;
7364 IPin *pin1, *pin2;
7365 HRESULT hr;
7366 ULONG ref;
7368 graph_init(&graph);
7369 hr = IFilterGraph2_QueryInterface(&graph.IFilterGraph2_iface, &IID_IMediaControl, (void **)&media_control);
7370 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7372 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, (IGraphBuilder *)&graph.IFilterGraph2_iface);
7373 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7374 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream1);
7375 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7376 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream2);
7377 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7378 hr = IMediaStream_QueryInterface(stream1, &IID_IPin, (void **)&pin1);
7379 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7380 hr = IMediaStream_QueryInterface(stream2, &IID_IPin, (void **)&pin2);
7381 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7382 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
7383 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7384 ok(filter != NULL, "Expected non-null filter\n");
7385 testfilter_init(&source1);
7386 testfilter_init(&source2);
7387 hr = IFilterGraph2_AddFilter(&graph.IFilterGraph2_iface, &source1.filter.IBaseFilter_iface, NULL);
7388 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7389 hr = IFilterGraph2_AddFilter(&graph.IFilterGraph2_iface, &source2.filter.IBaseFilter_iface, NULL);
7390 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7392 hr = IPin_Connect(&source1.source.pin.IPin_iface, pin1, &audio_mt);
7393 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7394 hr = IPin_Connect(&source2.source.pin.IPin_iface, pin2, &rgb32_mt);
7395 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7397 /* Initially, EC_COMPLETE notifications are disabled. */
7398 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
7399 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7401 graph.got_notify = 0;
7403 hr = IMediaStreamFilter_EndOfStream(filter);
7404 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7405 hr = IMediaStreamFilter_EndOfStream(filter);
7406 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7408 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7410 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
7411 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7413 /* Unsuccsessful call to SupportSeeking does not enable EC_COMPLETE notifications. */
7414 hr = IMediaStreamFilter_SupportSeeking(filter, TRUE);
7415 ok(hr == E_NOINTERFACE, "Got hr %#lx.\n", hr);
7417 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
7418 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7420 graph.got_notify = 0;
7422 hr = IMediaStreamFilter_EndOfStream(filter);
7423 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7424 hr = IMediaStreamFilter_EndOfStream(filter);
7425 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7427 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7429 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
7430 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7432 /* Successful call to SupportSeeking enables EC_COMPLETE notifications. */
7433 source1.IMediaSeeking_iface.lpVtbl = &testsource_seeking_vtbl;
7435 hr = IMediaStreamFilter_SupportSeeking(filter, TRUE);
7436 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7438 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
7439 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7441 graph.got_notify = 0;
7443 hr = IMediaStreamFilter_EndOfStream(filter);
7444 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7446 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7448 hr = IMediaStreamFilter_EndOfStream(filter);
7449 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7451 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7453 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
7454 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7456 /* EC_COMPLETE is sent on paused->running state transition
7457 * if EndOfStream has been called for all streams. */
7458 graph.got_notify = 0;
7460 hr = IMediaStreamFilter_EndOfStream(filter);
7461 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7462 hr = IMediaStreamFilter_EndOfStream(filter);
7463 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7465 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7467 hr = IMediaControl_Pause(media_control);
7468 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7470 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7472 hr = IMediaControl_Run(media_control);
7473 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7475 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7477 hr = IMediaControl_Run(media_control);
7478 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7480 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7482 hr = IMediaControl_Stop(media_control);
7483 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7485 /* EC_COMPLETE is sent on paused->running state transition
7486 * if EndOfStream has been called for all streams. */
7487 graph.got_notify = 0;
7489 hr = IMediaStreamFilter_EndOfStream(filter);
7490 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7491 hr = IMediaStreamFilter_EndOfStream(filter);
7492 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7494 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7496 hr = IMediaControl_Pause(media_control);
7497 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7499 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7501 hr = IMediaControl_Run(media_control);
7502 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7504 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7506 hr = IMediaControl_Stop(media_control);
7507 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7509 /* EndOfStream count is reset on paused->stopped state transition. */
7510 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
7511 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7513 graph.got_notify = 0;
7515 hr = IMediaStreamFilter_EndOfStream(filter);
7516 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7518 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
7519 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7520 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
7521 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7523 hr = IMediaStreamFilter_EndOfStream(filter);
7524 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7526 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7528 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
7529 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7531 /* EOS count is not reset on running->paused state transition. */
7532 hr = IMediaControl_Run(media_control);
7533 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7535 graph.got_notify = 0;
7537 hr = IMediaStreamFilter_EndOfStream(filter);
7538 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7540 hr = IMediaControl_Pause(media_control);
7541 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7542 hr = IMediaControl_Run(media_control);
7543 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7545 hr = IMediaStreamFilter_EndOfStream(filter);
7546 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7548 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7550 hr = IMediaControl_Stop(media_control);
7551 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7553 /* EndOfStream count is not reset when Stop() is called on an already stopped filter. */
7554 hr = IMediaStreamFilter_EndOfStream(filter);
7555 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7557 hr = IMediaStreamFilter_Stop(filter);
7558 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7560 hr = IMediaStreamFilter_EndOfStream(filter);
7561 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7563 graph.got_notify = 0;
7565 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
7566 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7568 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7570 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
7571 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7573 /* Flush with cancel_eos=TRUE decrements EOS count. */
7574 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
7575 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7577 graph.got_notify = 0;
7579 hr = IMediaStreamFilter_EndOfStream(filter);
7580 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7582 hr = IMediaStreamFilter_Flush(filter, TRUE);
7584 hr = IMediaStreamFilter_EndOfStream(filter);
7585 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7587 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7589 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
7590 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7592 /* Flush followed by EndOfStream causes another EC_COMPLETE to be sent. */
7593 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
7594 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7596 graph.got_notify = 0;
7598 hr = IMediaStreamFilter_EndOfStream(filter);
7599 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7600 hr = IMediaStreamFilter_EndOfStream(filter);
7601 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7603 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7605 hr = IMediaStreamFilter_Flush(filter, TRUE);
7606 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7608 hr = IMediaStreamFilter_EndOfStream(filter);
7609 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7611 ok(graph.got_notify == 2, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7613 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
7614 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7616 /* Flush decrements EOS count event when it is 0. */
7617 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
7618 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7620 graph.got_notify = 0;
7622 hr = IMediaStreamFilter_Flush(filter, TRUE);
7623 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7625 hr = IMediaStreamFilter_EndOfStream(filter);
7626 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7627 hr = IMediaStreamFilter_EndOfStream(filter);
7628 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7630 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7632 hr = IMediaStreamFilter_EndOfStream(filter);
7633 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7635 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7637 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
7638 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7640 /* Flush with cancel_eos=FALSE does not decrement EOS count. */
7641 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
7642 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7644 graph.got_notify = 0;
7646 hr = IMediaStreamFilter_EndOfStream(filter);
7647 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7649 hr = IMediaStreamFilter_Flush(filter, FALSE);
7651 hr = IMediaStreamFilter_EndOfStream(filter);
7652 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7654 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7656 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
7657 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7659 ref = IAMMultiMediaStream_Release(mmstream);
7660 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7661 IMediaControl_Release(media_control);
7662 graph_destroy(&graph);
7663 ref = IMediaStreamFilter_Release(filter);
7664 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7665 IPin_Release(pin1);
7666 ref = IMediaStream_Release(stream1);
7667 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7668 IPin_Release(pin2);
7669 ref = IMediaStream_Release(stream2);
7670 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7673 static void test_ddrawstream_getsetdirectdraw(void)
7675 IAMMultiMediaStream *mmstream = create_ammultimediastream();
7676 IDirectDraw *ddraw, *ddraw2, *ddraw3, *ddraw4;
7677 IDirectDrawMediaStream *ddraw_stream;
7678 IDirectDrawStreamSample *sample;
7679 IDirectDraw7 *ddraw7;
7680 IMediaStream *stream;
7681 HRESULT hr;
7682 ULONG ref;
7684 hr = DirectDrawCreate(NULL, &ddraw, NULL);
7685 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7686 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw7, (void **)&ddraw7);
7687 ok(hr == DD_OK, "Got hr %#lx.\n", hr);
7688 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, GetDesktopWindow(), DDSCL_NORMAL);
7689 ok(hr == DD_OK, "Got hr %#lx.\n", hr);
7690 EXPECT_REF(ddraw, 1);
7691 EXPECT_REF(ddraw7, 1);
7693 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
7694 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7696 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)ddraw7, &MSPID_PrimaryVideo, 0, &stream);
7697 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7698 EXPECT_REF(ddraw, 2);
7700 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
7701 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7703 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, NULL);
7704 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
7706 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw2);
7707 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7708 ok(ddraw2 == ddraw, "Expected ddraw %p, got %p.\n", ddraw, ddraw2);
7709 EXPECT_REF(ddraw, 3);
7711 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw3);
7712 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7713 ok(ddraw3 == ddraw2, "Expected ddraw %p, got %p.\n", ddraw2, ddraw3);
7714 EXPECT_REF(ddraw, 4);
7715 IDirectDraw_Release(ddraw3);
7716 EXPECT_REF(ddraw, 3);
7718 /* The current ddraw is released when SetDirectDraw() is called. */
7719 hr = IDirectDrawMediaStream_SetDirectDraw(ddraw_stream, NULL);
7720 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7721 EXPECT_REF(ddraw, 2);
7723 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw3);
7724 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7725 ok(ddraw3 == NULL, "Expected NULL, got %p.\n", ddraw3);
7727 hr = IDirectDrawMediaStream_SetDirectDraw(ddraw_stream, ddraw2);
7728 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7729 EXPECT_REF(ddraw, 3);
7731 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw3);
7732 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7733 ok(ddraw3 == ddraw2, "Expected ddraw %p, got %p.\n", ddraw2, ddraw3);
7734 EXPECT_REF(ddraw, 4);
7735 IDirectDraw_Release(ddraw3);
7736 EXPECT_REF(ddraw, 3);
7738 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &sample);
7739 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7741 /* SetDirectDraw() doesn't take an extra reference to the ddraw object
7742 * if there are samples extant. */
7743 hr = IDirectDrawMediaStream_SetDirectDraw(ddraw_stream, ddraw2);
7744 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7745 EXPECT_REF(ddraw, 3);
7747 hr = DirectDrawCreate(NULL, &ddraw3, NULL);
7748 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7749 hr = IDirectDraw_SetCooperativeLevel(ddraw3, GetDesktopWindow(), DDSCL_NORMAL);
7750 ok(hr == DD_OK, "Got hr %#lx.\n", hr);
7751 EXPECT_REF(ddraw3, 1);
7753 hr = IDirectDrawMediaStream_SetDirectDraw(ddraw_stream, ddraw3);
7754 ok(hr == MS_E_SAMPLEALLOC, "Got hr %#lx.\n", hr);
7756 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw4);
7757 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7758 ok(ddraw4 == ddraw2, "Expected ddraw %p, got %p.\n", ddraw2, ddraw4);
7759 EXPECT_REF(ddraw, 4);
7760 IDirectDraw_Release(ddraw4);
7761 EXPECT_REF(ddraw, 3);
7763 ref = IDirectDrawStreamSample_Release(sample);
7764 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7766 hr = IDirectDrawMediaStream_SetDirectDraw(ddraw_stream, ddraw3);
7767 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7768 EXPECT_REF(ddraw, 2);
7769 EXPECT_REF(ddraw3, 2);
7771 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw4);
7772 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7773 ok(ddraw4 == ddraw3, "Expected ddraw %p, got %p.\n", ddraw3, ddraw4);
7774 EXPECT_REF(ddraw3, 3);
7775 IDirectDraw_Release(ddraw4);
7776 EXPECT_REF(ddraw3, 2);
7778 hr = IDirectDrawMediaStream_SetDirectDraw(ddraw_stream, NULL);
7779 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7780 EXPECT_REF(ddraw3, 1);
7782 ref = IDirectDraw_Release(ddraw3);
7783 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7785 EXPECT_REF(stream, 3);
7786 IDirectDrawMediaStream_Release(ddraw_stream);
7787 EXPECT_REF(stream, 2);
7788 ref = IAMMultiMediaStream_Release(mmstream);
7789 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7790 EXPECT_REF(stream, 1);
7791 ref = IMediaStream_Release(stream);
7792 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7793 ref = IDirectDraw7_Release(ddraw7);
7794 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7795 IDirectDraw_Release(ddraw2);
7796 EXPECT_REF(ddraw, 1);
7797 ref = IDirectDraw_Release(ddraw);
7798 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7801 static void test_audiostreamsample_get_media_stream(void)
7803 IAMMultiMediaStream *mmstream = create_ammultimediastream();
7804 IAudioStreamSample *audio_sample;
7805 IAudioMediaStream *audio_stream;
7806 IMediaStream *stream, *stream2;
7807 IAudioData *audio_data;
7808 HRESULT hr;
7809 ULONG ref;
7811 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
7812 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7814 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
7815 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7817 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
7818 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7820 hr = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER, &IID_IAudioData, (void **)&audio_data);
7821 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7823 hr = IAudioMediaStream_CreateSample(audio_stream, audio_data, 0, &audio_sample);
7824 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7826 /* Crashes on native. */
7827 if (0)
7829 hr = IAudioStreamSample_GetMediaStream(audio_sample, NULL);
7830 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
7833 EXPECT_REF(stream, 4);
7834 hr = IAudioStreamSample_GetMediaStream(audio_sample, &stream2);
7835 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7836 ok(stream2 == stream, "Expected stream %p, got %p.\n", stream, stream2);
7837 EXPECT_REF(stream, 5);
7839 IMediaStream_Release(stream2);
7841 IAudioMediaStream_Release(audio_stream);
7842 ref = IAudioStreamSample_Release(audio_sample);
7843 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7844 ref = IAudioData_Release(audio_data);
7845 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7846 ref = IAMMultiMediaStream_Release(mmstream);
7847 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7848 ref = IMediaStream_Release(stream);
7849 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7852 static void test_audiostreamsample_get_audio_data(void)
7854 IAMMultiMediaStream *mmstream = create_ammultimediastream();
7855 IAudioData *audio_data, *audio_data2;
7856 IAudioStreamSample *audio_sample;
7857 IAudioMediaStream *audio_stream;
7858 IMediaStream *stream;
7859 HRESULT hr;
7860 ULONG ref;
7862 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
7863 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7865 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
7866 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7868 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
7869 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7871 hr = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER, &IID_IAudioData, (void **)&audio_data);
7872 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7874 hr = IAudioMediaStream_CreateSample(audio_stream, audio_data, 0, &audio_sample);
7875 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7877 hr = IAudioStreamSample_GetAudioData(audio_sample, NULL);
7878 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
7880 EXPECT_REF(audio_data, 2);
7881 hr = IAudioStreamSample_GetAudioData(audio_sample, &audio_data2);
7882 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7883 ok(audio_data2 == audio_data, "Expected audio data %p, got %p.\n", audio_data, audio_data2);
7884 EXPECT_REF(audio_data, 3);
7886 IAudioData_Release(audio_data2);
7888 IAudioMediaStream_Release(audio_stream);
7889 ref = IAudioStreamSample_Release(audio_sample);
7890 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7891 ref = IAudioData_Release(audio_data);
7892 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7893 ref = IAMMultiMediaStream_Release(mmstream);
7894 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7895 ref = IMediaStream_Release(stream);
7896 ok(!ref, "Got outstanding refcount %ld.\n", ref);
7899 #define get_ddrawstream_create_sample_desc(a,b,c,d) get_ddrawstream_create_sample_desc_(__LINE__,a,b,c,d)
7900 static void get_ddrawstream_create_sample_desc_(int line, const DDSURFACEDESC *format1,
7901 const DDSURFACEDESC *format2, const AM_MEDIA_TYPE *mt, DDSURFACEDESC *desc)
7903 IAMMultiMediaStream *mmstream = create_ammultimediastream();
7904 IDirectDrawMediaStream *ddraw_stream;
7905 IDirectDrawStreamSample *sample;
7906 IDirectDrawSurface *surface;
7907 struct testfilter source;
7908 IGraphBuilder *graph;
7909 IMediaStream *stream;
7910 HRESULT hr;
7911 ULONG ref;
7912 IPin *pin;
7914 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
7915 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
7916 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
7917 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
7918 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
7919 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
7920 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
7921 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
7922 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
7923 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
7925 testfilter_init(&source);
7927 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
7928 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
7930 if (format1)
7932 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, format1, NULL);
7933 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
7935 if (format2)
7937 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, format2, NULL);
7938 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
7940 if (mt)
7942 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, mt);
7943 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
7945 hr = IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
7946 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
7947 hr = IGraphBuilder_Disconnect(graph, pin);
7948 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
7951 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &sample);
7952 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
7954 hr = IDirectDrawStreamSample_GetSurface(sample, &surface, NULL);
7955 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
7956 ok_(__FILE__, line)(!!surface, "Expected non-NULL sufrace.\n");
7958 desc->dwSize = sizeof(*desc);
7959 hr = IDirectDrawSurface_GetSurfaceDesc(surface, desc);
7960 ok_(__FILE__, line)(hr == S_OK, "Got hr %#lx.\n", hr);
7962 ref = IDirectDrawStreamSample_Release(sample);
7963 ok_(__FILE__, line)(!ref, "Got outstanding refcount %ld.\n", ref);
7964 ref = IDirectDrawSurface_Release(surface);
7965 ok_(__FILE__, line)(!ref, "Got outstanding refcount %ld.\n", ref);
7966 ref = IAMMultiMediaStream_Release(mmstream);
7967 ok_(__FILE__, line)(!ref, "Got outstanding refcount %ld.\n", ref);
7968 ref = IGraphBuilder_Release(graph);
7969 ok_(__FILE__, line)(!ref, "Got outstanding refcount %ld.\n", ref);
7970 IPin_Release(pin);
7971 IDirectDrawMediaStream_Release(ddraw_stream);
7972 ref = IMediaStream_Release(stream);
7973 ok_(__FILE__, line)(!ref, "Got outstanding refcount %ld.\n", ref);
7976 static void test_ddrawstream_create_sample(void)
7978 IAMMultiMediaStream *mmstream = create_ammultimediastream();
7979 DDSURFACEDESC desc2 = { sizeof(desc2) };
7980 IDirectDrawSurface *surface, *surface2;
7981 DDSURFACEDESC desc = { sizeof(desc) };
7982 IDirectDrawMediaStream *ddraw_stream;
7983 IDirectDrawStreamSample *sample;
7984 DDSURFACEDESC format1;
7985 DDSURFACEDESC format2;
7986 IMediaStream *stream;
7987 IDirectDraw *ddraw;
7988 HRESULT hr;
7989 RECT rect;
7990 ULONG ref;
7992 hr = DirectDrawCreate(NULL, &ddraw, NULL);
7993 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7995 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
7996 ok(hr == S_OK, "Got hr %#lx.\n", hr);
7998 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
7999 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8001 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)ddraw, &MSPID_PrimaryVideo, 0, &stream);
8002 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8004 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
8005 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8007 /* Crashes on native. */
8008 if (0)
8010 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, NULL);
8011 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
8014 SetRectEmpty(&rect);
8015 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, &rect, 0, &sample);
8016 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
8018 EXPECT_REF(mmstream, 1);
8019 EXPECT_REF(stream, 3);
8020 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &sample);
8021 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8022 EXPECT_REF(mmstream, 2);
8023 EXPECT_REF(stream, 4);
8025 hr = IDirectDrawStreamSample_GetSurface(sample, NULL, NULL);
8026 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8028 hr = IDirectDrawStreamSample_GetSurface(sample, NULL, &rect);
8029 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8031 hr = IDirectDrawStreamSample_GetSurface(sample, &surface, NULL);
8032 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8033 ok(surface != NULL, "Expected non-NULL surface.\n");
8034 IDirectDrawSurface_Release(surface);
8036 surface = NULL;
8037 hr = IDirectDrawStreamSample_GetSurface(sample, &surface, &rect);
8038 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8039 ok(surface != NULL, "Expected non-NULL surface.\n");
8041 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc);
8042 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8043 ok(desc.dwWidth == 100, "Expected width 100, got %ld.\n", desc.dwWidth);
8044 ok(desc.dwHeight == 100, "Expected height 100, got %ld.\n", desc.dwHeight);
8045 ok(desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Expected format flags DDPF_RGB, got %#lx.\n", desc.ddpfPixelFormat.dwFlags);
8046 ok(desc.ddpfPixelFormat.u1.dwRGBBitCount, "Expected non-zero RGB bit count.\n");
8047 IDirectDrawSurface_Release(surface);
8048 IDirectDrawStreamSample_Release(sample);
8049 EXPECT_REF(stream, 3);
8051 memset(&desc, 0, sizeof(desc));
8052 desc.dwSize = sizeof(desc);
8053 desc.dwFlags = DDSD_CAPS;
8054 desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
8055 hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
8056 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8058 EXPECT_REF(surface, 1);
8059 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, NULL, 0, &sample);
8060 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8061 EXPECT_REF(surface, 2);
8063 surface2 = NULL;
8064 SetRectEmpty(&rect);
8065 hr = IDirectDrawStreamSample_GetSurface(sample, &surface2, &rect);
8066 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8067 ok(surface2 == surface, "Expected surface %p, got %p.\n", surface, surface2);
8068 ok(rect.right > 0 && rect.bottom > 0, "Got rect %ld, %ld.\n", rect.right, rect.bottom);
8069 EXPECT_REF(surface, 3);
8070 IDirectDrawSurface_Release(surface2);
8071 EXPECT_REF(surface, 2);
8072 IDirectDrawStreamSample_Release(sample);
8073 EXPECT_REF(surface, 1);
8075 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, &rect, 0, &sample);
8076 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8078 ref = IDirectDrawStreamSample_Release(sample);
8079 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8080 ref = IDirectDrawSurface_Release(surface);
8081 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8083 memset(&desc, 0, sizeof(desc));
8084 desc.dwSize = sizeof(desc);
8085 desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
8086 desc.dwWidth = 444;
8087 desc.dwHeight = 400;
8088 desc.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
8089 desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
8090 desc.ddpfPixelFormat.u1.dwRGBBitCount = 32;
8091 desc.ddpfPixelFormat.u2.dwRBitMask = 0xff0000;
8092 desc.ddpfPixelFormat.u3.dwGBitMask = 0x00ff00;
8093 desc.ddpfPixelFormat.u4.dwBBitMask = 0x0000ff;
8094 desc.ddpfPixelFormat.u5.dwRGBAlphaBitMask = 0xff000000;
8095 desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
8096 hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
8097 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8099 SetRect(&rect, 111, 100, 333, 300);
8101 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, &rect, 0, &sample);
8102 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8103 ref = IDirectDrawStreamSample_Release(sample);
8104 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8106 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &sample);
8107 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8108 surface2 = NULL;
8109 hr = IDirectDrawStreamSample_GetSurface(sample, &surface2, &rect);
8110 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8112 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc);
8113 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8114 hr = IDirectDrawSurface_GetSurfaceDesc(surface2, &desc2);
8115 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8116 ok(desc2.dwWidth == 222, "Got width %lu.\n", desc2.dwWidth);
8117 ok(desc2.dwHeight == 200, "Got height %lu.\n", desc2.dwHeight);
8118 ok(memcmp(&desc2.ddpfPixelFormat, &desc.ddpfPixelFormat, sizeof(DDPIXELFORMAT)) == 0,
8119 "Pixel format didn't match.\n");
8121 ref = IDirectDrawStreamSample_Release(sample);
8122 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8123 ref = IDirectDrawSurface_Release(surface);
8124 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8125 ref = IDirectDrawSurface_Release(surface2);
8126 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8128 memset(&desc, 0, sizeof(desc));
8129 desc.dwSize = sizeof(desc);
8130 desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
8131 desc.dwWidth = 444;
8132 desc.dwHeight = 400;
8133 desc.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
8134 desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED4;
8135 desc.ddpfPixelFormat.u1.dwRGBBitCount = 4;
8136 desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
8137 hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
8138 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8140 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, NULL, 0, &sample);
8141 ok(hr == DDERR_INVALIDSURFACETYPE, "Got hr %#lx.\n", hr);
8143 IDirectDrawMediaStream_Release(ddraw_stream);
8144 ref = IDirectDrawSurface_Release(surface);
8145 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8146 ref = IAMMultiMediaStream_Release(mmstream);
8147 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8148 ref = IMediaStream_Release(stream);
8149 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8150 ref = IDirectDraw_Release(ddraw);
8151 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8153 format1 = rgb8_format;
8154 format1.dwFlags = 0;
8155 format1.dwWidth = 333;
8156 format1.dwHeight = 444;
8157 get_ddrawstream_create_sample_desc(&format1, NULL, NULL, &desc);
8158 ok(desc.dwWidth == 100, "Got width %lu.\n", desc.dwWidth);
8159 ok(desc.dwHeight == 100, "Got height %lu.\n", desc.dwHeight);
8160 ok(desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Got flags %#lx.\n", desc.ddpfPixelFormat.dwFlags);
8161 ok(desc.ddpfPixelFormat.u1.dwRGBBitCount == 32, "Got rgb bit count %lu.\n", desc.ddpfPixelFormat.u1.dwRGBBitCount);
8162 ok(desc.ddpfPixelFormat.u2.dwRBitMask == 0xff0000, "Got r bit mask %#lx.\n", desc.ddpfPixelFormat.u2.dwRBitMask);
8163 ok(desc.ddpfPixelFormat.u3.dwGBitMask == 0x00ff00, "Got g bit mask %#lx.\n", desc.ddpfPixelFormat.u3.dwGBitMask);
8164 ok(desc.ddpfPixelFormat.u4.dwBBitMask == 0x0000ff, "Got b bit mask %#lx.\n", desc.ddpfPixelFormat.u4.dwBBitMask);
8166 format1 = rgb8_format;
8167 format1.dwFlags |= DDSD_WIDTH;
8168 format1.dwWidth = 333;
8169 format1.dwHeight = 444;
8170 format2 = rgb8_format;
8171 format2.dwFlags = 0;
8172 get_ddrawstream_create_sample_desc(&format1, &format2, NULL, &desc);
8173 ok(desc.dwWidth == 333, "Got width %lu.\n", desc.dwWidth);
8174 ok(desc.dwHeight == 444, "Got height %lu.\n", desc.dwHeight);
8176 format1 = rgb8_format;
8177 format1.dwFlags |= DDSD_HEIGHT;
8178 format1.dwWidth = 333;
8179 format1.dwHeight = 444;
8180 format2 = rgb8_format;
8181 format2.dwFlags = 0;
8182 get_ddrawstream_create_sample_desc(&format1, &format2, NULL, &desc);
8183 ok(desc.dwWidth == 333, "Got width %lu.\n", desc.dwWidth);
8184 ok(desc.dwHeight == 444, "Got height %lu.\n", desc.dwHeight);
8186 get_ddrawstream_create_sample_desc(NULL, NULL, &rgb8_mt, &desc);
8187 ok(desc.dwWidth == 333, "Got width %lu.\n", desc.dwWidth);
8188 ok(desc.dwHeight == 444, "Got height %lu.\n", desc.dwHeight);
8189 ok(desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Got flags %#lx.\n", desc.ddpfPixelFormat.dwFlags);
8190 ok(desc.ddpfPixelFormat.u1.dwRGBBitCount == 32, "Got rgb bit count %lu.\n", desc.ddpfPixelFormat.u1.dwRGBBitCount);
8191 ok(desc.ddpfPixelFormat.u2.dwRBitMask == 0xff0000, "Got r bit mask %#lx.\n", desc.ddpfPixelFormat.u2.dwRBitMask);
8192 ok(desc.ddpfPixelFormat.u3.dwGBitMask == 0x00ff00, "Got g bit mask %#lx.\n", desc.ddpfPixelFormat.u3.dwGBitMask);
8193 ok(desc.ddpfPixelFormat.u4.dwBBitMask == 0x0000ff, "Got b bit mask %#lx.\n", desc.ddpfPixelFormat.u4.dwBBitMask);
8195 get_ddrawstream_create_sample_desc(&rgb565_format, NULL, NULL, &desc);
8196 ok(desc.dwWidth == 100, "Got width %lu.\n", desc.dwWidth);
8197 ok(desc.dwHeight == 100, "Got height %lu.\n", desc.dwHeight);
8198 ok(desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Got flags %#lx.\n", desc.ddpfPixelFormat.dwFlags);
8199 ok(desc.ddpfPixelFormat.u1.dwRGBBitCount == 16, "Got rgb bit count %lu.\n", desc.ddpfPixelFormat.u1.dwRGBBitCount);
8200 ok(desc.ddpfPixelFormat.u2.dwRBitMask == 0xf800, "Got r bit mask %#lx.\n", desc.ddpfPixelFormat.u2.dwRBitMask);
8201 ok(desc.ddpfPixelFormat.u3.dwGBitMask == 0x07e0, "Got g bit mask %#lx.\n", desc.ddpfPixelFormat.u3.dwGBitMask);
8202 ok(desc.ddpfPixelFormat.u4.dwBBitMask == 0x001f, "Got b bit mask %#lx.\n", desc.ddpfPixelFormat.u4.dwBBitMask);
8204 get_ddrawstream_create_sample_desc(&argb32_format, NULL, NULL, &desc);
8205 ok(desc.dwWidth == 100, "Got width %lu.\n", desc.dwWidth);
8206 ok(desc.dwHeight == 100, "Got height %lu.\n", desc.dwHeight);
8207 ok(desc.ddpfPixelFormat.dwFlags == (DDPF_RGB | DDPF_ALPHAPIXELS), "Got flags %#lx.\n", desc.ddpfPixelFormat.dwFlags);
8208 ok(desc.ddpfPixelFormat.u1.dwRGBBitCount == 32, "Got rgb bit count %lu.\n", desc.ddpfPixelFormat.u1.dwRGBBitCount);
8209 ok(desc.ddpfPixelFormat.u2.dwRBitMask == 0xff0000, "Got r bit mask %#lx.\n", desc.ddpfPixelFormat.u2.dwRBitMask);
8210 ok(desc.ddpfPixelFormat.u3.dwGBitMask == 0x00ff00, "Got g bit mask %#lx.\n", desc.ddpfPixelFormat.u3.dwGBitMask);
8211 ok(desc.ddpfPixelFormat.u4.dwBBitMask == 0x0000ff, "Got b bit mask %#lx.\n", desc.ddpfPixelFormat.u4.dwBBitMask);
8212 ok(desc.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0xff000000,
8213 "Got alpha bit mask %#lx.\n", desc.ddpfPixelFormat.u4.dwBBitMask);
8215 format1 = rgb32_format;
8216 format1.dwFlags |= DDSD_CAPS;
8217 format1.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
8218 get_ddrawstream_create_sample_desc(&format1, NULL, NULL, &desc);
8219 ok(desc.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN, "Expected set DDSCAPS_OFFSCREENPLAIN.\n");
8220 ok(desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY, "Expected set DDSCAPS_SYSTEMMEMORY.\n");
8221 ok(!(desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY), "Expected unset DDSCAPS_VIDEOMEMORY.\n");
8222 ok(desc.dwWidth == 100, "Got width %lu.\n", desc.dwWidth);
8223 ok(desc.dwHeight == 100, "Got height %lu.\n", desc.dwHeight);
8224 ok(desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Got flags %#lx.\n", desc.ddpfPixelFormat.dwFlags);
8225 ok(desc.ddpfPixelFormat.u1.dwRGBBitCount == 32, "Got rgb bit count %lu.\n", desc.ddpfPixelFormat.u1.dwRGBBitCount);
8226 ok(desc.ddpfPixelFormat.u2.dwRBitMask == 0xff0000, "Got r bit mask %#lx.\n", desc.ddpfPixelFormat.u2.dwRBitMask);
8227 ok(desc.ddpfPixelFormat.u3.dwGBitMask == 0x00ff00, "Got g bit mask %#lx.\n", desc.ddpfPixelFormat.u3.dwGBitMask);
8228 ok(desc.ddpfPixelFormat.u4.dwBBitMask == 0x0000ff, "Got b bit mask %#lx.\n", desc.ddpfPixelFormat.u4.dwBBitMask);
8230 format1 = rgb32_format;
8231 format1.dwFlags |= DDSD_CKSRCBLT;
8232 format1.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff;
8233 format1.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff;
8234 get_ddrawstream_create_sample_desc(&format1, NULL, NULL, &desc);
8235 ok(!(desc.dwFlags & DDSD_CKSRCBLT), "Expected unset DDSD_CKSRCBLT.\n");
8236 ok(desc.dwWidth == 100, "Got width %lu.\n", desc.dwWidth);
8237 ok(desc.dwHeight == 100, "Got height %lu.\n", desc.dwHeight);
8238 ok(desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Got flags %#lx.\n", desc.ddpfPixelFormat.dwFlags);
8239 ok(desc.ddpfPixelFormat.u1.dwRGBBitCount == 32, "Got rgb bit count %lu.\n", desc.ddpfPixelFormat.u1.dwRGBBitCount);
8240 ok(desc.ddpfPixelFormat.u2.dwRBitMask == 0xff0000, "Got r bit mask %#lx.\n", desc.ddpfPixelFormat.u2.dwRBitMask);
8241 ok(desc.ddpfPixelFormat.u3.dwGBitMask == 0x00ff00, "Got g bit mask %#lx.\n", desc.ddpfPixelFormat.u3.dwGBitMask);
8242 ok(desc.ddpfPixelFormat.u4.dwBBitMask == 0x0000ff, "Got b bit mask %#lx.\n", desc.ddpfPixelFormat.u4.dwBBitMask);
8243 ok(desc.ddckCKSrcBlt.dwColorSpaceLowValue == 0, "Got color key low value %#lx.\n",
8244 desc.ddckCKSrcBlt.dwColorSpaceLowValue);
8245 ok(desc.ddckCKSrcBlt.dwColorSpaceHighValue == 0, "Got color key high value %#lx.\n",
8246 desc.ddckCKSrcBlt.dwColorSpaceHighValue);
8249 static void test_ddrawstream_qc(void)
8251 static const BYTE test_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
8252 IAMMultiMediaStream *mmstream = create_ammultimediastream();
8253 struct advise_time_cookie cookie = { 0 };
8254 IDirectDrawStreamSample *stream_sample;
8255 IDirectDrawMediaStream *ddraw_stream;
8256 IMediaFilter *graph_media_filter;
8257 STREAM_TIME filter_start_time;
8258 IMemInputPin *mem_input_pin;
8259 IMediaStreamFilter *filter;
8260 struct testfilter source;
8261 struct testclock clock;
8262 STREAM_TIME start_time;
8263 STREAM_TIME end_time;
8264 IGraphBuilder *graph;
8265 IMediaStream *stream;
8266 VIDEOINFO video_info;
8267 AM_MEDIA_TYPE mt;
8268 HANDLE thread;
8269 HRESULT hr;
8270 ULONG ref;
8271 IPin *pin;
8273 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
8274 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8275 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
8276 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8277 ok(!!filter, "Expected non-null filter.\n");
8278 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
8279 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8280 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
8281 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8282 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
8283 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8284 hr = IMediaStream_QueryInterface(stream, &IID_IMemInputPin, (void **)&mem_input_pin);
8285 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8286 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
8287 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8288 ok(graph != NULL, "Expected non-NULL graph.\n");
8289 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void **)&graph_media_filter);
8290 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8291 testfilter_init(&source);
8292 source.IQualityControl_iface.lpVtbl = &testsource_qc_vtbl;
8293 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
8294 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8295 testclock_init(&clock);
8296 cookie.advise_time_called_event = CreateEventW(NULL, FALSE, FALSE, NULL);
8297 ok(cookie.advise_time_called_event != NULL, "Expected non-NULL event.");
8299 video_info = rgb32_video_info;
8300 video_info.bmiHeader.biWidth = 3;
8301 video_info.bmiHeader.biHeight = 1;
8302 mt = rgb32_mt;
8303 mt.pbFormat = (BYTE *)&video_info;
8304 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
8305 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8307 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &stream_sample);
8308 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8310 /* There are no quality control messages without a sync source. */
8311 hr = IMediaFilter_SetSyncSource(graph_media_filter, NULL);
8312 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8314 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8315 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8317 source.qc_notify_sender = (IBaseFilter *)0xdeadbeef;
8318 source.qc_notify_quality.Type = Flood;
8319 source.qc_notify_quality.Proportion = 0xdeadbeef;
8320 source.qc_notify_quality.Late = 0xdeadbeef;
8321 source.qc_notify_quality.TimeStamp = 0xdeadbeef;
8323 thread = ammediastream_async_receive_time(&source,
8324 11111111, 11111111, test_data, sizeof(test_data));
8325 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
8327 hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
8328 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8330 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8331 CloseHandle(thread);
8333 ok(source.qc_notify_sender == (IBaseFilter *)0xdeadbeef, "Got sender %p.\n",
8334 source.qc_notify_sender);
8335 ok(source.qc_notify_quality.Type == Flood, "Got type %d.\n",
8336 source.qc_notify_quality.Type);
8337 ok(source.qc_notify_quality.Proportion == 0xdeadbeef, "Got proportion %ld.\n",
8338 source.qc_notify_quality.Proportion);
8339 ok(source.qc_notify_quality.Late == 0xdeadbeef,
8340 "Got late %s.\n", wine_dbgstr_longlong(source.qc_notify_quality.Late));
8341 ok(source.qc_notify_quality.TimeStamp == 0xdeadbeef, "Got time stamp %s.\n",
8342 wine_dbgstr_longlong(source.qc_notify_quality.TimeStamp));
8344 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8345 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8347 hr = IMediaFilter_SetSyncSource(graph_media_filter, &clock.IReferenceClock_iface);
8348 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8350 clock.time = 12345678;
8352 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8353 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8355 hr = IMediaStreamFilter_GetCurrentStreamTime(filter, &filter_start_time);
8356 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8358 /* Quality control message is sent on update completion, q.Late is computed
8359 * as a difference between sample start time and update completion time. */
8361 /* Test Update() before Reveive(). */
8362 source.qc_notify_sender = (IBaseFilter *)0xdeadbeef;
8363 source.qc_notify_quality.Type = Flood;
8364 source.qc_notify_quality.Proportion = 0xdeadbeef;
8365 source.qc_notify_quality.Late = 0xdeadbeef;
8366 source.qc_notify_quality.TimeStamp = 0xdeadbeef;
8368 clock.time = 12345678 - filter_start_time + 11111111;
8370 hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
8371 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
8373 clock.advise_time_cookie = &cookie;
8374 clock.time = 12345678 - filter_start_time + 11111111 + 100000;
8376 start_time = 11111111 + 200000;
8377 end_time = 11111111 + 200000;
8378 thread = ammediastream_async_receive_time(&source,
8379 start_time, end_time, test_data, sizeof(test_data));
8380 ok(!WaitForSingleObject(cookie.advise_time_called_event, 2000), "Wait timed out.\n");
8382 ok(source.qc_notify_sender == (IBaseFilter *)0xdeadbeef, "Got sender %p.\n",
8383 source.qc_notify_sender);
8384 ok(source.qc_notify_quality.Type == Flood, "Got type %d.\n",
8385 source.qc_notify_quality.Type);
8386 ok(source.qc_notify_quality.Proportion == 0xdeadbeef, "Got proportion %ld.\n",
8387 source.qc_notify_quality.Proportion);
8388 ok(source.qc_notify_quality.Late == 0xdeadbeef,
8389 "Got late %s.\n", wine_dbgstr_longlong(source.qc_notify_quality.Late));
8390 ok(source.qc_notify_quality.TimeStamp == 0xdeadbeef, "Got time stamp %s.\n",
8391 wine_dbgstr_longlong(source.qc_notify_quality.TimeStamp));
8393 clock.time = 12345678 - filter_start_time + 11111111 + 200000;
8395 SetEvent(cookie.event);
8397 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8398 CloseHandle(thread);
8400 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample, 0, 0);
8401 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8403 ok(source.qc_notify_sender == (IBaseFilter *)filter, "Got sender %p.\n",
8404 source.qc_notify_sender);
8405 ok(source.qc_notify_quality.Type == Famine, "Got type %d.\n",
8406 source.qc_notify_quality.Type);
8407 ok(source.qc_notify_quality.Proportion == 1000, "Got proportion %ld.\n",
8408 source.qc_notify_quality.Proportion);
8409 ok(source.qc_notify_quality.Late == 0, "Got late %s.\n",
8410 wine_dbgstr_longlong(source.qc_notify_quality.Late));
8411 ok(source.qc_notify_quality.TimeStamp == start_time, "Got time stamp %s.\n",
8412 wine_dbgstr_longlong(source.qc_notify_quality.TimeStamp));
8414 /* Test Update() after Reveive(). */
8415 source.qc_notify_sender = (IBaseFilter *)0xdeadbeef;
8416 source.qc_notify_quality.Type = Flood;
8417 source.qc_notify_quality.Proportion = 0xdeadbeef;
8418 source.qc_notify_quality.Late = 0xdeadbeef;
8419 source.qc_notify_quality.TimeStamp = 0xdeadbeef;
8421 clock.advise_time_cookie = &cookie;
8422 clock.time = 12345678 - filter_start_time + 11111111 + 300000;
8424 start_time = 11111111 + 400000;
8425 end_time = 11111111 + 400000;
8426 thread = ammediastream_async_receive_time(&source,
8427 start_time, end_time, test_data, sizeof(test_data));
8428 ok(!WaitForSingleObject(cookie.advise_time_called_event, 2000), "Wait timed out.\n");
8430 clock.time = 12345678 - filter_start_time + 11111111 + 400000;
8431 SetEvent(cookie.event);
8433 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
8435 ok(source.qc_notify_sender == (IBaseFilter *)0xdeadbeef, "Got sender %p.\n",
8436 source.qc_notify_sender);
8437 ok(source.qc_notify_quality.Type == Flood, "Got type %d.\n",
8438 source.qc_notify_quality.Type);
8439 ok(source.qc_notify_quality.Proportion == 0xdeadbeef, "Got proportion %ld.\n",
8440 source.qc_notify_quality.Proportion);
8441 ok(source.qc_notify_quality.Late == 0xdeadbeef,
8442 "Got late %s.\n", wine_dbgstr_longlong(source.qc_notify_quality.Late));
8443 ok(source.qc_notify_quality.TimeStamp == 0xdeadbeef, "Got time stamp %s.\n",
8444 wine_dbgstr_longlong(source.qc_notify_quality.TimeStamp));
8446 clock.time = 12345678 - filter_start_time + 11111111 + 500000;
8448 hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
8449 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8451 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8452 CloseHandle(thread);
8454 ok(source.qc_notify_sender == (IBaseFilter *)filter, "Got sender %p.\n",
8455 source.qc_notify_sender);
8456 ok(source.qc_notify_quality.Type == Famine, "Got type %d.\n",
8457 source.qc_notify_quality.Type);
8458 ok(source.qc_notify_quality.Proportion == 1000, "Got proportion %ld.\n",
8459 source.qc_notify_quality.Proportion);
8460 ok(source.qc_notify_quality.Late == 100000, "Got late %s.\n",
8461 wine_dbgstr_longlong(source.qc_notify_quality.Late));
8462 ok(source.qc_notify_quality.TimeStamp == start_time, "Got time stamp %s.\n",
8463 wine_dbgstr_longlong(source.qc_notify_quality.TimeStamp));
8465 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8466 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8467 IGraphBuilder_Disconnect(graph, pin);
8468 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
8470 CloseHandle(cookie.advise_time_called_event);
8471 ref = IDirectDrawStreamSample_Release(stream_sample);
8472 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8473 ref = IAMMultiMediaStream_Release(mmstream);
8474 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8475 IMediaFilter_Release(graph_media_filter);
8476 ref = IGraphBuilder_Release(graph);
8477 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8478 ref = IMediaStreamFilter_Release(filter);
8479 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8480 IPin_Release(pin);
8481 IMemInputPin_Release(mem_input_pin);
8482 IDirectDrawMediaStream_Release(ddraw_stream);
8483 ref = IMediaStream_Release(stream);
8484 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8487 static void test_ddrawstreamsample_get_media_stream(void)
8489 IAMMultiMediaStream *mmstream = create_ammultimediastream();
8490 IDirectDrawMediaStream *ddraw_stream;
8491 IDirectDrawStreamSample *sample;
8492 IMediaStream *stream, *stream2;
8493 IDirectDraw *ddraw;
8494 HRESULT hr;
8495 ULONG ref;
8497 hr = DirectDrawCreate(NULL, &ddraw, NULL);
8498 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8500 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
8501 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8503 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
8504 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8506 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)ddraw, &MSPID_PrimaryVideo, 0, &stream);
8507 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8509 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
8510 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8512 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &sample);
8513 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8515 /* Crashes on native. */
8516 if (0)
8518 hr = IDirectDrawStreamSample_GetMediaStream(sample, NULL);
8519 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
8522 EXPECT_REF(stream, 4);
8523 hr = IDirectDrawStreamSample_GetMediaStream(sample, &stream2);
8524 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8525 ok(stream2 == stream, "Expected stream %p, got %p.\n", stream, stream2);
8526 EXPECT_REF(stream, 5);
8527 IMediaStream_Release(stream2);
8528 EXPECT_REF(stream, 4);
8530 IDirectDrawMediaStream_Release(ddraw_stream);
8531 ref = IDirectDrawStreamSample_Release(sample);
8532 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8533 ref = IAMMultiMediaStream_Release(mmstream);
8534 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8535 ref = IMediaStream_Release(stream);
8536 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8537 ref = IDirectDraw_Release(ddraw);
8538 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8541 static void test_ddrawstreamsample_update(void)
8543 static const BYTE initial_data[] =
8545 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
8547 static const BYTE test_data[] =
8549 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
8550 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
8552 IAMMultiMediaStream *mmstream = create_ammultimediastream();
8553 IDirectDrawStreamSample *stream_sample;
8554 struct advise_time_cookie cookie = {0};
8555 IDirectDrawMediaStream *ddraw_stream;
8556 IMediaControl *media_control;
8557 IDirectDrawSurface *surface;
8558 IMemInputPin *mem_input_pin;
8559 IMediaSample *media_sample;
8560 IMediaFilter *media_filter;
8561 REFERENCE_TIME start_time;
8562 REFERENCE_TIME end_time;
8563 struct testfilter source;
8564 struct testclock clock;
8565 IGraphBuilder *graph;
8566 IMediaStream *stream;
8567 VIDEOINFO video_info;
8568 DDSURFACEDESC desc;
8569 IDirectDraw *ddraw;
8570 AM_MEDIA_TYPE mt;
8571 HANDLE thread;
8572 HANDLE event;
8573 HRESULT hr;
8574 ULONG ref;
8575 IPin *pin;
8576 RECT rect;
8577 int i;
8579 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
8580 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8581 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
8582 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8583 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
8584 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8585 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
8586 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8587 hr = IMediaStream_QueryInterface(stream, &IID_IMemInputPin, (void **)&mem_input_pin);
8588 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8589 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw);
8590 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8591 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
8592 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8593 ok(graph != NULL, "Expected non-NULL graph.\n");
8594 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void **)&media_control);
8595 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8596 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void **)&media_filter);
8597 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8598 testfilter_init(&source);
8599 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
8600 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8601 testclock_init(&clock);
8602 event = CreateEventW(NULL, FALSE, FALSE, NULL);
8603 ok(event != NULL, "Expected non-NULL event.");
8604 cookie.advise_time_called_event = CreateEventW(NULL, FALSE, FALSE, NULL);
8605 ok(cookie.advise_time_called_event != NULL, "Expected non-NULL event.");
8607 hr = IMediaFilter_SetSyncSource(media_filter, NULL);
8608 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8610 desc = rgb24_format;
8611 desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
8612 desc.dwWidth = 4;
8613 desc.dwHeight = 5;
8614 desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
8615 hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
8616 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8617 /* Make the rect width equal to the surface width, as the native
8618 * implementation incorrectly handles rects that are not full-width
8619 * when the ddraw stream's custom allocator is not used. */
8620 SetRect(&rect, 0, 1, 4, 3);
8621 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, &rect, 0, &stream_sample);
8622 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8624 hr = IDirectDrawStreamSample_Update(stream_sample, 0, event, apc_func, 0);
8625 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
8627 hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
8628 ok(hr == MS_E_NOTRUNNING, "Got hr %#lx.\n", hr);
8630 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8631 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8633 hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
8634 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#lx.\n", hr);
8636 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8637 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8638 video_info = rgb24_video_info;
8639 video_info.bmiHeader.biWidth = 4;
8640 video_info.bmiHeader.biHeight = -2;
8641 mt = rgb24_mt;
8642 mt.pbFormat = (BYTE *)&video_info;
8643 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
8644 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8646 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8647 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8649 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8650 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8651 for (i = 0; i < 5; ++i)
8652 memcpy((BYTE *)desc.lpSurface + i * desc.u1.lPitch, initial_data, 12);
8653 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8654 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8656 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8658 ammediastream_mem_input_pin = mem_input_pin;
8659 ammediastream_media_sample = media_sample;
8660 ammediastream_sleep_time = 0;
8661 ammediastream_expected_hr = S_OK;
8662 thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
8664 Sleep(100);
8665 hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
8666 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8667 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8668 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8669 ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8670 ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.u1.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n");
8671 ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.u1.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n");
8672 ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8673 ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8674 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8675 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8677 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8678 CloseHandle(thread);
8680 ref = IMediaSample_Release(media_sample);
8681 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8683 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8684 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8685 IGraphBuilder_Disconnect(graph, pin);
8686 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
8687 video_info = rgb24_video_info;
8688 video_info.bmiHeader.biWidth = 4;
8689 video_info.bmiHeader.biHeight = 2;
8690 mt = rgb24_mt;
8691 mt.pbFormat = (BYTE *)&video_info;
8692 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
8693 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8694 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8695 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8697 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8698 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8699 for (i = 0; i < 5; ++i)
8700 memcpy((BYTE *)desc.lpSurface + i * desc.u1.lPitch, initial_data, 12);
8701 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8702 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8704 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8706 ammediastream_mem_input_pin = mem_input_pin;
8707 ammediastream_media_sample = media_sample;
8708 ammediastream_sleep_time = 0;
8709 ammediastream_expected_hr = S_OK;
8710 thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
8712 Sleep(100);
8713 hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
8714 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8715 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8716 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8717 ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8718 ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.u1.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n");
8719 ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.u1.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n");
8720 ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8721 ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8722 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8723 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8725 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8726 CloseHandle(thread);
8728 ref = IMediaSample_Release(media_sample);
8729 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8731 hr = IPin_EndOfStream(pin);
8732 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8734 hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
8735 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#lx.\n", hr);
8737 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8738 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8739 hr = IMediaControl_Pause(media_control);
8740 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8742 hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
8743 ok(hr == MS_E_NOTRUNNING, "Got hr %#lx.\n", hr);
8745 hr = IMediaControl_Stop(media_control);
8746 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8747 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8748 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8750 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8751 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8752 for (i = 0; i < 5; ++i)
8753 memcpy((BYTE *)desc.lpSurface + i * desc.u1.lPitch, initial_data, 12);
8754 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8755 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8757 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8759 ammediastream_mem_input_pin = mem_input_pin;
8760 ammediastream_media_sample = media_sample;
8761 ammediastream_sleep_time = 100;
8762 ammediastream_expected_hr = S_OK;
8763 thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
8765 hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
8766 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8767 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8768 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8769 ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8770 ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.u1.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n");
8771 ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.u1.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n");
8772 ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8773 ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8774 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8775 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8777 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8778 CloseHandle(thread);
8780 ref = IMediaSample_Release(media_sample);
8781 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8783 ammediastream_pin = pin;
8784 ammediastream_sleep_time = 100;
8785 ammediastream_expected_hr = S_OK;
8786 thread = CreateThread(NULL, 0, ammediastream_end_of_stream, NULL, 0, NULL);
8788 hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
8789 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#lx.\n", hr);
8791 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8792 CloseHandle(thread);
8794 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8795 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8796 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8797 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8799 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8800 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8801 for (i = 0; i < 5; ++i)
8802 memcpy((BYTE *)desc.lpSurface + i * desc.u1.lPitch, initial_data, 12);
8803 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8804 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8806 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8808 ammediastream_mem_input_pin = mem_input_pin;
8809 ammediastream_media_sample = media_sample;
8810 ammediastream_sleep_time = 100;
8811 ammediastream_expected_hr = S_OK;
8812 thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
8814 hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_CONTINUOUS, NULL, NULL, 0);
8815 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8816 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8817 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8818 ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8819 ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.u1.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n");
8820 ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.u1.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n");
8821 ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8822 ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8823 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8824 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8826 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8827 CloseHandle(thread);
8829 ref = IMediaSample_Release(media_sample);
8830 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8832 hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC | SSUPDATE_CONTINUOUS, NULL, NULL, 0);
8833 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
8835 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8836 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8837 for (i = 0; i < 5; ++i)
8838 memcpy((BYTE *)desc.lpSurface + i * desc.u1.lPitch, initial_data, 12);
8839 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8840 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8842 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8843 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
8844 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8845 ref = IMediaSample_Release(media_sample);
8846 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8848 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8849 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8850 ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8851 ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.u1.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n");
8852 ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.u1.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n");
8853 ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8854 ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8855 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8856 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8858 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8859 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8860 for (i = 0; i < 5; ++i)
8861 memcpy((BYTE *)desc.lpSurface + i * desc.u1.lPitch, initial_data, 12);
8862 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8863 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8865 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8866 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
8867 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8868 ref = IMediaSample_Release(media_sample);
8869 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8871 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8872 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8873 ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8874 ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.u1.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n");
8875 ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.u1.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n");
8876 ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8877 ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8878 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8879 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8881 hr = IPin_EndOfStream(pin);
8882 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8884 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8885 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8886 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8887 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8889 hr = IDirectDrawStreamSample_Update(stream_sample, 0, event, NULL, 0);
8890 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
8892 ok(WaitForSingleObject(event, 0) == WAIT_TIMEOUT, "Event should not be signaled.\n");
8894 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8895 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
8896 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8897 ref = IMediaSample_Release(media_sample);
8898 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8900 ok(WaitForSingleObject(event, 0) == 0, "Event should be signaled.\n");
8902 hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
8903 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
8904 EXPECT_REF(stream_sample, 1);
8906 hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
8907 ok(hr == MS_E_BUSY, "Got hr %#lx.\n", hr);
8909 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8910 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8911 hr = IMediaFilter_SetSyncSource(media_filter, &clock.IReferenceClock_iface);
8912 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8913 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8914 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8916 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8917 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8918 for (i = 0; i < 5; ++i)
8919 memcpy((BYTE *)desc.lpSurface + i * desc.u1.lPitch, initial_data, 12);
8920 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8921 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8923 hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
8924 ok(hr == MS_E_BUSY, "Got hr %#lx.\n", hr);
8926 clock.advise_time_cookie = &cookie;
8928 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8929 start_time = 11111111;
8930 end_time = 11111111;
8931 hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
8932 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8934 ammediastream_mem_input_pin = mem_input_pin;
8935 ammediastream_media_sample = media_sample;
8936 ammediastream_sleep_time = 0;
8937 ammediastream_expected_hr = S_OK;
8938 thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
8939 ok(!WaitForSingleObject(cookie.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
8940 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
8942 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8943 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8944 for (i = 0; i < 5; ++i)
8945 ok(memcmp((BYTE *)desc.lpSurface + i * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8946 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8947 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8949 SetEvent(cookie.event);
8951 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8952 CloseHandle(thread);
8954 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8955 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8956 ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8957 ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.u1.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n");
8958 ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.u1.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n");
8959 ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8960 ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8961 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8962 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8964 ref = IMediaSample_Release(media_sample);
8965 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8967 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8968 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8969 IGraphBuilder_Disconnect(graph, pin);
8970 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
8971 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8972 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8974 hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
8975 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#lx.\n", hr);
8977 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8978 ok(hr == S_OK, "Got hr %#lx.\n", hr);
8980 CloseHandle(cookie.advise_time_called_event);
8981 CloseHandle(event);
8982 ref = IDirectDrawStreamSample_Release(stream_sample);
8983 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8984 ref = IDirectDrawSurface_Release(surface);
8985 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8986 ref = IAMMultiMediaStream_Release(mmstream);
8987 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8988 IMediaControl_Release(media_control);
8989 IMediaFilter_Release(media_filter);
8990 ref = IGraphBuilder_Release(graph);
8991 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8992 IPin_Release(pin);
8993 IMemInputPin_Release(mem_input_pin);
8994 IDirectDrawMediaStream_Release(ddraw_stream);
8995 ref = IMediaStream_Release(stream);
8996 ok(!ref, "Got outstanding refcount %ld.\n", ref);
8997 ref = IDirectDraw_Release(ddraw);
8998 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9001 static void test_ddrawstreamsample_completion_status(void)
9003 static const BYTE test_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
9004 IAMMultiMediaStream *mmstream = create_ammultimediastream();
9005 struct advise_time_cookie cookie = { 0 };
9006 IDirectDrawStreamSample *stream_sample1;
9007 IDirectDrawStreamSample *stream_sample2;
9008 IDirectDrawMediaStream *ddraw_stream;
9009 STREAM_TIME filter_start_time;
9010 IMediaStreamFilter *filter;
9011 IMediaSample *media_sample;
9012 IMediaFilter *media_filter;
9013 struct testfilter source;
9014 struct testclock clock;
9015 VIDEOINFO video_info;
9016 IGraphBuilder *graph;
9017 IMediaStream *stream;
9018 AM_MEDIA_TYPE mt;
9019 HANDLE thread;
9020 HRESULT hr;
9021 ULONG ref;
9022 IPin *pin;
9024 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
9025 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9026 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
9027 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9028 ok(!!filter, "Expected non-null filter.\n");
9029 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
9030 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9031 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
9032 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9033 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
9034 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9035 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
9036 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9037 ok(graph != NULL, "Expected non-NULL graph.\n");
9038 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void **)&media_filter);
9039 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9040 testfilter_init(&source);
9041 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
9042 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9043 testclock_init(&clock);
9044 cookie.advise_time_called_event = CreateEventW(NULL, FALSE, FALSE, NULL);
9046 hr = IMediaFilter_SetSyncSource(media_filter, NULL);
9047 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9049 video_info = rgb32_video_info;
9050 video_info.bmiHeader.biWidth = 3;
9051 video_info.bmiHeader.biHeight = 1;
9052 mt = rgb32_mt;
9053 mt.pbFormat = (BYTE *)&video_info;
9054 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
9055 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9056 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
9057 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9059 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &stream_sample1);
9060 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9061 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &stream_sample2);
9062 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9064 /* Initial status is S_OK. */
9065 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9066 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9068 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_WAIT, INFINITE);
9069 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9071 /* Update changes the status to MS_S_PENDING. */
9072 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
9073 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9075 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9076 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9078 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_WAIT, 100);
9079 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9081 /* Each Receive call changes the status of one queued sample to S_OK in the same order Update was called. */
9082 hr = IDirectDrawStreamSample_Update(stream_sample2, SSUPDATE_ASYNC, NULL, NULL, 0);
9083 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9085 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample2, 0, 0);
9086 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9088 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
9089 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
9090 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9091 ref = IMediaSample_Release(media_sample);
9092 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9094 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9095 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9097 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_WAIT, INFINITE);
9098 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9100 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample2, 0, 0);
9101 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9103 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
9104 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
9105 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9106 ref = IMediaSample_Release(media_sample);
9107 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9109 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample2, 0, 0);
9110 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9112 /* COMPSTAT_NOUPDATEOK removes the sample from the queue and changes the status to MS_S_NOUPDATE. */
9113 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
9114 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9116 hr = IDirectDrawStreamSample_Update(stream_sample2, SSUPDATE_ASYNC, NULL, NULL, 0);
9117 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9119 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_NOUPDATEOK, 0);
9120 ok(hr == MS_S_NOUPDATE, "Got hr %#lx.\n", hr);
9122 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_WAIT, INFINITE);
9123 ok(hr == MS_S_NOUPDATE, "Got hr %#lx.\n", hr);
9125 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
9126 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
9127 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9128 ref = IMediaSample_Release(media_sample);
9129 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9131 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9132 ok(hr == MS_S_NOUPDATE, "Got hr %#lx.\n", hr);
9134 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample2, 0, 0);
9135 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9137 /* COMPSTAT_ABORT removes the sample from the queue and changes the status to MS_S_NOUPDATE. */
9138 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
9139 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9141 hr = IDirectDrawStreamSample_Update(stream_sample2, SSUPDATE_ASYNC, NULL, NULL, 0);
9142 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9144 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_ABORT, 0);
9145 ok(hr == MS_S_NOUPDATE, "Got hr %#lx.\n", hr);
9147 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_WAIT, INFINITE);
9148 ok(hr == MS_S_NOUPDATE, "Got hr %#lx.\n", hr);
9150 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
9151 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
9152 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9153 ref = IMediaSample_Release(media_sample);
9154 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9156 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9157 ok(hr == MS_S_NOUPDATE, "Got hr %#lx.\n", hr);
9159 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample2, 0, 0);
9160 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9162 /* COMPSTAT_WAIT has no effect when combined with COMPSTAT_NOUPDATEOK. */
9163 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
9164 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9166 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_NOUPDATEOK | COMPSTAT_WAIT, INFINITE);
9167 ok(hr == MS_S_NOUPDATE, "Got hr %#lx.\n", hr);
9169 /* COMPSTAT_WAIT has no effect when combined with COMPSTAT_ABORT. */
9170 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
9171 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9173 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_ABORT | COMPSTAT_WAIT, INFINITE);
9174 ok(hr == MS_S_NOUPDATE, "Got hr %#lx.\n", hr);
9176 /* EndOfStream changes the status of the queued samples to MS_S_ENDOFSTREAM. */
9177 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
9178 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9180 hr = IPin_EndOfStream(pin);
9181 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9183 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9184 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#lx.\n", hr);
9186 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_WAIT, INFINITE);
9187 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#lx.\n", hr);
9189 /* Update after EndOfStream changes the status to MS_S_ENDOFSTREAM. */
9190 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
9191 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#lx.\n", hr);
9193 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9194 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#lx.\n", hr);
9196 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_WAIT, INFINITE);
9197 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#lx.\n", hr);
9199 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
9200 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9201 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
9202 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9204 /* Continuous update can be canceled by COMPSTAT_NOUPDATEOK. */
9205 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC | SSUPDATE_CONTINUOUS, NULL, NULL, 0);
9206 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9208 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_NOUPDATEOK, 0);
9209 ok(hr == MS_S_NOUPDATE, "Got hr %#lx.\n", hr);
9211 /* Continuous update can be canceled by COMPSTAT_ABORT. */
9212 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC | SSUPDATE_CONTINUOUS, NULL, NULL, 0);
9213 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9215 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_ABORT, 0);
9216 ok(hr == MS_S_NOUPDATE, "Got hr %#lx.\n", hr);
9218 /* If a sample is in countinuous update mode, when Receive is called it's status remains MS_S_PENDING
9219 * and the sample is moved to the end of the queue. */
9220 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC | SSUPDATE_CONTINUOUS, NULL, NULL, 0);
9221 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9223 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC | SSUPDATE_CONTINUOUS, NULL, NULL, 0);
9224 ok(hr == MS_E_BUSY, "Got hr %#lx.\n", hr);
9226 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
9227 ok(hr == MS_E_BUSY, "Got hr %#lx.\n", hr);
9229 hr = IDirectDrawStreamSample_Update(stream_sample2, SSUPDATE_ASYNC, NULL, NULL, 0);
9230 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9232 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9233 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9235 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
9236 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
9237 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9238 ref = IMediaSample_Release(media_sample);
9239 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9241 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9242 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9244 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample2, 0, 0);
9245 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9247 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
9248 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
9249 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9250 ref = IMediaSample_Release(media_sample);
9251 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9253 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9254 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9256 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample2, 0, 0);
9257 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9259 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_NOUPDATEOK, 0);
9260 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9262 /* In continuous update mode, flushing does not affect the status. */
9263 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC | SSUPDATE_CONTINUOUS, NULL, NULL, 0);
9264 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9266 hr = IPin_BeginFlush(pin);
9267 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9269 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9270 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9272 hr = IPin_EndFlush(pin);
9273 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9275 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9276 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9278 /* In continuous update mode, stopping and running the stream does not affect the status. */
9279 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
9280 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9282 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9283 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9285 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
9286 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9288 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9289 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9291 /* In continuous update mode, EndOfStream changes the status to MS_S_ENDOFSTREAM. */
9292 hr = IPin_EndOfStream(pin);
9293 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9295 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9296 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#lx.\n", hr);
9298 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
9299 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9300 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
9301 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9303 /* COMPSTAT_WAIT resets the sample to the non-continuous update mode. */
9304 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC | SSUPDATE_CONTINUOUS, NULL, NULL, 0);
9305 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9307 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_WAIT, 0);
9308 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9310 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
9311 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
9312 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9313 ref = IMediaSample_Release(media_sample);
9314 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9316 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9317 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9319 /* In continuous update mode, CompletionStatus with COMPSTAT_WAIT returns when Receive is called. */
9320 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC | SSUPDATE_CONTINUOUS, NULL, NULL, 0);
9321 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9323 streamsample_sample = (IStreamSample *)stream_sample1;
9324 streamsample_flags = COMPSTAT_WAIT;
9325 streamsample_timeout = INFINITE;
9326 streamsample_expected_hr = S_OK;
9327 thread = CreateThread(NULL, 0, streamsample_completion_status, NULL, 0, NULL);
9328 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "CompletionStatus returned prematurely.\n");
9330 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
9331 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
9332 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9333 ref = IMediaSample_Release(media_sample);
9334 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9336 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
9337 CloseHandle(thread);
9339 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9340 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9342 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
9343 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9344 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
9345 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9347 /* CompletionStatus with COMPSTAT_WAIT returns when Receive is called. */
9348 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
9349 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9351 streamsample_sample = (IStreamSample *)stream_sample1;
9352 streamsample_flags = COMPSTAT_WAIT;
9353 streamsample_timeout = INFINITE;
9354 streamsample_expected_hr = S_OK;
9355 thread = CreateThread(NULL, 0, streamsample_completion_status, NULL, 0, NULL);
9356 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "CompletionStatus returned prematurely.\n");
9358 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
9359 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
9360 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9361 ref = IMediaSample_Release(media_sample);
9362 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9364 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
9365 CloseHandle(thread);
9367 /* CompletionStatus with COMPSTAT_WAIT returns when EndOfStream is called. */
9368 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
9369 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9371 streamsample_sample = (IStreamSample *)stream_sample1;
9372 streamsample_flags = COMPSTAT_WAIT;
9373 streamsample_timeout = INFINITE;
9374 streamsample_expected_hr = MS_S_ENDOFSTREAM;
9375 thread = CreateThread(NULL, 0, streamsample_completion_status, NULL, 0, NULL);
9376 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "CompletionStatus returned prematurely.\n");
9378 hr = IPin_EndOfStream(pin);
9379 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9381 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
9382 CloseHandle(thread);
9384 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
9385 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9386 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
9387 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9389 /* Stopping and running the stream does not affect the status and does not remove the sample from the queue. */
9390 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
9391 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9393 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
9394 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9396 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9397 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9399 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
9400 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9402 media_sample = ammediastream_allocate_sample(&source, test_data, 6);
9403 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
9404 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9405 ref = IMediaSample_Release(media_sample);
9406 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9408 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9409 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9411 /* When the stream is stopped Update does not change the status. */
9412 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
9413 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9415 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
9416 ok(hr == MS_E_NOTRUNNING, "Got hr %#lx.\n", hr);
9418 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9419 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9421 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_WAIT, INFINITE);
9422 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9424 /* When the wait time is less than 1ms the sample is updated immediately. */
9425 hr = IMediaFilter_SetSyncSource(media_filter, &clock.IReferenceClock_iface);
9426 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9428 clock.time = 12345678;
9430 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
9431 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9433 hr = IMediaStreamFilter_GetCurrentStreamTime(filter, &filter_start_time);
9434 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9436 clock.time = 12345678 - filter_start_time + 11111111;
9438 clock.advise_time_cookie = &cookie;
9440 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
9441 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9443 thread = ammediastream_async_receive_time(&source,
9444 11111111 + 9999, 11111111 + 9999, test_data, sizeof(test_data));
9445 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
9446 CloseHandle(thread);
9448 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, INFINITE);
9449 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9451 /* When the wait time is 1ms or greater AdviseTime is called
9452 * with base equal to the sample start time and offset equal to the filter start time. */
9453 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
9454 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9456 thread = ammediastream_async_receive_time(&source,
9457 11111111 + 10000, 11111111 + 10000, test_data, sizeof(test_data));
9458 ok(!WaitForSingleObject(cookie.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
9459 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
9461 ok(cookie.base == 11111111 + 10000, "Got base %s.\n", wine_dbgstr_longlong(cookie.base));
9462 ok(cookie.offset == 12345678 - filter_start_time, "Got offset %s.\n", wine_dbgstr_longlong(cookie.offset));
9464 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9465 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9467 clock.time = 12345678 - filter_start_time + 11111111 + 10000;
9468 SetEvent(cookie.event);
9470 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
9471 CloseHandle(thread);
9473 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9474 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9476 /* NewSegment does not affect the values passed to AdviseTime. */
9477 hr = IPin_NewSegment(pin, 22222222, 33333333, 1.0);
9478 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9480 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
9481 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9483 thread = ammediastream_async_receive_time(&source,
9484 11111111 + 20000, 11111111 + 20000, test_data, sizeof(test_data));
9485 ok(!WaitForSingleObject(cookie.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
9486 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
9488 ok(cookie.base == 11111111 + 20000, "Got base %s.\n", wine_dbgstr_longlong(cookie.base));
9489 ok(cookie.offset == 12345678 - filter_start_time, "Got offset %s.\n", wine_dbgstr_longlong(cookie.offset));
9491 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_NOUPDATEOK, 0);
9492 ok(hr == MS_S_NOUPDATE, "Got hr %#lx.\n", hr);
9494 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
9496 clock.time = 12345678 - filter_start_time + 11111111 + 20000;
9497 SetEvent(cookie.event);
9499 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
9501 /* COMPSTAT_NOUPDATEOK does not cause Receive to return.
9502 * Receive waits for the next sample to be queued and updates it. */
9503 hr = IDirectDrawStreamSample_Update(stream_sample1, 0, NULL, NULL, 0);
9504 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9506 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
9507 CloseHandle(thread);
9509 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
9510 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9512 thread = ammediastream_async_receive_time(&source,
9513 11111111 + 30000, 11111111 + 30000, test_data, sizeof(test_data));
9514 ok(!WaitForSingleObject(cookie.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
9515 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
9517 ok(cookie.base == 11111111 + 30000, "Got base %s.\n", wine_dbgstr_longlong(cookie.base));
9518 ok(cookie.offset == 12345678 - filter_start_time, "Got offset %s.\n", wine_dbgstr_longlong(cookie.offset));
9520 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_NOUPDATEOK | COMPSTAT_WAIT, INFINITE);
9521 ok(hr == MS_S_NOUPDATE, "Got hr %#lx.\n", hr);
9523 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
9525 clock.time = 12345678 - filter_start_time + 11111111 + 30000;
9526 SetEvent(cookie.event);
9528 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
9530 hr = IDirectDrawStreamSample_Update(stream_sample1, 0, NULL, NULL, 0);
9531 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9533 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
9534 CloseHandle(thread);
9536 /* COMPSTAT_ABORT does not cause Receive to return.
9537 * Receive waits for the next sample to be queued and updates it. */
9538 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
9539 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9541 thread = ammediastream_async_receive_time(&source,
9542 11111111 + 40000, 11111111 + 40000, test_data, sizeof(test_data));
9543 ok(!WaitForSingleObject(cookie.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
9544 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
9546 ok(cookie.base == 11111111 + 40000, "Got base %s.\n", wine_dbgstr_longlong(cookie.base));
9547 ok(cookie.offset == 12345678 - filter_start_time, "Got offset %s.\n", wine_dbgstr_longlong(cookie.offset));
9549 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_ABORT, 0);
9550 ok(hr == MS_S_NOUPDATE, "Got hr %#lx.\n", hr);
9552 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
9554 clock.time = 12345678 - filter_start_time + 11111111 + 40000;
9555 SetEvent(cookie.event);
9557 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
9559 hr = IDirectDrawStreamSample_Update(stream_sample1, 0, NULL, NULL, 0);
9560 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9562 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
9563 CloseHandle(thread);
9565 /* Stopping the stream causes Receive to return and leaves the sample with MS_S_PENDING status. */
9566 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
9567 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9569 thread = ammediastream_async_receive_time(&source,
9570 11111111 + 50000, 11111111 + 50000, test_data, sizeof(test_data));
9571 ok(!WaitForSingleObject(cookie.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
9572 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
9574 ok(cookie.base == 11111111 + 50000, "Got base %s.\n", wine_dbgstr_longlong(cookie.base));
9575 ok(cookie.offset == 12345678 - filter_start_time, "Got offset %s.\n", wine_dbgstr_longlong(cookie.offset));
9577 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
9578 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9580 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
9581 CloseHandle(thread);
9583 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
9584 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9586 IGraphBuilder_Disconnect(graph, pin);
9587 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
9589 CloseHandle(cookie.advise_time_called_event);
9590 ref = IDirectDrawStreamSample_Release(stream_sample1);
9591 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9592 ref = IDirectDrawStreamSample_Release(stream_sample2);
9593 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9594 ref = IAMMultiMediaStream_Release(mmstream);
9595 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9596 IMediaFilter_Release(media_filter);
9597 ref = IGraphBuilder_Release(graph);
9598 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9599 ref = IMediaStreamFilter_Release(filter);
9600 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9601 IPin_Release(pin);
9602 IDirectDrawMediaStream_Release(ddraw_stream);
9603 ref = IMediaStream_Release(stream);
9604 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9607 static void test_ddrawstreamsample_get_sample_times(void)
9609 static const BYTE test_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
9610 IAMMultiMediaStream *mmstream = create_ammultimediastream();
9611 IDirectDrawStreamSample *stream_sample;
9612 IMediaFilter *graph_media_filter;
9613 IDirectDrawMediaStream *ddraw_stream;
9614 STREAM_TIME filter_start_time;
9615 IMemInputPin *mem_input_pin;
9616 IMediaStreamFilter *filter;
9617 IMediaSample *media_sample;
9618 struct testfilter source;
9619 STREAM_TIME current_time;
9620 struct testclock clock;
9621 STREAM_TIME start_time;
9622 STREAM_TIME end_time;
9623 IGraphBuilder *graph;
9624 IMediaStream *stream;
9625 VIDEOINFO video_info;
9626 AM_MEDIA_TYPE mt;
9627 HRESULT hr;
9628 ULONG ref;
9629 IPin *pin;
9631 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
9632 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9633 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
9634 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9635 ok(!!filter, "Expected non-null filter.\n");
9636 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
9637 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9638 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
9639 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9640 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
9641 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9642 hr = IMediaStream_QueryInterface(stream, &IID_IMemInputPin, (void **)&mem_input_pin);
9643 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9644 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
9645 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9646 ok(graph != NULL, "Expected non-NULL graph.\n");
9647 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void **)&graph_media_filter);
9648 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9649 testfilter_init(&source);
9650 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
9651 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9652 testclock_init(&clock);
9654 video_info = rgb32_video_info;
9655 video_info.bmiHeader.biWidth = 3;
9656 video_info.bmiHeader.biHeight = 1;
9657 mt = rgb32_mt;
9658 mt.pbFormat = (BYTE *)&video_info;
9659 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
9660 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9662 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &stream_sample);
9663 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9665 clock.time = 12345678;
9667 current_time = 0xdeadbeefdeadbeef;
9668 hr = IDirectDrawStreamSample_GetSampleTimes(stream_sample, NULL, NULL, &current_time);
9669 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9670 ok(current_time == 0, "Got current time %s.\n", wine_dbgstr_longlong(current_time));
9672 hr = IMediaFilter_SetSyncSource(graph_media_filter, &clock.IReferenceClock_iface);
9673 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9675 current_time = 0xdeadbeefdeadbeef;
9676 hr = IDirectDrawStreamSample_GetSampleTimes(stream_sample, NULL, NULL, &current_time);
9677 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9678 ok(current_time == 0, "Got current time %s.\n", wine_dbgstr_longlong(current_time));
9680 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
9681 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9683 hr = IMediaStreamFilter_GetCurrentStreamTime(filter, &filter_start_time);
9684 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9686 clock.get_time_hr = E_FAIL;
9688 current_time = 0xdeadbeefdeadbeef;
9689 hr = IDirectDrawStreamSample_GetSampleTimes(stream_sample, NULL, NULL, &current_time);
9690 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9691 ok(current_time == 0xdeadbeefddf15da1 + filter_start_time, "Expected current time %s, got %s.\n",
9692 wine_dbgstr_longlong(0xdeadbeefddf15da1 + filter_start_time), wine_dbgstr_longlong(current_time));
9694 clock.get_time_hr = S_OK;
9696 current_time = 0xdeadbeefdeadbeef;
9697 hr = IDirectDrawStreamSample_GetSampleTimes(stream_sample, NULL, NULL, &current_time);
9698 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9699 ok(current_time == filter_start_time, "Expected current time %s, got %s.\n",
9700 wine_dbgstr_longlong(filter_start_time), wine_dbgstr_longlong(current_time));
9702 clock.time = 23456789;
9704 current_time = 0xdeadbeefdeadbeef;
9705 hr = IDirectDrawStreamSample_GetSampleTimes(stream_sample, NULL, NULL, &current_time);
9706 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9707 ok(current_time == filter_start_time + 11111111, "Expected current time %s, got %s.\n",
9708 wine_dbgstr_longlong(filter_start_time + 11111111), wine_dbgstr_longlong(current_time));
9710 start_time = 0xdeadbeefdeadbeef;
9711 end_time = 0xdeadbeefdeadbeef;
9712 hr = IDirectDrawStreamSample_GetSampleTimes(stream_sample, &start_time, &end_time, NULL);
9713 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9714 ok(start_time == 0, "Got start time %s.\n", wine_dbgstr_longlong(start_time));
9715 ok(end_time == 0, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
9717 hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
9718 ok(hr == MS_S_PENDING, "Got hr %#lx.\n", hr);
9720 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
9721 start_time = 12345678;
9722 end_time = 23456789;
9723 hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
9724 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9725 hr = IMemInputPin_Receive(mem_input_pin, media_sample);
9726 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9727 IMediaSample_Release(media_sample);
9729 start_time = 0xdeadbeefdeadbeef;
9730 end_time = 0xdeadbeefdeadbeef;
9731 hr = IDirectDrawStreamSample_GetSampleTimes(stream_sample, &start_time, &end_time, NULL);
9732 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9733 ok(start_time == 12345678, "Got start time %s.\n", wine_dbgstr_longlong(start_time));
9734 ok(end_time == 23456789, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
9736 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
9737 ok(hr == S_OK, "Got hr %#lx.\n", hr);
9738 IGraphBuilder_Disconnect(graph, pin);
9739 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
9741 ref = IDirectDrawStreamSample_Release(stream_sample);
9742 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9743 ref = IAMMultiMediaStream_Release(mmstream);
9744 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9745 IMediaFilter_Release(graph_media_filter);
9746 ref = IGraphBuilder_Release(graph);
9747 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9748 ref = IMediaStreamFilter_Release(filter);
9749 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9750 IPin_Release(pin);
9751 IMemInputPin_Release(mem_input_pin);
9752 IDirectDrawMediaStream_Release(ddraw_stream);
9753 ref = IMediaStream_Release(stream);
9754 ok(!ref, "Got outstanding refcount %ld.\n", ref);
9757 START_TEST(amstream)
9759 const WCHAR *test_avi_path;
9761 CoInitializeEx(NULL, COINIT_MULTITHREADED);
9763 test_interfaces();
9764 test_add_stream();
9765 test_media_streams();
9766 test_enum_pins();
9767 test_find_pin();
9768 test_pin_info();
9769 test_initialize();
9770 test_set_state();
9771 test_enum_media_types();
9772 test_media_types();
9773 test_get_end_of_stream_event_handle();
9775 test_avi_path = load_resource(L"test.avi");
9777 test_openfile(test_avi_path);
9778 test_mmstream_get_duration(test_avi_path);
9780 unload_resource(test_avi_path);
9782 test_audiodata_query_interface();
9783 test_audiodata_get_info();
9784 test_audiodata_set_buffer();
9785 test_audiodata_set_actual();
9786 test_audiodata_get_format();
9787 test_audiodata_set_format();
9789 test_audiostream_get_format();
9790 test_audiostream_set_format();
9791 test_audiostream_receive_connection();
9792 test_audiostream_receive();
9793 test_audiostream_initialize();
9794 test_audiostream_begin_flush_end_flush();
9795 test_audiostream_new_segment();
9797 test_audiostreamsample_update();
9798 test_audiostreamsample_completion_status();
9799 test_audiostreamsample_get_sample_times();
9800 test_audiostreamsample_get_media_stream();
9801 test_audiostreamsample_get_audio_data();
9803 test_ddrawstream_initialize();
9804 test_ddrawstream_getsetdirectdraw();
9805 test_ddrawstream_receive_connection();
9806 test_ddrawstream_create_sample();
9807 test_ddrawstream_get_format();
9808 test_ddrawstream_set_format();
9809 test_ddrawstream_receive();
9810 test_ddrawstream_begin_flush_end_flush();
9811 test_ddrawstream_new_segment();
9812 test_ddrawstream_get_time_per_frame();
9813 test_ddrawstream_qc();
9815 test_ddrawstreamsample_get_media_stream();
9816 test_ddrawstreamsample_update();
9817 test_ddrawstreamsample_completion_status();
9818 test_ddrawstreamsample_get_sample_times();
9820 test_ammediastream_join_am_multi_media_stream();
9821 test_ammediastream_join_filter();
9822 test_ammediastream_join_filter_graph();
9823 test_ammediastream_set_state();
9824 test_ammediastream_end_of_stream();
9826 test_mediastreamfilter_get_state();
9827 test_mediastreamfilter_stop_pause_run();
9828 test_mediastreamfilter_support_seeking();
9829 test_mediastreamfilter_seeking();
9830 test_mediastreamfilter_get_current_stream_time();
9831 test_mediastreamfilter_reference_time_to_stream_time();
9832 test_mediastreamfilter_wait_until();
9833 test_mediastreamfilter_end_of_stream();
9835 CoUninitialize();