mfplat: Read queue subscriber within the critical section.
[wine/zf.git] / dlls / amstream / tests / amstream.c
blob9cefec1244208e3ac28f7f40f5b5cbf789b55c7b
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 %u.\n", wine_dbgstr_w(path), GetLastError());
268 resource = FindResourceW(module, name, (const WCHAR *)RT_RCDATA);
269 ok(!!resource, "Failed to find resource %s, error %u.\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 %d, got %d\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 %#x.\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 %#x, expected %#x.\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 %#x.\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 %#x.\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);
390 IMediaStream_Release(stream);
392 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
393 ok(hr == S_OK, "Got hr %#x.\n", hr);
395 check_interface(stream, &IID_IAMMediaStream, TRUE);
396 check_interface(stream, &IID_IDirectDrawMediaStream, TRUE);
397 check_interface(stream, &IID_IMediaStream, TRUE);
398 check_interface(stream, &IID_IMemInputPin, TRUE);
399 check_interface(stream, &IID_IPin, TRUE);
400 check_interface(stream, &IID_IUnknown, TRUE);
402 check_interface(stream, &IID_IAMMediaTypeStream, FALSE);
403 check_interface(stream, &IID_IAMMultiMediaStream, FALSE);
404 check_interface(stream, &IID_IAudioMediaStream, FALSE);
405 check_interface(stream, &IID_IBaseFilter, FALSE);
406 check_interface(stream, &IID_IDirectDraw, FALSE);
407 check_interface(stream, &IID_IMediaFilter, FALSE);
408 check_interface(stream, &IID_IMediaStreamFilter, FALSE);
409 check_interface(stream, &IID_IMultiMediaStream, FALSE);
410 check_interface(stream, &IID_IPersist, FALSE);
412 IMediaStream_Release(stream);
414 ref = IAMMultiMediaStream_Release(mmstream);
415 ok(!ref, "Got outstanding refcount %u.\n", ref);
418 static void test_openfile(const WCHAR *test_avi_path)
420 IAMMultiMediaStream *mmstream = create_ammultimediastream();
421 IMediaControl *media_control;
422 IMediaStreamFilter *filter;
423 IMediaFilter *media_filter;
424 IReferenceClock *clock;
425 IGraphBuilder *graph;
426 OAFilterState state;
427 HRESULT hr;
428 ULONG ref;
430 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
431 ok(hr == S_OK, "Got hr %#x.\n", hr);
432 ok(!graph, "Expected NULL graph.\n");
434 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
435 ok(!!filter, "Expected non-NULL filter.\n");
436 ok(hr == S_OK, "Got hr %#x.\n", hr);
438 check_interface(filter, &IID_IMediaSeeking, FALSE);
440 hr = IAMMultiMediaStream_OpenFile(mmstream, test_avi_path, AMMSF_NORENDER);
441 ok(hr == S_OK, "Got hr %#x.\n", hr);
443 check_interface(filter, &IID_IMediaSeeking, FALSE);
445 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
446 ok(hr == S_OK, "Got hr %#x.\n", hr);
447 ok(!!graph, "Expected non-NULL graph.\n");
448 IGraphBuilder_Release(graph);
449 IMediaStreamFilter_Release(filter);
451 ref = IAMMultiMediaStream_Release(mmstream);
452 ok(!ref, "Got outstanding refcount %d.\n", ref);
454 mmstream = create_ammultimediastream();
455 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
456 ok(hr == S_OK, "Got hr %#x.\n", hr);
457 ok(!graph, "Expected NULL graph.\n");
459 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
460 ok(!!filter, "Expected non-NULL filter.\n");
461 ok(hr == S_OK, "Got hr %#x.\n", hr);
463 check_interface(filter, &IID_IMediaSeeking, FALSE);
465 hr = IAMMultiMediaStream_OpenFile(mmstream, test_avi_path, 0);
466 ok(hr == VFW_E_CANNOT_CONNECT, "Got hr %#x.\n", hr);
468 check_interface(filter, &IID_IMediaSeeking, FALSE);
470 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
471 ok(hr == S_OK, "Got hr %#x.\n", hr);
472 ok(!!graph, "Expected non-NULL graph.\n");
473 IGraphBuilder_Release(graph);
474 IMediaStreamFilter_Release(filter);
476 ref = IAMMultiMediaStream_Release(mmstream);
477 ok(!ref, "Got outstanding refcount %d.\n", ref);
479 mmstream = create_ammultimediastream();
480 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, NULL);
481 ok(hr == S_OK, "Got hr %#x.\n", hr);
482 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
483 ok(hr == S_OK, "Got hr %#x.\n", hr);
484 ok(!!graph, "Expected non-NULL graph.\n");
485 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void **)&media_filter);
486 ok(hr == S_OK, "Got hr %#x.\n", hr);
487 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
488 ok(hr == S_OK, "Got hr %#x.\n", hr);
490 check_interface(filter, &IID_IMediaSeeking, FALSE);
492 hr = IAMMultiMediaStream_OpenFile(mmstream, test_avi_path, 0);
493 ok(hr == S_OK, "Got hr %#x.\n", hr);
495 check_interface(filter, &IID_IMediaSeeking, TRUE);
497 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
498 ok(hr == S_OK, "Got hr %#x.\n", hr);
500 clock = NULL;
501 IMediaFilter_GetSyncSource(media_filter, &clock);
502 ok(!!clock, "Expected non-NULL clock.\n");
504 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
505 ok(hr == S_OK, "Got hr %#x.\n", hr);
507 ref = IAMMultiMediaStream_Release(mmstream);
508 ok(!ref, "Got outstanding refcount %d.\n", ref);
509 IMediaFilter_Release(media_filter);
510 ref = IGraphBuilder_Release(graph);
511 ok(!ref, "Got outstanding refcount %d.\n", ref);
512 ref = IMediaStreamFilter_Release(filter);
513 ok(!ref, "Got outstanding refcount %d.\n", ref);
514 ref = IReferenceClock_Release(clock);
515 ok(!ref, "Got outstanding refcount %d.\n", ref);
517 mmstream = create_ammultimediastream();
518 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, NULL);
519 ok(hr == S_OK, "Got hr %#x.\n", hr);
520 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
521 ok(hr == S_OK, "Got hr %#x.\n", hr);
522 ok(!!graph, "Expected non-NULL graph.\n");
523 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void **)&media_control);
524 ok(hr == S_OK, "Got hr %#x.\n", hr);
526 hr = IAMMultiMediaStream_OpenFile(mmstream, test_avi_path, AMMSF_RUN);
527 ok(hr == S_OK, "Got hr %#x.\n", hr);
529 state = 0xdeadbeef;
530 hr = IMediaControl_GetState(media_control, INFINITE, &state);
531 ok(hr == S_OK, "Got hr %#x.\n", hr);
532 ok(state == State_Running, "Got state %#x.\n", state);
534 ref = IAMMultiMediaStream_Release(mmstream);
535 ok(!ref, "Got outstanding refcount %d.\n", ref);
536 IMediaControl_Release(media_control);
537 ref = IGraphBuilder_Release(graph);
538 ok(!ref, "Got outstanding refcount %d.\n", ref);
540 mmstream = create_ammultimediastream();
541 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, NULL);
542 ok(hr == S_OK, "Got hr %#x.\n", hr);
543 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
544 ok(hr == S_OK, "Got hr %#x.\n", hr);
545 ok(!!graph, "Expected non-NULL graph.\n");
546 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void **)&media_filter);
547 ok(hr == S_OK, "Got hr %#x.\n", hr);
549 hr = IAMMultiMediaStream_OpenFile(mmstream, test_avi_path, AMMSF_NOCLOCK);
550 ok(hr == S_OK, "Got hr %#x.\n", hr);
552 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
553 ok(hr == S_OK, "Got hr %#x.\n", hr);
555 clock = (IReferenceClock *)0xdeadbeef;
556 IMediaFilter_GetSyncSource(media_filter, &clock);
557 ok(!clock, "Got clock %p.\n", clock);
559 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
560 ok(hr == S_OK, "Got hr %#x.\n", hr);
562 ref = IAMMultiMediaStream_Release(mmstream);
563 ok(!ref, "Got outstanding refcount %d.\n", ref);
564 IMediaFilter_Release(media_filter);
565 ref = IGraphBuilder_Release(graph);
566 ok(!ref, "Got outstanding refcount %d.\n", ref);
569 static void test_mmstream_get_duration(const WCHAR *test_avi_path)
571 IAMMultiMediaStream *mmstream = create_ammultimediastream();
572 HRESULT hr, audio_hr;
573 LONGLONG duration;
574 ULONG ref;
576 duration = 0xdeadbeefdeadbeefULL;
577 hr = IAMMultiMediaStream_GetDuration(mmstream, &duration);
578 ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr);
579 ok(duration == 0xdeadbeefdeadbeefULL, "Got duration %s.\n", wine_dbgstr_longlong(duration));
581 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, NULL);
582 ok(hr == S_OK, "Got hr %#x.\n", hr);
584 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, AMMSF_ADDDEFAULTRENDERER, NULL);
585 ok(hr == S_OK || hr == VFW_E_NO_AUDIO_HARDWARE, "Got hr %#x.\n", hr);
586 audio_hr = hr;
588 hr = IAMMultiMediaStream_OpenFile(mmstream, test_avi_path, 0);
589 ok(hr == S_OK, "Got hr %#x.\n", hr);
591 duration = 0xdeadbeefdeadbeefULL;
592 hr = IAMMultiMediaStream_GetDuration(mmstream, &duration);
593 if (audio_hr == S_OK)
595 ok(hr == S_OK, "Got hr %#x.\n", hr);
596 ok(duration == 1000000LL, "Got duration %s.\n", wine_dbgstr_longlong(duration));
598 else
600 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
601 ok(!duration, "Got duration %s.\n", wine_dbgstr_longlong(duration));
604 ref = IAMMultiMediaStream_Release(mmstream);
605 ok(!ref, "Got outstanding refcount %d.\n", ref);
607 mmstream = create_ammultimediastream();
608 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, NULL);
609 ok(hr == S_OK, "Got hr %#x.\n", hr);
611 duration = 0xdeadbeefdeadbeefULL;
612 hr = IAMMultiMediaStream_GetDuration(mmstream, &duration);
613 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
614 ok(duration == 0, "Got duration %s.\n", wine_dbgstr_longlong(duration));
616 ref = IAMMultiMediaStream_Release(mmstream);
617 ok(!ref, "Got outstanding refcount %d.\n", ref);
619 mmstream = create_ammultimediastream();
621 hr = IAMMultiMediaStream_OpenFile(mmstream, test_avi_path, 0);
622 ok(hr == VFW_E_CANNOT_CONNECT, "Got hr %#x.\n", hr);
624 duration = 0xdeadbeefdeadbeefULL;
625 hr = IAMMultiMediaStream_GetDuration(mmstream, &duration);
626 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
627 ok(duration == 0, "Got duration %s.\n", wine_dbgstr_longlong(duration));
629 ref = IAMMultiMediaStream_Release(mmstream);
630 ok(!ref, "Got outstanding refcount %d.\n", ref);
632 mmstream = create_ammultimediastream();
633 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, NULL);
634 ok(hr == S_OK, "Got hr %#x.\n", hr);
636 hr = IAMMultiMediaStream_OpenFile(mmstream, test_avi_path, AMMSF_NORENDER);
637 ok(hr == S_OK, "Got hr %#x.\n", hr);
639 duration = 0xdeadbeefdeadbeefULL;
640 hr = IAMMultiMediaStream_GetDuration(mmstream, &duration);
641 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
642 ok(duration == 0, "Got duration %s.\n", wine_dbgstr_longlong(duration));
644 ref = IAMMultiMediaStream_Release(mmstream);
645 ok(!ref, "Got outstanding refcount %d.\n", ref);
648 static const GUID test_mspid = {0x88888888};
650 struct teststream
652 IAMMediaStream IAMMediaStream_iface;
653 IPin IPin_iface;
654 LONG refcount;
655 GUID mspid;
656 IAMMultiMediaStream *mmstream;
657 IMediaStreamFilter *filter;
658 IFilterGraph *graph;
659 FILTER_STATE state;
660 HRESULT set_state_result;
663 static struct teststream *impl_from_IAMMediaStream(IAMMediaStream *iface)
665 return CONTAINING_RECORD(iface, struct teststream, IAMMediaStream_iface);
668 static struct teststream *impl_from_IPin(IPin *iface)
670 return CONTAINING_RECORD(iface, struct teststream, IPin_iface);
673 static HRESULT WINAPI pin_QueryInterface(IPin *iface, REFIID iid, void **out)
675 struct teststream *stream = impl_from_IPin(iface);
676 return IAMMediaStream_QueryInterface(&stream->IAMMediaStream_iface, iid, out);
679 static ULONG WINAPI pin_AddRef(IPin *iface)
681 struct teststream *stream = impl_from_IPin(iface);
682 return IAMMediaStream_AddRef(&stream->IAMMediaStream_iface);
685 static ULONG WINAPI pin_Release(IPin *iface)
687 struct teststream *stream = impl_from_IPin(iface);
688 return IAMMediaStream_Release(&stream->IAMMediaStream_iface);
691 static HRESULT WINAPI pin_Connect(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
693 ok(0, "Unexpected call.\n");
694 return E_NOTIMPL;
697 static HRESULT WINAPI pin_ReceiveConnection(IPin *iface, IPin *peer, const AM_MEDIA_TYPE *mt)
699 ok(0, "Unexpected call.\n");
700 return E_NOTIMPL;
703 static HRESULT WINAPI pin_Disconnect(IPin *iface)
705 if (winetest_debug > 1) trace("Disconnect\n");
706 return E_NOTIMPL;
709 static HRESULT WINAPI pin_ConnectedTo(IPin *iface, IPin **peer)
711 if (winetest_debug > 1) trace("ConnectedTo\n");
712 return E_NOTIMPL;
715 static HRESULT WINAPI pin_ConnectionMediaType(IPin *iface, AM_MEDIA_TYPE *mt)
717 ok(0, "Unexpected call.\n");
718 return E_NOTIMPL;
721 static HRESULT WINAPI pin_QueryPinInfo(IPin *iface, PIN_INFO *info)
723 ok(0, "Unexpected call.\n");
724 return E_NOTIMPL;
727 static HRESULT WINAPI pin_QueryDirection(IPin *iface, PIN_DIRECTION *dir)
729 if (winetest_debug > 1) trace("QueryDirection\n");
730 *dir = PINDIR_INPUT;
731 return S_OK;
734 static HRESULT WINAPI pin_QueryId(IPin *iface, WCHAR **id)
736 ok(0, "Unexpected call.\n");
737 return E_NOTIMPL;
740 static HRESULT WINAPI pin_QueryAccept(IPin *iface, const AM_MEDIA_TYPE *mt)
742 ok(0, "Unexpected call.\n");
743 return E_NOTIMPL;
746 static HRESULT WINAPI pin_EnumMediaTypes(IPin *iface, IEnumMediaTypes **out)
748 ok(0, "Unexpected call.\n");
749 return E_NOTIMPL;
752 static HRESULT WINAPI pin_QueryInternalConnections(IPin *iface, IPin **pins, ULONG *count)
754 ok(0, "Unexpected call.\n");
755 return E_NOTIMPL;
758 static HRESULT WINAPI pin_EndOfStream(IPin *iface)
760 ok(0, "Unexpected call.\n");
761 return E_NOTIMPL;
764 static HRESULT WINAPI pin_BeginFlush(IPin *iface)
766 ok(0, "Unexpected call.\n");
767 return E_NOTIMPL;
770 static HRESULT WINAPI pin_EndFlush(IPin *iface)
772 ok(0, "Unexpected call.\n");
773 return E_NOTIMPL;
776 static HRESULT WINAPI pin_NewSegment(IPin *iface, REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
778 ok(0, "Unexpected call.\n");
779 return E_NOTIMPL;
782 static const IPinVtbl pin_vtbl =
784 pin_QueryInterface,
785 pin_AddRef,
786 pin_Release,
787 pin_Connect,
788 pin_ReceiveConnection,
789 pin_Disconnect,
790 pin_ConnectedTo,
791 pin_ConnectionMediaType,
792 pin_QueryPinInfo,
793 pin_QueryDirection,
794 pin_QueryId,
795 pin_QueryAccept,
796 pin_EnumMediaTypes,
797 pin_QueryInternalConnections,
798 pin_EndOfStream,
799 pin_BeginFlush,
800 pin_EndFlush,
801 pin_NewSegment
804 static HRESULT WINAPI stream_QueryInterface(IAMMediaStream *iface, REFIID iid, void **out)
806 struct teststream *stream = impl_from_IAMMediaStream(iface);
808 if (winetest_debug > 1) trace("QueryInterface(%s)\n", wine_dbgstr_guid(iid));
810 if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IMediaStream) || IsEqualGUID(iid, &IID_IAMMediaStream))
812 IAMMediaStream_AddRef(iface);
813 *out = iface;
814 return S_OK;
816 else if (IsEqualGUID(iid, &IID_IPin))
818 IAMMediaStream_AddRef(iface);
819 *out = &stream->IPin_iface;
820 return S_OK;
823 ok(0, "Unexpected interface %s.\n", wine_dbgstr_guid(iid));
824 return E_NOINTERFACE;
827 static ULONG WINAPI stream_AddRef(IAMMediaStream *iface)
829 struct teststream *stream = impl_from_IAMMediaStream(iface);
830 return InterlockedIncrement(&stream->refcount);
833 static ULONG WINAPI stream_Release(IAMMediaStream *iface)
835 struct teststream *stream = impl_from_IAMMediaStream(iface);
836 return InterlockedDecrement(&stream->refcount);
839 static HRESULT WINAPI stream_GetMultiMediaStream(IAMMediaStream *iface, IMultiMediaStream **mmstream)
841 ok(0, "Unexpected call.\n");
842 return E_NOTIMPL;
845 static HRESULT WINAPI stream_GetInformation(IAMMediaStream *iface, MSPID *id, STREAM_TYPE *type)
847 struct teststream *stream = impl_from_IAMMediaStream(iface);
848 if (winetest_debug > 1) trace("GetInformation(%p, %p)\n", id, type);
849 if (id)
850 *id = stream->mspid;
851 if (type)
852 *type = STREAMTYPE_READ;
853 return S_OK;
856 static HRESULT WINAPI stream_SetSameFormat(IAMMediaStream *iface, IMediaStream *ref, DWORD flags)
858 ok(0, "Unexpected call.\n");
859 return E_NOTIMPL;
862 static HRESULT WINAPI stream_AllocateSample(IAMMediaStream *iface, DWORD flags, IStreamSample **sample)
864 ok(0, "Unexpected call.\n");
865 return E_NOTIMPL;
868 static HRESULT WINAPI stream_CreateSharedSample(IAMMediaStream *iface,
869 IStreamSample *existing, DWORD flags, IStreamSample **out)
871 ok(0, "Unexpected call.\n");
872 return E_NOTIMPL;
875 static HRESULT WINAPI stream_SendEndOfStream(IAMMediaStream *iface, DWORD flags)
877 ok(0, "Unexpected call.\n");
878 return E_NOTIMPL;
881 static HRESULT WINAPI stream_Initialize(IAMMediaStream *iface, IUnknown *source,
882 DWORD flags, REFMSPID id, const STREAM_TYPE type)
884 ok(0, "Unexpected call.\n");
885 return E_NOTIMPL;
888 static HRESULT WINAPI stream_SetState(IAMMediaStream *iface, FILTER_STATE state)
890 struct teststream *stream = impl_from_IAMMediaStream(iface);
891 if (winetest_debug > 1) trace("SetState(%#x)\n", state);
892 if (SUCCEEDED(stream->set_state_result))
893 stream->state = state;
894 return stream->set_state_result;
897 static HRESULT WINAPI stream_JoinAMMultiMediaStream(IAMMediaStream *iface, IAMMultiMediaStream *mmstream)
899 struct teststream *stream = impl_from_IAMMediaStream(iface);
900 if (winetest_debug > 1) trace("JoinAMMultiMediaStream(%p)\n", mmstream);
901 stream->mmstream = mmstream;
902 return S_OK;
905 static HRESULT WINAPI stream_JoinFilter(IAMMediaStream *iface, IMediaStreamFilter *filter)
907 struct teststream *stream = impl_from_IAMMediaStream(iface);
908 if (winetest_debug > 1) trace("JoinFilter(%p)\n", filter);
909 stream->filter = filter;
910 return S_OK;
913 static HRESULT WINAPI stream_JoinFilterGraph(IAMMediaStream *iface, IFilterGraph *graph)
915 struct teststream *stream = impl_from_IAMMediaStream(iface);
916 if (winetest_debug > 1) trace("JoinFilterGraph(%p)\n", graph);
917 stream->graph = graph;
918 return S_OK;
921 static const IAMMediaStreamVtbl stream_vtbl =
923 stream_QueryInterface,
924 stream_AddRef,
925 stream_Release,
926 stream_GetMultiMediaStream,
927 stream_GetInformation,
928 stream_SetSameFormat,
929 stream_AllocateSample,
930 stream_CreateSharedSample,
931 stream_SendEndOfStream,
932 stream_Initialize,
933 stream_SetState,
934 stream_JoinAMMultiMediaStream,
935 stream_JoinFilter,
936 stream_JoinFilterGraph,
939 static void teststream_init(struct teststream *stream)
941 memset(stream, 0, sizeof(*stream));
942 stream->IAMMediaStream_iface.lpVtbl = &stream_vtbl;
943 stream->IPin_iface.lpVtbl = &pin_vtbl;
944 stream->refcount = 1;
945 stream->mspid = test_mspid;
946 stream->set_state_result = S_OK;
949 #define check_enum_stream(a,b,c,d) check_enum_stream_(__LINE__,a,b,c,d)
950 static void check_enum_stream_(int line, IAMMultiMediaStream *mmstream,
951 IMediaStreamFilter *filter, LONG index, IMediaStream *expect)
953 IMediaStream *stream = NULL, *stream2 = NULL;
954 HRESULT hr;
956 hr = IAMMultiMediaStream_EnumMediaStreams(mmstream, index, &stream);
957 ok_(__FILE__, line)(hr == (expect ? S_OK : S_FALSE),
958 "IAMMultiMediaStream::EnumMediaStreams() returned %#x.\n", hr);
959 hr = IMediaStreamFilter_EnumMediaStreams(filter, index, &stream2);
960 ok_(__FILE__, line)(hr == (expect ? S_OK : S_FALSE),
961 "IMediaStreamFilter::EnumMediaStreams() returned %#x.\n", hr);
962 if (hr == S_OK)
964 ok_(__FILE__, line)(stream == expect, "Expected stream %p, got %p.\n", expect, stream);
965 ok_(__FILE__, line)(stream2 == expect, "Expected stream %p, got %p.\n", expect, stream2);
966 IMediaStream_Release(stream);
967 IMediaStream_Release(stream2);
971 struct testfilter
973 struct strmbase_filter filter;
974 struct strmbase_source source;
975 IMediaSeeking IMediaSeeking_iface;
976 LONGLONG current_position;
977 LONGLONG stop_position;
978 const AM_MEDIA_TYPE *preferred_mt;
979 HANDLE wait_state_event;
980 HRESULT get_duration_hr;
981 HRESULT get_stop_position_hr;
982 HRESULT set_positions_hr;
983 HRESULT init_stream_hr;
984 HRESULT cleanup_stream_hr;
985 HRESULT wait_state_hr;
986 HRESULT is_format_supported_hr;
989 static inline struct testfilter *impl_from_BaseFilter(struct strmbase_filter *iface)
991 return CONTAINING_RECORD(iface, struct testfilter, filter);
994 static struct strmbase_pin *testfilter_get_pin(struct strmbase_filter *iface, unsigned int index)
996 struct testfilter *filter = impl_from_BaseFilter(iface);
997 if (!index)
998 return &filter->source.pin;
999 return NULL;
1002 static void testfilter_destroy(struct strmbase_filter *iface)
1004 struct testfilter *filter = impl_from_BaseFilter(iface);
1005 CloseHandle(filter->wait_state_event);
1006 strmbase_source_cleanup(&filter->source);
1007 strmbase_filter_cleanup(&filter->filter);
1010 static HRESULT testfilter_init_stream(struct strmbase_filter *iface)
1012 struct testfilter *filter = impl_from_BaseFilter(iface);
1013 HRESULT hr;
1015 if (SUCCEEDED(filter->init_stream_hr) && filter->source.pin.peer)
1017 hr = IMemAllocator_Commit(filter->source.pAllocator);
1018 ok(hr == S_OK, "Got hr %#x.\n", hr);
1021 return filter->init_stream_hr;
1024 static HRESULT testfilter_cleanup_stream(struct strmbase_filter *iface)
1026 struct testfilter *filter = impl_from_BaseFilter(iface);
1027 HRESULT hr;
1029 if (SUCCEEDED(filter->cleanup_stream_hr) && filter->source.pin.peer)
1031 hr = IMemAllocator_Decommit(filter->source.pAllocator);
1032 ok(hr == S_OK, "Got hr %#x.\n", hr);
1035 return filter->cleanup_stream_hr;
1038 static HRESULT testfilter_wait_state(struct strmbase_filter *iface, DWORD timeout)
1040 struct testfilter *filter = impl_from_BaseFilter(iface);
1041 HRESULT hr;
1043 LeaveCriticalSection(&filter->filter.filter_cs);
1044 WaitForSingleObject(filter->wait_state_event, timeout);
1045 EnterCriticalSection(&filter->filter.filter_cs);
1047 hr = filter->wait_state_hr;
1049 return hr;
1052 static const struct strmbase_filter_ops testfilter_ops =
1054 .filter_get_pin = testfilter_get_pin,
1055 .filter_destroy = testfilter_destroy,
1056 .filter_init_stream = testfilter_init_stream,
1057 .filter_cleanup_stream = testfilter_cleanup_stream,
1058 .filter_wait_state = testfilter_wait_state,
1061 static inline struct testfilter *impl_from_base_pin(struct strmbase_pin *iface)
1063 return CONTAINING_RECORD(iface, struct testfilter, source.pin);
1066 static HRESULT testsource_get_media_type(struct strmbase_pin *iface, unsigned int index, AM_MEDIA_TYPE *mt)
1068 struct testfilter *filter = impl_from_base_pin(iface);
1070 if (index < 1 && filter->preferred_mt)
1071 return CopyMediaType(mt, filter->preferred_mt);
1073 return VFW_S_NO_MORE_ITEMS;
1076 static HRESULT testsource_query_interface(struct strmbase_pin *iface, REFIID iid, void **out)
1078 struct testfilter *filter = impl_from_base_pin(iface);
1080 if (IsEqualGUID(iid, &IID_IMediaSeeking) && filter->IMediaSeeking_iface.lpVtbl)
1081 *out = &filter->IMediaSeeking_iface;
1082 else
1083 return E_NOINTERFACE;
1085 IUnknown_AddRef((IUnknown *)*out);
1087 return S_OK;
1090 static HRESULT WINAPI testsource_DecideAllocator(struct strmbase_source *iface, IMemInputPin *pin, IMemAllocator **alloc)
1092 ALLOCATOR_PROPERTIES props = {0};
1093 HRESULT hr;
1095 /* AMDirectDrawStream tries to use it's custom allocator and
1096 * when it is able to do so it's behavior changes slightly
1097 * (e.g. it uses dynamic format change instead of reconnecting in SetFormat).
1098 * We don't yet implement the custom allocator so force the standard one for now. */
1099 hr = BaseOutputPinImpl_InitAllocator(iface, alloc);
1100 ok(hr == S_OK, "Got hr %#x.\n", hr);
1102 IMemInputPin_GetAllocatorRequirements(pin, &props);
1103 hr = iface->pFuncsTable->pfnDecideBufferSize(iface, *alloc, &props);
1104 ok(hr == S_OK, "Got hr %#x.\n", hr);
1106 return IMemInputPin_NotifyAllocator(pin, *alloc, FALSE);
1109 static HRESULT WINAPI testsource_DecideBufferSize(struct strmbase_source *iface,
1110 IMemAllocator *alloc, ALLOCATOR_PROPERTIES *requested)
1112 ALLOCATOR_PROPERTIES actual;
1114 if (!requested->cbAlign)
1115 requested->cbAlign = 1;
1117 if (requested->cbBuffer < 4096)
1118 requested->cbBuffer = 4096;
1120 if (!requested->cBuffers)
1121 requested->cBuffers = 2;
1123 return IMemAllocator_SetProperties(alloc, requested, &actual);
1126 static const struct strmbase_source_ops testsource_ops =
1128 .base.pin_get_media_type = testsource_get_media_type,
1129 .base.pin_query_interface = testsource_query_interface,
1130 .pfnAttemptConnection = BaseOutputPinImpl_AttemptConnection,
1131 .pfnDecideBufferSize = testsource_DecideBufferSize,
1132 .pfnDecideAllocator = testsource_DecideAllocator,
1135 static void testfilter_init(struct testfilter *filter)
1137 static const GUID clsid = {0xabacab};
1138 memset(filter, 0, sizeof(*filter));
1139 strmbase_filter_init(&filter->filter, NULL, &clsid, &testfilter_ops);
1140 strmbase_source_init(&filter->source, &filter->filter, L"", &testsource_ops);
1141 filter->stop_position = 0x8000000000000000ULL;
1142 filter->wait_state_event = CreateEventW(NULL, TRUE, TRUE, NULL);
1145 static inline struct testfilter *impl_from_IMediaSeeking(IMediaSeeking *iface)
1147 return CONTAINING_RECORD(iface, struct testfilter, IMediaSeeking_iface);
1150 static HRESULT WINAPI testsource_seeking_QueryInterface(IMediaSeeking *iface, REFIID iid, void **out)
1152 struct testfilter *filter = impl_from_IMediaSeeking(iface);
1153 return IBaseFilter_QueryInterface(&filter->filter.IBaseFilter_iface, iid, out);
1156 static ULONG WINAPI testsource_seeking_AddRef(IMediaSeeking *iface)
1158 struct testfilter *filter = impl_from_IMediaSeeking(iface);
1159 return IBaseFilter_AddRef(&filter->filter.IBaseFilter_iface);
1162 static ULONG WINAPI testsource_seeking_Release(IMediaSeeking *iface)
1164 struct testfilter *filter = impl_from_IMediaSeeking(iface);
1165 return IBaseFilter_Release(&filter->filter.IBaseFilter_iface);
1168 static HRESULT WINAPI testsource_seeking_GetCapabilities(IMediaSeeking *iface, DWORD *capabilities)
1170 return E_NOTIMPL;
1173 static HRESULT WINAPI testsource_seeking_CheckCapabilities(IMediaSeeking *iface, DWORD *capabilities)
1175 ok(0, "Unexpected call.\n");
1176 return E_NOTIMPL;
1179 static HRESULT WINAPI testsource_seeking_IsFormatSupported(IMediaSeeking *iface, const GUID *format)
1181 struct testfilter *filter = impl_from_IMediaSeeking(iface);
1183 ok(IsEqualGUID(format, &TIME_FORMAT_MEDIA_TIME),
1184 "Got format %s.\n", wine_dbgstr_guid(format));
1186 return filter->is_format_supported_hr;
1189 static HRESULT WINAPI testsource_seeking_QueryPreferredFormat(IMediaSeeking *iface, GUID *format)
1191 ok(0, "Unexpected call.\n");
1192 return E_NOTIMPL;
1195 static HRESULT WINAPI testsource_seeking_GetTimeFormat(IMediaSeeking *iface, GUID *format)
1197 ok(0, "Unexpected call.\n");
1198 return E_NOTIMPL;
1201 static HRESULT WINAPI testsource_seeking_IsUsingTimeFormat(IMediaSeeking *iface, const GUID *format)
1203 return E_NOTIMPL;
1206 static HRESULT WINAPI testsource_seeking_SetTimeFormat(IMediaSeeking *iface, const GUID *format)
1208 ok(0, "Unexpected call.\n");
1209 return E_NOTIMPL;
1212 static HRESULT WINAPI testsource_seeking_GetDuration(IMediaSeeking *iface, LONGLONG *duration)
1214 struct testfilter *filter = impl_from_IMediaSeeking(iface);
1216 if (SUCCEEDED(filter->get_duration_hr))
1217 *duration = 0x8000000000000000ULL;
1219 return filter->get_duration_hr;
1222 static HRESULT WINAPI testsource_seeking_GetStopPosition(IMediaSeeking *iface, LONGLONG *stop)
1224 struct testfilter *filter = impl_from_IMediaSeeking(iface);
1226 if (SUCCEEDED(filter->get_stop_position_hr))
1227 *stop = 0x8000000000000000ULL;
1229 return filter->get_stop_position_hr;
1232 static HRESULT WINAPI testsource_seeking_GetCurrentPosition(IMediaSeeking *iface, LONGLONG *current)
1234 ok(0, "Unexpected call.\n");
1235 return E_NOTIMPL;
1238 static HRESULT WINAPI testsource_seeking_ConvertTimeFormat(IMediaSeeking *iface, LONGLONG *target,
1239 const GUID *target_format, LONGLONG source, const GUID *source_format)
1241 ok(0, "Unexpected call.\n");
1242 return E_NOTIMPL;
1245 static HRESULT WINAPI testsource_seeking_SetPositions(IMediaSeeking *iface, LONGLONG *current_ptr, DWORD current_flags,
1246 LONGLONG *stop_ptr, DWORD stop_flags)
1248 struct testfilter *filter = impl_from_IMediaSeeking(iface);
1250 if (SUCCEEDED(filter->set_positions_hr))
1252 if (current_ptr)
1253 filter->current_position = *current_ptr;
1255 if (stop_ptr)
1256 filter->stop_position = *stop_ptr;
1259 return filter->set_positions_hr;
1262 static HRESULT WINAPI testsource_seeking_GetPositions(IMediaSeeking *iface, LONGLONG *current, LONGLONG *stop)
1264 ok(0, "Unexpected call.\n");
1265 return E_NOTIMPL;
1268 static HRESULT WINAPI testsource_seeking_GetAvailable(IMediaSeeking *iface, LONGLONG *earliest, LONGLONG *latest)
1270 ok(0, "Unexpected call.\n");
1271 return E_NOTIMPL;
1274 static HRESULT WINAPI testsource_seeking_SetRate(IMediaSeeking *iface, double rate)
1276 ok(0, "Unexpected call.\n");
1277 return E_NOTIMPL;
1280 static HRESULT WINAPI testsource_seeking_GetRate(IMediaSeeking *iface, double *rate)
1282 ok(0, "Unexpected call.\n");
1283 return E_NOTIMPL;
1286 static HRESULT WINAPI testsource_seeking_GetPreroll(IMediaSeeking *iface, LONGLONG *preroll)
1288 ok(0, "Unexpected call.\n");
1289 return E_NOTIMPL;
1292 static const IMediaSeekingVtbl testsource_seeking_vtbl =
1294 testsource_seeking_QueryInterface,
1295 testsource_seeking_AddRef,
1296 testsource_seeking_Release,
1297 testsource_seeking_GetCapabilities,
1298 testsource_seeking_CheckCapabilities,
1299 testsource_seeking_IsFormatSupported,
1300 testsource_seeking_QueryPreferredFormat,
1301 testsource_seeking_GetTimeFormat,
1302 testsource_seeking_IsUsingTimeFormat,
1303 testsource_seeking_SetTimeFormat,
1304 testsource_seeking_GetDuration,
1305 testsource_seeking_GetStopPosition,
1306 testsource_seeking_GetCurrentPosition,
1307 testsource_seeking_ConvertTimeFormat,
1308 testsource_seeking_SetPositions,
1309 testsource_seeking_GetPositions,
1310 testsource_seeking_GetAvailable,
1311 testsource_seeking_SetRate,
1312 testsource_seeking_GetRate,
1313 testsource_seeking_GetPreroll,
1316 #define check_get_stream(a,b,c,d) check_get_stream_(__LINE__,a,b,c,d)
1317 static void check_get_stream_(int line, IAMMultiMediaStream *mmstream,
1318 IMediaStreamFilter *filter, const GUID *mspid, IMediaStream *expect)
1320 IMediaStream *stream = NULL, *stream2 = NULL;
1321 HRESULT hr;
1323 hr = IAMMultiMediaStream_GetMediaStream(mmstream, mspid, &stream);
1324 ok_(__FILE__, line)(hr == (expect ? S_OK : MS_E_NOSTREAM),
1325 "IAMMultiMediaStream::GetMediaStream() returned %#x.\n", hr);
1326 hr = IMediaStreamFilter_GetMediaStream(filter, mspid, &stream2);
1327 ok_(__FILE__, line)(hr == (expect ? S_OK : MS_E_NOSTREAM),
1328 "IMediaStreamFilter::GetMediaStream() returned %#x.\n", hr);
1329 if (hr == S_OK)
1331 ok_(__FILE__, line)(stream == expect, "Expected stream %p, got %p.\n", expect, stream);
1332 ok_(__FILE__, line)(stream2 == expect, "Expected stream %p, got %p.\n", expect, stream2);
1335 if (stream) IMediaStream_Release(stream);
1336 if (stream2) IMediaStream_Release(stream2);
1339 static void test_add_stream(void)
1341 IAMMultiMediaStream *mmstream = create_ammultimediastream();
1342 IMediaStream *video_stream, *audio_stream, *stream;
1343 IDirectDrawMediaStream *ddraw_stream;
1344 IMediaStreamFilter *stream_filter;
1345 struct teststream teststream;
1346 IDirectDraw *ddraw, *ddraw2;
1347 IEnumFilters *enum_filters;
1348 IBaseFilter *filters[3];
1349 IGraphBuilder *graph;
1350 FILTER_INFO info;
1351 ULONG ref, count;
1352 CLSID clsid;
1353 HRESULT hr;
1355 teststream_init(&teststream);
1357 hr = IAMMultiMediaStream_GetFilter(mmstream, &stream_filter);
1358 ok(hr == S_OK, "Got hr %#x.\n", hr);
1360 hr = IAMMultiMediaStream_EnumMediaStreams(mmstream, 0, NULL);
1361 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1362 hr = IMediaStreamFilter_EnumMediaStreams(stream_filter, 0, NULL);
1363 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1365 hr = IAMMultiMediaStream_GetMediaStream(mmstream, &MSPID_PrimaryAudio, NULL);
1366 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
1367 hr = IMediaStreamFilter_GetMediaStream(stream_filter, &MSPID_PrimaryAudio, NULL);
1368 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
1369 hr = IAMMultiMediaStream_GetMediaStream(mmstream, &MSPID_PrimaryVideo, NULL);
1370 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
1371 hr = IMediaStreamFilter_GetMediaStream(stream_filter, &MSPID_PrimaryVideo, NULL);
1372 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
1374 check_enum_stream(mmstream, stream_filter, 0, NULL);
1376 check_get_stream(mmstream, stream_filter, NULL, NULL);
1377 check_get_stream(mmstream, stream_filter, &MSPID_PrimaryAudio, NULL);
1378 check_get_stream(mmstream, stream_filter, &MSPID_PrimaryVideo, NULL);
1379 check_get_stream(mmstream, stream_filter, &test_mspid, NULL);
1381 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &test_mspid, 0, &stream);
1382 ok(hr == MS_E_PURPOSEID, "Got hr %#x.\n", hr);
1384 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &video_stream);
1385 ok(hr == S_OK, "Got hr %#x.\n", hr);
1387 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
1388 ok(hr == MS_E_PURPOSEID, "Got hr %#x.\n", hr);
1390 hr = IAMMultiMediaStream_EnumMediaStreams(mmstream, 0, NULL);
1391 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
1392 hr = IMediaStreamFilter_EnumMediaStreams(stream_filter, 0, NULL);
1393 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
1394 hr = IAMMultiMediaStream_EnumMediaStreams(mmstream, 1, NULL);
1395 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1396 hr = IMediaStreamFilter_EnumMediaStreams(stream_filter, 1, NULL);
1397 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1399 check_enum_stream(mmstream, stream_filter, 0, video_stream);
1400 check_enum_stream(mmstream, stream_filter, 1, NULL);
1402 check_get_stream(mmstream, stream_filter, &MSPID_PrimaryVideo, video_stream);
1403 check_get_stream(mmstream, stream_filter, &MSPID_PrimaryAudio, NULL);
1404 check_get_stream(mmstream, stream_filter, &test_mspid, NULL);
1406 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &audio_stream);
1407 ok(hr == S_OK, "Got hr %#x.\n", hr);
1409 check_enum_stream(mmstream, stream_filter, 0, video_stream);
1410 check_enum_stream(mmstream, stream_filter, 1, audio_stream);
1411 check_enum_stream(mmstream, stream_filter, 2, NULL);
1413 check_get_stream(mmstream, stream_filter, &MSPID_PrimaryVideo, video_stream);
1414 check_get_stream(mmstream, stream_filter, &MSPID_PrimaryAudio, audio_stream);
1415 check_get_stream(mmstream, stream_filter, &test_mspid, NULL);
1417 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)&teststream, &IID_IUnknown, 0, &stream);
1418 ok(hr == MS_E_PURPOSEID, "Got hr %#x.\n", hr);
1420 hr = IMediaStreamFilter_QueryFilterInfo(stream_filter, &info);
1421 ok(hr == S_OK, "Got hr %#x.\n", hr);
1423 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)&teststream, &test_mspid, 0, &stream);
1424 ok(hr == S_OK, "Got hr %#x.\n", hr);
1425 ok(stream == (IMediaStream *)&teststream, "Streams didn't match.\n");
1426 IMediaStream_Release(stream);
1427 ok(teststream.mmstream == mmstream, "IAMMultiMediaStream objects didn't match.\n");
1428 ok(teststream.filter == stream_filter, "IMediaStreamFilter objects didn't match.\n");
1429 ok(teststream.graph == info.pGraph, "IFilterGraph objects didn't match.\n");
1431 IFilterGraph_Release(info.pGraph);
1433 check_enum_stream(mmstream, stream_filter, 0, video_stream);
1434 check_enum_stream(mmstream, stream_filter, 1, audio_stream);
1435 check_enum_stream(mmstream, stream_filter, 2, (IMediaStream *)&teststream);
1436 check_enum_stream(mmstream, stream_filter, 3, NULL);
1438 check_get_stream(mmstream, stream_filter, &MSPID_PrimaryVideo, video_stream);
1439 check_get_stream(mmstream, stream_filter, &MSPID_PrimaryAudio, audio_stream);
1440 check_get_stream(mmstream, stream_filter, &test_mspid, (IMediaStream *)&teststream);
1442 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
1443 ok(hr == MS_E_PURPOSEID, "Got hr %#x.\n", hr);
1445 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
1446 ok(hr == S_OK, "Got hr %#x.\n", hr);
1447 ok(!!graph, "Expected a non-NULL graph.\n");
1449 hr = IGraphBuilder_EnumFilters(graph, &enum_filters);
1450 ok(hr == S_OK, "Got hr %#x.\n", hr);
1451 hr = IEnumFilters_Next(enum_filters, 3, filters, &count);
1452 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1453 ok(count == 1, "Got count %u.\n", count);
1454 ok(filters[0] == (IBaseFilter *)stream_filter,
1455 "Expected filter %p, got %p.\n", stream_filter, filters[0]);
1456 IBaseFilter_Release(filters[0]);
1457 IEnumFilters_Release(enum_filters);
1458 IGraphBuilder_Release(graph);
1460 IMediaStreamFilter_Release(stream_filter);
1461 ref = IAMMultiMediaStream_Release(mmstream);
1462 ok(!ref, "Got outstanding refcount %d.\n", ref);
1463 ref = IMediaStream_Release(video_stream);
1464 ok(!ref, "Got outstanding refcount %d.\n", ref);
1465 ref = IMediaStream_Release(audio_stream);
1466 ok(!ref, "Got outstanding refcount %d.\n", ref);
1467 ok(teststream.refcount == 1, "Got outstanding refcount %d.\n", teststream.refcount);
1469 /* The return parameter is optional. */
1471 mmstream = create_ammultimediastream();
1473 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, NULL);
1474 ok(hr == S_OK, "Got hr %#x.\n", hr);
1476 hr = IAMMultiMediaStream_GetMediaStream(mmstream, &MSPID_PrimaryVideo, &stream);
1477 ok(hr == S_OK, "Got hr %#x.\n", hr);
1478 IMediaStream_Release(stream);
1480 ref = IAMMultiMediaStream_Release(mmstream);
1481 ok(!ref, "Got outstanding refcount %d.\n", ref);
1483 /* Test supplying a DirectDraw object with the primary video stream. */
1485 hr = DirectDrawCreate(NULL, &ddraw, NULL);
1486 ok(hr == DD_OK, "Got hr %#x.\n", hr);
1487 mmstream = create_ammultimediastream();
1489 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)ddraw, &MSPID_PrimaryVideo, 0, &video_stream);
1490 ok(hr == S_OK, "Got hr %#x.\n", hr);
1492 hr = IMediaStream_QueryInterface(video_stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
1493 ok(hr == S_OK, "Got hr %#x.\n", hr);
1494 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw2);
1495 ok(hr == S_OK, "Got hr %#x.\n", hr);
1496 ok(ddraw2 == ddraw, "Expected IDirectDraw %p, got %p.\n", ddraw, ddraw2);
1497 IDirectDraw_Release(ddraw2);
1498 IDirectDrawMediaStream_Release(ddraw_stream);
1500 ref = IAMMultiMediaStream_Release(mmstream);
1501 ok(!ref, "Got outstanding refcount %d.\n", ref);
1502 ref = IMediaStream_Release(video_stream);
1503 ok(!ref, "Got outstanding refcount %d.\n", ref);
1504 ref = IDirectDraw_Release(ddraw);
1505 ok(!ref, "Got outstanding refcount %d.\n", ref);
1507 mmstream = create_ammultimediastream();
1509 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &video_stream);
1510 ok(hr == S_OK, "Got hr %#x.\n", hr);
1512 hr = IMediaStream_QueryInterface(video_stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
1513 ok(hr == S_OK, "Got hr %#x.\n", hr);
1514 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw);
1515 ok(hr == S_OK, "Got hr %#x.\n", hr);
1516 ok(!!ddraw, "Expected a non-NULL IDirectDraw.\n");
1517 IDirectDraw_Release(ddraw);
1518 IDirectDrawMediaStream_Release(ddraw_stream);
1520 ref = IAMMultiMediaStream_Release(mmstream);
1521 ok(!ref, "Got outstanding refcount %d.\n", ref);
1522 ref = IMediaStream_Release(video_stream);
1523 ok(!ref, "Got outstanding refcount %d.\n", ref);
1525 /* Test the AMMSF_ADDDEFAULTRENDERER flag. No stream is added; however, a
1526 * new filter will be added to the graph. */
1528 mmstream = create_ammultimediastream();
1529 hr = IAMMultiMediaStream_GetFilter(mmstream, &stream_filter);
1530 ok(hr == S_OK, "Got hr %#x.\n", hr);
1532 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo,
1533 AMMSF_ADDDEFAULTRENDERER, &video_stream);
1534 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
1536 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo,
1537 AMMSF_ADDDEFAULTRENDERER, NULL);
1538 ok(hr == MS_E_PURPOSEID, "Got hr %#x.\n", hr);
1540 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio,
1541 AMMSF_ADDDEFAULTRENDERER, &audio_stream);
1542 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
1544 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio,
1545 AMMSF_ADDDEFAULTRENDERER, NULL);
1546 ok(hr == S_OK || hr == VFW_E_NO_AUDIO_HARDWARE, "Got hr %#x.\n", hr);
1548 check_enum_stream(mmstream, stream_filter, 0, NULL);
1550 check_get_stream(mmstream, stream_filter, &MSPID_PrimaryAudio, NULL);
1551 check_get_stream(mmstream, stream_filter, &MSPID_PrimaryVideo, NULL);
1553 if (hr == S_OK)
1555 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
1556 ok(hr == S_OK, "Got hr %#x.\n", hr);
1557 ok(!!graph, "Got graph %p.\n", graph);
1558 hr = IGraphBuilder_EnumFilters(graph, &enum_filters);
1559 ok(hr == S_OK, "Got hr %#x.\n", hr);
1560 hr = IEnumFilters_Next(enum_filters, 3, filters, &count);
1561 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1562 ok(count == 2, "Got count %u.\n", count);
1563 ok(filters[1] == (IBaseFilter *)stream_filter,
1564 "Expected filter %p, got %p.\n", stream_filter, filters[1]);
1565 hr = IBaseFilter_GetClassID(filters[0], &clsid);
1566 ok(hr == S_OK, "Got hr %#x.\n", hr);
1567 ok(IsEqualGUID(&clsid, &CLSID_DSoundRender), "Got unexpected filter %s.\n", wine_dbgstr_guid(&clsid));
1568 IBaseFilter_Release(filters[0]);
1569 IBaseFilter_Release(filters[1]);
1570 IEnumFilters_Release(enum_filters);
1571 IGraphBuilder_Release(graph);
1574 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &test_mspid,
1575 AMMSF_ADDDEFAULTRENDERER, NULL);
1576 ok(hr == MS_E_PURPOSEID, "Got hr %#x.\n", hr);
1577 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &test_mspid,
1578 AMMSF_ADDDEFAULTRENDERER, &audio_stream);
1579 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
1581 ref = IAMMultiMediaStream_Release(mmstream);
1582 ok(!ref, "Got outstanding refcount %d.\n", ref);
1583 ref = IMediaStreamFilter_Release(stream_filter);
1584 ok(!ref, "Got outstanding refcount %d.\n", ref);
1587 static void test_media_streams(void)
1589 IAMMultiMediaStream *pams;
1590 HRESULT hr;
1591 IMediaStream *video_stream = NULL;
1592 IMediaStream *audio_stream = NULL;
1593 IMediaStreamFilter* media_stream_filter = NULL;
1595 if (!(pams = create_ammultimediastream()))
1596 return;
1598 hr = IAMMultiMediaStream_Initialize(pams, STREAMTYPE_READ, 0, NULL);
1599 ok(hr == S_OK, "IAMMultiMediaStream_Initialize returned: %x\n", hr);
1601 /* Retrieve media stream filter */
1602 hr = IAMMultiMediaStream_GetFilter(pams, NULL);
1603 ok(hr == E_POINTER, "IAMMultiMediaStream_GetFilter returned: %x\n", hr);
1604 hr = IAMMultiMediaStream_GetFilter(pams, &media_stream_filter);
1605 ok(hr == S_OK, "IAMMultiMediaStream_GetFilter returned: %x\n", hr);
1607 hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &MSPID_PrimaryVideo, 0, NULL);
1608 ok(hr == S_OK, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
1609 hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryVideo, &video_stream);
1610 ok(hr == S_OK, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
1612 /* Check interfaces and samples for video */
1613 if (video_stream)
1615 IAMMediaStream* am_media_stream;
1616 IMultiMediaStream *multi_media_stream;
1617 IPin *pin = NULL;
1618 IAudioMediaStream* audio_media_stream;
1619 IDirectDrawMediaStream *ddraw_stream = NULL;
1620 IDirectDrawStreamSample *ddraw_sample = NULL;
1622 hr = IMediaStream_QueryInterface(video_stream, &IID_IAMMediaStream, (LPVOID*)&am_media_stream);
1623 ok(hr == S_OK, "IMediaStream_QueryInterface returned: %x\n", hr);
1624 ok((void*)am_media_stream == (void*)video_stream, "Not same interface, got %p expected %p\n", am_media_stream, video_stream);
1626 hr = IAMMediaStream_GetMultiMediaStream(am_media_stream, NULL);
1627 ok(hr == E_POINTER, "Expected E_POINTER, got %x\n", hr);
1629 multi_media_stream = (void *)0xdeadbeef;
1630 hr = IAMMediaStream_GetMultiMediaStream(am_media_stream, &multi_media_stream);
1631 ok(hr == S_OK, "IAMMediaStream_GetMultiMediaStream returned: %x\n", hr);
1632 ok((void *)multi_media_stream == (void *)pams, "Expected %p, got %p\n", pams, multi_media_stream);
1633 IMultiMediaStream_Release(multi_media_stream);
1635 IAMMediaStream_Release(am_media_stream);
1637 hr = IMediaStream_QueryInterface(video_stream, &IID_IPin, (void **)&pin);
1638 ok(hr == S_OK, "IMediaStream_QueryInterface returned: %x\n", hr);
1640 IPin_Release(pin);
1642 hr = IMediaStream_QueryInterface(video_stream, &IID_IAudioMediaStream, (LPVOID*)&audio_media_stream);
1643 ok(hr == E_NOINTERFACE, "IMediaStream_QueryInterface returned: %x\n", hr);
1645 hr = IMediaStream_QueryInterface(video_stream, &IID_IDirectDrawMediaStream, (LPVOID*)&ddraw_stream);
1646 ok(hr == S_OK, "IMediaStream_QueryInterface returned: %x\n", hr);
1648 if (SUCCEEDED(hr))
1650 DDSURFACEDESC current_format, desired_format;
1651 IDirectDrawPalette *palette;
1652 DWORD flags;
1654 hr = IDirectDrawMediaStream_GetFormat(ddraw_stream, &current_format, &palette, &desired_format, &flags);
1655 ok(hr == MS_E_NOSTREAM, "IDirectDrawoMediaStream_GetFormat returned: %x\n", hr);
1657 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &ddraw_sample);
1658 ok(hr == S_OK, "IDirectDrawMediaStream_CreateSample returned: %x\n", hr);
1660 hr = IDirectDrawMediaStream_GetMultiMediaStream(ddraw_stream, NULL);
1661 ok(hr == E_POINTER, "Expected E_POINTER, got %x\n", hr);
1663 multi_media_stream = (void *)0xdeadbeef;
1664 hr = IDirectDrawMediaStream_GetMultiMediaStream(ddraw_stream, &multi_media_stream);
1665 ok(hr == S_OK, "IDirectDrawMediaStream_GetMultiMediaStream returned: %x\n", hr);
1666 ok((void *)multi_media_stream == (void *)pams, "Expected %p, got %p\n", pams, multi_media_stream);
1667 IMultiMediaStream_Release(multi_media_stream);
1670 if (ddraw_sample)
1671 IDirectDrawStreamSample_Release(ddraw_sample);
1672 if (ddraw_stream)
1673 IDirectDrawMediaStream_Release(ddraw_stream);
1676 hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &MSPID_PrimaryAudio, 0, NULL);
1677 ok(hr == S_OK, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
1678 hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryAudio, &audio_stream);
1679 ok(hr == S_OK, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
1681 /* Check interfaces and samples for audio */
1682 if (audio_stream)
1684 IAMMediaStream* am_media_stream;
1685 IMultiMediaStream *multi_media_stream;
1686 IPin *pin = NULL;
1687 IDirectDrawMediaStream* ddraw_stream = NULL;
1688 IAudioMediaStream* audio_media_stream = NULL;
1689 IAudioStreamSample *audio_sample = NULL;
1691 hr = IMediaStream_QueryInterface(audio_stream, &IID_IAMMediaStream, (LPVOID*)&am_media_stream);
1692 ok(hr == S_OK, "IMediaStream_QueryInterface returned: %x\n", hr);
1693 ok((void*)am_media_stream == (void*)audio_stream, "Not same interface, got %p expected %p\n", am_media_stream, audio_stream);
1695 hr = IAMMediaStream_GetMultiMediaStream(am_media_stream, NULL);
1696 ok(hr == E_POINTER, "Expected E_POINTER, got %x\n", hr);
1698 multi_media_stream = (void *)0xdeadbeef;
1699 hr = IAMMediaStream_GetMultiMediaStream(am_media_stream, &multi_media_stream);
1700 ok(hr == S_OK, "IAMMediaStream_GetMultiMediaStream returned: %x\n", hr);
1701 ok((void *)multi_media_stream == (void *)pams, "Expected %p, got %p\n", pams, multi_media_stream);
1702 IMultiMediaStream_Release(multi_media_stream);
1704 IAMMediaStream_Release(am_media_stream);
1706 hr = IMediaStream_QueryInterface(audio_stream, &IID_IPin, (void **)&pin);
1707 ok(hr == S_OK, "IMediaStream_QueryInterface returned: %x\n", hr);
1709 IPin_Release(pin);
1711 hr = IMediaStream_QueryInterface(audio_stream, &IID_IDirectDrawMediaStream, (LPVOID*)&ddraw_stream);
1712 ok(hr == E_NOINTERFACE, "IMediaStream_QueryInterface returned: %x\n", hr);
1714 hr = IMediaStream_QueryInterface(audio_stream, &IID_IAudioMediaStream, (LPVOID*)&audio_media_stream);
1715 ok(hr == S_OK, "IMediaStream_QueryInterface returned: %x\n", hr);
1717 if (SUCCEEDED(hr))
1719 IAudioData* audio_data = NULL;
1721 hr = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER, &IID_IAudioData, (void **)&audio_data);
1722 ok(hr == S_OK, "CoCreateInstance returned: %x\n", hr);
1724 hr = IAudioMediaStream_CreateSample(audio_media_stream, NULL, 0, &audio_sample);
1725 ok(hr == E_POINTER, "IAudioMediaStream_CreateSample returned: %x\n", hr);
1727 EXPECT_REF(audio_stream, 3);
1728 EXPECT_REF(audio_data, 1);
1729 hr = IAudioMediaStream_CreateSample(audio_media_stream, audio_data, 0, &audio_sample);
1730 ok(hr == S_OK, "IAudioMediaStream_CreateSample returned: %x\n", hr);
1731 EXPECT_REF(audio_stream, 4);
1732 EXPECT_REF(audio_data, 2);
1734 hr = IAudioMediaStream_GetMultiMediaStream(audio_media_stream, NULL);
1735 ok(hr == E_POINTER, "Expected E_POINTER, got %x\n", hr);
1737 multi_media_stream = (void *)0xdeadbeef;
1738 hr = IAudioMediaStream_GetMultiMediaStream(audio_media_stream, &multi_media_stream);
1739 ok(hr == S_OK, "IAudioMediaStream_GetMultiMediaStream returned: %x\n", hr);
1740 ok((void *)multi_media_stream == (void *)pams, "Expected %p, got %p\n", pams, multi_media_stream);
1741 IMultiMediaStream_Release(multi_media_stream);
1743 if (audio_data)
1744 IAudioData_Release(audio_data);
1745 if (audio_sample)
1746 IAudioStreamSample_Release(audio_sample);
1747 if (audio_media_stream)
1748 IAudioMediaStream_Release(audio_media_stream);
1752 if (media_stream_filter)
1754 IEnumPins *enum_pins;
1756 hr = IMediaStreamFilter_EnumPins(media_stream_filter, &enum_pins);
1757 ok(hr == S_OK, "IBaseFilter_EnumPins returned: %x\n", hr);
1758 if (hr == S_OK)
1760 IPin* pins[3] = { NULL, NULL, NULL };
1761 ULONG nb_pins;
1762 ULONG expected_nb_pins = audio_stream ? 2 : 1;
1763 int i;
1765 hr = IEnumPins_Next(enum_pins, 3, pins, &nb_pins);
1766 ok(SUCCEEDED(hr), "IEnumPins_Next returned: %x\n", hr);
1767 ok(nb_pins == expected_nb_pins, "Number of pins is %u instead of %u\n", nb_pins, expected_nb_pins);
1768 for (i = 0; i < min(nb_pins, expected_nb_pins); i++)
1770 IPin* pin;
1772 hr = IPin_ConnectedTo(pins[i], &pin);
1773 ok(hr == VFW_E_NOT_CONNECTED, "IPin_ConnectedTo returned: %x\n", hr);
1774 IPin_Release(pins[i]);
1776 IEnumPins_Release(enum_pins);
1780 /* Test open file with no filename */
1781 hr = IAMMultiMediaStream_OpenFile(pams, NULL, 0);
1782 ok(hr == E_POINTER, "IAMMultiMediaStream_OpenFile returned %x instead of %x\n", hr, E_POINTER);
1784 if (video_stream)
1785 IMediaStream_Release(video_stream);
1786 if (audio_stream)
1787 IMediaStream_Release(audio_stream);
1788 if (media_stream_filter)
1789 IMediaStreamFilter_Release(media_stream_filter);
1791 IAMMultiMediaStream_Release(pams);
1794 static void test_enum_pins(void)
1796 IAMMultiMediaStream *mmstream = create_ammultimediastream();
1797 IMediaStreamFilter *filter;
1798 IEnumPins *enum1, *enum2;
1799 IMediaStream *stream;
1800 IPin *pins[3], *pin;
1801 ULONG ref, count;
1802 HRESULT hr;
1804 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
1805 ok(hr == S_OK, "Got hr %#x.\n", hr);
1807 ref = get_refcount(filter);
1808 ok(ref == 3, "Got unexpected refcount %d.\n", ref);
1810 hr = IMediaStreamFilter_EnumPins(filter, NULL);
1811 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
1813 hr = IMediaStreamFilter_EnumPins(filter, &enum1);
1814 ok(hr == S_OK, "Got hr %#x.\n", hr);
1815 ref = get_refcount(filter);
1816 ok(ref == 3, "Got unexpected refcount %d.\n", ref);
1817 ref = get_refcount(enum1);
1818 ok(ref == 1, "Got unexpected refcount %d.\n", ref);
1820 hr = IEnumPins_Next(enum1, 1, NULL, NULL);
1821 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
1823 hr = IEnumPins_Next(enum1, 1, pins, NULL);
1824 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1826 hr = IEnumPins_Reset(enum1);
1827 ok(hr == S_OK, "Got hr %#x.\n", hr);
1829 hr = IEnumPins_Skip(enum1, 0);
1830 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1832 hr = IEnumPins_Skip(enum1, 1);
1833 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1835 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
1836 ok(hr == S_OK, "Got hr %#x.\n", hr);
1837 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
1838 ok(hr == S_OK, "Got hr %#x.\n", hr);
1840 /* Reset() isn't enough; we have to call EnumPins() again to see the updated
1841 * pin count. */
1842 hr = IEnumPins_Reset(enum1);
1843 ok(hr == S_OK, "Got hr %#x.\n", hr);
1845 hr = IEnumPins_Next(enum1, 1, pins, NULL);
1846 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1848 IEnumPins_Release(enum1);
1850 hr = IMediaStreamFilter_EnumPins(filter, &enum1);
1851 ok(hr == S_OK, "Got hr %#x.\n", hr);
1853 ref = get_refcount(filter);
1854 ok(ref == 4, "Got unexpected refcount %d.\n", ref);
1855 ref = get_refcount(enum1);
1856 ok(ref == 1, "Got unexpected refcount %d.\n", ref);
1857 ref = get_refcount(pin);
1858 ok(ref == 4, "Got unexpected refcount %d.\n", ref);
1860 hr = IEnumPins_Next(enum1, 1, pins, NULL);
1861 ok(hr == S_OK, "Got hr %#x.\n", hr);
1862 ok(pins[0] == pin, "Expected pin %p, got %p.\n", pin, pins[0]);
1863 ref = get_refcount(filter);
1864 ok(ref == 4, "Got unexpected refcount %d.\n", ref);
1865 ref = get_refcount(enum1);
1866 ok(ref == 1, "Got unexpected refcount %d.\n", ref);
1867 ref = get_refcount(pin);
1868 ok(ref == 5, "Got unexpected refcount %d.\n", ref);
1869 IPin_Release(pins[0]);
1871 hr = IEnumPins_Next(enum1, 1, pins, NULL);
1872 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1874 hr = IEnumPins_Reset(enum1);
1875 ok(hr == S_OK, "Got hr %#x.\n", hr);
1877 hr = IEnumPins_Next(enum1, 1, pins, &count);
1878 ok(hr == S_OK, "Got hr %#x.\n", hr);
1879 ok(count == 1, "Got count %u.\n", count);
1880 ok(pins[0] == pin, "Expected pin %p, got %p.\n", pin, pins[0]);
1881 IPin_Release(pins[0]);
1883 hr = IEnumPins_Reset(enum1);
1884 ok(hr == S_OK, "Got hr %#x.\n", hr);
1886 hr = IEnumPins_Next(enum1, 2, pins, NULL);
1887 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
1889 hr = IEnumPins_Next(enum1, 2, pins, &count);
1890 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1891 ok(count == 1, "Got count %u.\n", count);
1892 ok(pins[0] == pin, "Expected pin %p, got %p.\n", pin, pins[0]);
1893 IPin_Release(pins[0]);
1895 hr = IEnumPins_Reset(enum1);
1896 ok(hr == S_OK, "Got hr %#x.\n", hr);
1898 hr = IEnumPins_Clone(enum1, &enum2);
1899 ok(hr == S_OK, "Got hr %#x.\n", hr);
1901 hr = IEnumPins_Skip(enum1, 0);
1902 ok(hr == S_OK, "Got hr %#x.\n", hr);
1904 hr = IEnumPins_Skip(enum1, 1);
1905 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1907 hr = IEnumPins_Next(enum1, 1, pins, NULL);
1908 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
1910 hr = IEnumPins_Next(enum2, 1, pins, NULL);
1911 ok(hr == S_OK, "Got hr %#x.\n", hr);
1912 ok(pins[0] == pin, "Expected pin %p, got %p.\n", pin, pins[0]);
1913 IPin_Release(pins[0]);
1915 IEnumPins_Release(enum2);
1916 IEnumPins_Release(enum1);
1918 IMediaStreamFilter_Release(filter);
1919 ref = IAMMultiMediaStream_Release(mmstream);
1920 ok(!ref, "Got outstanding refcount %d.\n", ref);
1921 IMediaStream_Release(stream);
1922 ref = IPin_Release(pin);
1923 ok(!ref, "Got outstanding refcount %d.\n", ref);
1926 static void test_find_pin(void)
1928 IAMMultiMediaStream *mmstream = create_ammultimediastream();
1929 IMediaStreamFilter *filter;
1930 IMediaStream *stream;
1931 IPin *pin, *pin2;
1932 HRESULT hr;
1933 ULONG ref;
1935 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
1936 ok(hr == S_OK, "Got hr %#x.\n", hr);
1938 hr = IMediaStreamFilter_FindPin(filter, primary_video_sink_id, &pin2);
1939 ok(hr == VFW_E_NOT_FOUND, "Got hr %#x.\n", hr);
1941 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
1942 ok(hr == S_OK, "Got hr %#x.\n", hr);
1943 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
1944 ok(hr == S_OK, "Got hr %#x.\n", hr);
1946 hr = IMediaStreamFilter_FindPin(filter, primary_video_sink_id, &pin2);
1947 ok(hr == S_OK, "Got hr %#x.\n", hr);
1948 ok(pin2 == pin, "Expected pin %p, got %p.\n", pin, pin2);
1950 IPin_Release(pin2);
1951 IPin_Release(pin);
1952 IMediaStream_Release(stream);
1953 IMediaStreamFilter_Release(filter);
1954 ref = IAMMultiMediaStream_Release(mmstream);
1955 ok(!ref, "Got outstanding refcount %d.\n", ref);
1958 static void test_pin_info(void)
1960 IAMMultiMediaStream *mmstream = create_ammultimediastream();
1961 IMediaStreamFilter *filter;
1962 IMediaStream *stream;
1963 PIN_DIRECTION dir;
1964 ULONG ref, count;
1965 PIN_INFO info;
1966 HRESULT hr;
1967 WCHAR *id;
1968 IPin *pin;
1970 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
1971 ok(hr == S_OK, "Got hr %#x.\n", hr);
1973 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
1974 ok(hr == S_OK, "Got hr %#x.\n", hr);
1975 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
1976 ok(hr == S_OK, "Got hr %#x.\n", hr);
1978 hr = IPin_QueryPinInfo(pin, &info);
1979 ok(hr == S_OK, "Got hr %#x.\n", hr);
1980 ok(info.pFilter == (IBaseFilter *)filter, "Expected filter %p, got %p.\n", filter, info.pFilter);
1981 ok(info.dir == PINDIR_INPUT, "Got direction %d.\n", info.dir);
1982 ok(!wcscmp(info.achName, primary_video_sink_id), "Got name %s.\n", wine_dbgstr_w(info.achName));
1983 IBaseFilter_Release(info.pFilter);
1985 hr = IPin_QueryDirection(pin, &dir);
1986 ok(hr == S_OK, "Got hr %#x.\n", hr);
1987 ok(dir == PINDIR_INPUT, "Got direction %d.\n", dir);
1989 hr = IPin_QueryId(pin, &id);
1990 ok(hr == S_OK, "Got hr %#x.\n", hr);
1991 ok(!wcscmp(id, primary_video_sink_id), "Got id %s.\n", wine_dbgstr_w(id));
1992 CoTaskMemFree(id);
1994 hr = IPin_QueryInternalConnections(pin, NULL, &count);
1995 ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
1997 IPin_Release(pin);
1998 IMediaStream_Release(stream);
2000 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
2001 ok(hr == S_OK, "Got hr %#x.\n", hr);
2002 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
2003 ok(hr == S_OK, "Got hr %#x.\n", hr);
2005 hr = IPin_QueryPinInfo(pin, &info);
2006 ok(hr == S_OK, "Got hr %#x.\n", hr);
2007 ok(info.pFilter == (IBaseFilter *)filter, "Expected filter %p, got %p.\n", filter, info.pFilter);
2008 ok(info.dir == PINDIR_INPUT, "Got direction %d.\n", info.dir);
2009 ok(!wcscmp(info.achName, primary_audio_sink_id), "Got name %s.\n", wine_dbgstr_w(info.achName));
2010 IBaseFilter_Release(info.pFilter);
2012 hr = IPin_QueryDirection(pin, &dir);
2013 ok(hr == S_OK, "Got hr %#x.\n", hr);
2014 ok(dir == PINDIR_INPUT, "Got direction %d.\n", dir);
2016 hr = IPin_QueryId(pin, &id);
2017 ok(hr == S_OK, "Got hr %#x.\n", hr);
2018 ok(!wcscmp(id, primary_audio_sink_id), "Got id %s.\n", wine_dbgstr_w(id));
2019 CoTaskMemFree(id);
2021 hr = IPin_QueryInternalConnections(pin, NULL, &count);
2022 ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
2024 IPin_Release(pin);
2025 IMediaStream_Release(stream);
2027 IMediaStreamFilter_Release(filter);
2028 ref = IAMMultiMediaStream_Release(mmstream);
2029 ok(!ref, "Got outstanding refcount %d.\n", ref);
2032 struct graph
2034 IFilterGraph2 IFilterGraph2_iface;
2035 IMediaEventSink IMediaEventSink_iface;
2036 IUnknown *inner_unk;
2037 IFilterGraph2 *inner;
2038 IMediaEventSink *inner_event_sink;
2039 LONG refcount;
2040 unsigned int got_add_filter;
2041 IBaseFilter *filter;
2042 WCHAR filter_name[128];
2043 unsigned int got_notify;
2044 LONG event_code;
2045 LONG_PTR event_param1;
2046 LONG_PTR event_param2;
2049 static struct graph *impl_from_IFilterGraph2(IFilterGraph2 *iface)
2051 return CONTAINING_RECORD(iface, struct graph, IFilterGraph2_iface);
2054 static struct graph *impl_from_IMediaEventSink(IMediaEventSink *iface)
2056 return CONTAINING_RECORD(iface, struct graph, IMediaEventSink_iface);
2059 static HRESULT WINAPI graph_QueryInterface(IFilterGraph2 *iface, REFIID iid, void **out)
2061 struct graph *graph = impl_from_IFilterGraph2(iface);
2062 if (winetest_debug > 1) trace("QueryInterface(%s)\n", wine_dbgstr_guid(iid));
2063 if (IsEqualGUID(iid, &IID_IFilterGraph2)
2064 || IsEqualGUID(iid, &IID_IGraphBuilder)
2065 || IsEqualGUID(iid, &IID_IFilterGraph)
2066 || IsEqualGUID(iid, &IID_IUnknown))
2068 *out = iface;
2069 IFilterGraph2_AddRef(iface);
2070 return S_OK;
2072 else if (IsEqualGUID(iid, &IID_IMediaEventSink))
2074 *out = &graph->IMediaEventSink_iface;
2075 IFilterGraph2_AddRef(iface);
2076 return S_OK;
2078 else
2080 return IUnknown_QueryInterface(graph->inner_unk, iid, out);
2082 return E_NOINTERFACE;
2085 static ULONG WINAPI graph_AddRef(IFilterGraph2 *iface)
2087 struct graph *graph = impl_from_IFilterGraph2(iface);
2088 return InterlockedIncrement(&graph->refcount);
2091 static ULONG WINAPI graph_Release(IFilterGraph2 *iface)
2093 struct graph *graph = impl_from_IFilterGraph2(iface);
2094 return InterlockedDecrement(&graph->refcount);
2097 static HRESULT WINAPI graph_AddFilter(IFilterGraph2 *iface, IBaseFilter *filter, const WCHAR *name)
2099 struct graph *graph = impl_from_IFilterGraph2(iface);
2100 if (winetest_debug > 1) trace("AddFilter(%p, %s)\n", filter, wine_dbgstr_w(name));
2101 ++graph->got_add_filter;
2102 graph->filter = filter;
2103 if (name)
2104 wcscpy(graph->filter_name, name);
2105 else
2106 graph->filter_name[0] = 0;
2107 return IFilterGraph2_AddFilter(graph->inner, filter, name);
2110 static HRESULT WINAPI graph_RemoveFilter(IFilterGraph2 *iface, IBaseFilter *filter)
2112 ok(0, "Unexpected call.\n");
2113 return E_NOTIMPL;
2116 static HRESULT WINAPI graph_EnumFilters(IFilterGraph2 *iface, IEnumFilters **enumfilters)
2118 struct graph *graph = impl_from_IFilterGraph2(iface);
2119 if (winetest_debug > 1) trace("EnumFilters()\n");
2120 return IFilterGraph2_EnumFilters(graph->inner, enumfilters);
2123 static HRESULT WINAPI graph_FindFilterByName(IFilterGraph2 *iface, const WCHAR *name, IBaseFilter **filter)
2125 ok(0, "Unexpected call.\n");
2126 return E_NOTIMPL;
2129 static HRESULT WINAPI graph_ConnectDirect(IFilterGraph2 *iface, IPin *source, IPin *sink, const AM_MEDIA_TYPE *mt)
2131 ok(0, "Unexpected call.\n");
2132 return E_NOTIMPL;
2135 static HRESULT WINAPI graph_Reconnect(IFilterGraph2 *iface, IPin *pin)
2137 ok(0, "Unexpected call.\n");
2138 return E_NOTIMPL;
2141 static HRESULT WINAPI graph_Disconnect(IFilterGraph2 *iface, IPin *pin)
2143 ok(0, "Unexpected call.\n");
2144 return E_NOTIMPL;
2147 static HRESULT WINAPI graph_SetDefaultSyncSource(IFilterGraph2 *iface)
2149 ok(0, "Unexpected call.\n");
2150 return E_NOTIMPL;
2153 static HRESULT WINAPI graph_Connect(IFilterGraph2 *iface, IPin *source, IPin *sink)
2155 ok(0, "Unexpected call.\n");
2156 return E_NOTIMPL;
2159 static HRESULT WINAPI graph_Render(IFilterGraph2 *iface, IPin *source)
2161 ok(0, "Unexpected call.\n");
2162 return E_NOTIMPL;
2165 static HRESULT WINAPI graph_RenderFile(IFilterGraph2 *iface, const WCHAR *filename, const WCHAR *playlist)
2167 ok(0, "Unexpected call.\n");
2168 return E_NOTIMPL;
2171 static HRESULT WINAPI graph_AddSourceFilter(IFilterGraph2 *iface,
2172 const WCHAR *filename, const WCHAR *filter_name, IBaseFilter **filter)
2174 ok(0, "Unexpected call.\n");
2175 return E_NOTIMPL;
2178 static HRESULT WINAPI graph_SetLogFile(IFilterGraph2 *iface, DWORD_PTR file)
2180 ok(0, "Unexpected call.\n");
2181 return E_NOTIMPL;
2184 static HRESULT WINAPI graph_Abort(IFilterGraph2 *iface)
2186 ok(0, "Unexpected call.\n");
2187 return E_NOTIMPL;
2190 static HRESULT WINAPI graph_ShouldOperationContinue(IFilterGraph2 *iface)
2192 ok(0, "Unexpected call.\n");
2193 return E_NOTIMPL;
2196 static HRESULT WINAPI graph_AddSourceFilterForMoniker(IFilterGraph2 *iface,
2197 IMoniker *moniker, IBindCtx *bind_ctx, const WCHAR *filter_name, IBaseFilter **filter)
2199 ok(0, "Unexpected call.\n");
2200 return E_NOTIMPL;
2203 static HRESULT WINAPI graph_ReconnectEx(IFilterGraph2 *iface, IPin *pin, const AM_MEDIA_TYPE *mt)
2205 ok(0, "Unexpected call.\n");
2206 return E_NOTIMPL;
2209 static HRESULT WINAPI graph_RenderEx(IFilterGraph2 *iface, IPin *pin, DWORD flags, DWORD *context)
2211 ok(0, "Unexpected call.\n");
2212 return E_NOTIMPL;
2215 static const IFilterGraph2Vtbl graph_vtbl =
2217 graph_QueryInterface,
2218 graph_AddRef,
2219 graph_Release,
2220 graph_AddFilter,
2221 graph_RemoveFilter,
2222 graph_EnumFilters,
2223 graph_FindFilterByName,
2224 graph_ConnectDirect,
2225 graph_Reconnect,
2226 graph_Disconnect,
2227 graph_SetDefaultSyncSource,
2228 graph_Connect,
2229 graph_Render,
2230 graph_RenderFile,
2231 graph_AddSourceFilter,
2232 graph_SetLogFile,
2233 graph_Abort,
2234 graph_ShouldOperationContinue,
2235 graph_AddSourceFilterForMoniker,
2236 graph_ReconnectEx,
2237 graph_RenderEx,
2240 static HRESULT WINAPI event_sink_QueryInterface(IMediaEventSink *iface, REFIID iid, void **out)
2242 struct graph *graph = impl_from_IMediaEventSink(iface);
2243 return IFilterGraph2_QueryInterface(&graph->IFilterGraph2_iface, iid, out);
2246 static ULONG WINAPI event_sink_AddRef(IMediaEventSink *iface)
2248 struct graph *graph = impl_from_IMediaEventSink(iface);
2249 return IFilterGraph2_AddRef(&graph->IFilterGraph2_iface);
2252 static ULONG WINAPI event_sink_Release(IMediaEventSink *iface)
2254 struct graph *graph = impl_from_IMediaEventSink(iface);
2255 return IFilterGraph2_Release(&graph->IFilterGraph2_iface);
2258 static HRESULT WINAPI event_sink_Notify(IMediaEventSink *iface,
2259 LONG code, LONG_PTR param1, LONG_PTR param2)
2261 struct graph *graph = impl_from_IMediaEventSink(iface);
2262 ++graph->got_notify;
2263 graph->event_code = code;
2264 graph->event_param1 = param1;
2265 graph->event_param2 = param2;
2266 return IMediaEventSink_Notify(graph->inner_event_sink, code, param1, param2);
2269 static const IMediaEventSinkVtbl event_sink_vtbl =
2271 event_sink_QueryInterface,
2272 event_sink_AddRef,
2273 event_sink_Release,
2274 event_sink_Notify,
2277 static void graph_init(struct graph *graph)
2279 HRESULT hr;
2281 memset(graph, 0, sizeof(*graph));
2282 graph->IFilterGraph2_iface.lpVtbl = &graph_vtbl;
2283 graph->IMediaEventSink_iface.lpVtbl = &event_sink_vtbl;
2284 graph->refcount = 1;
2285 hr = CoCreateInstance(&CLSID_FilterGraph, (IUnknown *)&graph->IFilterGraph2_iface, CLSCTX_INPROC_SERVER,
2286 &IID_IUnknown, (void **)&graph->inner_unk);
2287 ok(hr == S_OK, "Got hr %#x.\n", hr);
2288 hr = IUnknown_QueryInterface(graph->inner_unk, &IID_IFilterGraph2, (void **)&graph->inner);
2289 ok(hr == S_OK, "Got hr %#x.\n", hr);
2290 hr = IUnknown_QueryInterface(graph->inner_unk, &IID_IMediaEventSink, (void **)&graph->inner_event_sink);
2291 ok(hr == S_OK, "Got hr %#x.\n", hr);
2294 static void graph_destroy(struct graph *graph)
2296 ULONG ref;
2298 IMediaEventSink_Release(graph->inner_event_sink);
2299 IFilterGraph2_Release(graph->inner);
2300 ref = IUnknown_Release(graph->inner_unk);
2301 ok(!ref, "Got outstanding refcount %d.\n", ref);
2304 static void test_initialize(void)
2306 IAMMultiMediaStream *mmstream = create_ammultimediastream();
2307 IMediaStreamFilter *filter;
2308 IGraphBuilder *ret_graph;
2309 IMediaStream *stream;
2310 struct graph graph;
2311 STREAM_TYPE type;
2312 HRESULT hr;
2313 ULONG ref;
2315 ret_graph = (IGraphBuilder *)0xdeadbeef;
2316 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &ret_graph);
2317 ok(hr == S_OK, "Got hr %#x.\n", hr);
2318 ok(!ret_graph, "Got unexpected graph %p.\n", ret_graph);
2320 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
2321 ok(hr == S_OK, "Got hr %#x.\n", hr);
2322 ok(!!filter, "Expected a non-NULL filter.");
2323 IMediaStreamFilter_Release(filter);
2325 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
2326 ok(hr == S_OK, "Got hr %#x.\n", hr);
2328 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
2329 ok(hr == S_OK, "Got hr %#x.\n", hr);
2330 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_WRITE, 0, NULL);
2331 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2332 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_TRANSFORM, 0, NULL);
2333 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2335 ret_graph = (IGraphBuilder *)0xdeadbeef;
2336 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &ret_graph);
2337 ok(hr == S_OK, "Got hr %#x.\n", hr);
2338 ok(!ret_graph, "Got unexpected graph %p.\n", ret_graph);
2340 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
2341 ok(hr == S_OK, "Got hr %#x.\n", hr);
2342 type = 0xdeadbeef;
2343 hr = IMediaStream_GetInformation(stream, NULL, &type);
2344 ok(hr == S_OK, "Got hr %#x.\n", hr);
2345 ok(type == STREAMTYPE_READ, "Got type %u.\n", type);
2346 IMediaStream_Release(stream);
2348 ret_graph = NULL;
2349 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &ret_graph);
2350 ok(hr == S_OK, "Got hr %#x.\n", hr);
2351 ok(!!ret_graph, "Got unexpected graph %p.\n", ret_graph);
2352 IGraphBuilder_Release(ret_graph);
2354 ref = IAMMultiMediaStream_Release(mmstream);
2355 ok(!ref, "Got outstanding refcount %d.\n", ref);
2357 mmstream = create_ammultimediastream();
2359 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_WRITE, 0, NULL);
2360 ok(hr == S_OK, "Got hr %#x.\n", hr);
2362 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_WRITE, 0, NULL);
2363 ok(hr == S_OK, "Got hr %#x.\n", hr);
2364 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
2365 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2366 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_TRANSFORM, 0, NULL);
2367 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2369 ret_graph = (IGraphBuilder *)0xdeadbeef;
2370 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &ret_graph);
2371 ok(hr == S_OK, "Got hr %#x.\n", hr);
2372 ok(!ret_graph, "Got unexpected graph %p.\n", ret_graph);
2374 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
2375 ok(hr == S_OK, "Got hr %#x.\n", hr);
2376 type = 0xdeadbeef;
2377 hr = IMediaStream_GetInformation(stream, NULL, &type);
2378 ok(hr == S_OK, "Got hr %#x.\n", hr);
2379 ok(type == STREAMTYPE_WRITE, "Got type %u.\n", type);
2380 IMediaStream_Release(stream);
2382 ref = IAMMultiMediaStream_Release(mmstream);
2383 ok(!ref, "Got outstanding refcount %d.\n", ref);
2385 mmstream = create_ammultimediastream();
2387 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_TRANSFORM, 0, NULL);
2388 ok(hr == S_OK, "Got hr %#x.\n", hr);
2390 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_TRANSFORM, 0, NULL);
2391 ok(hr == S_OK, "Got hr %#x.\n", hr);
2392 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
2393 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2394 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_WRITE, 0, NULL);
2395 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2397 ret_graph = (IGraphBuilder *)0xdeadbeef;
2398 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &ret_graph);
2399 ok(hr == S_OK, "Got hr %#x.\n", hr);
2400 ok(!ret_graph, "Got unexpected graph %p.\n", ret_graph);
2402 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
2403 ok(hr == S_OK, "Got hr %#x.\n", hr);
2404 type = 0xdeadbeef;
2405 hr = IMediaStream_GetInformation(stream, NULL, &type);
2406 ok(hr == S_OK, "Got hr %#x.\n", hr);
2407 ok(type == STREAMTYPE_TRANSFORM, "Got type %u.\n", type);
2408 IMediaStream_Release(stream);
2410 ref = IAMMultiMediaStream_Release(mmstream);
2411 ok(!ref, "Got outstanding refcount %d.\n", ref);
2413 mmstream = create_ammultimediastream();
2415 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
2416 ok(hr == S_OK, "Got hr %#x.\n", hr);
2418 type = 0xdeadbeef;
2419 hr = IMediaStream_GetInformation(stream, NULL, &type);
2420 ok(hr == S_OK, "Got hr %#x.\n", hr);
2421 ok(type == STREAMTYPE_READ, "Got type %u.\n", type);
2423 ret_graph = NULL;
2424 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &ret_graph);
2425 ok(hr == S_OK, "Got hr %#x.\n", hr);
2426 ok(!!ret_graph, "Got unexpected graph %p.\n", ret_graph);
2427 IGraphBuilder_Release(ret_graph);
2429 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_TRANSFORM, 0, NULL);
2430 ok(hr == S_OK, "Got hr %#x.\n", hr);
2432 type = 0xdeadbeef;
2433 hr = IMediaStream_GetInformation(stream, NULL, &type);
2434 ok(hr == S_OK, "Got hr %#x.\n", hr);
2435 ok(type == STREAMTYPE_READ, "Got type %u.\n", type);
2437 IMediaStream_Release(stream);
2438 ref = IAMMultiMediaStream_Release(mmstream);
2439 ok(!ref, "Got outstanding refcount %d.\n", ref);
2441 /* Test with a custom filter graph. */
2443 mmstream = create_ammultimediastream();
2445 graph_init(&graph);
2447 ret_graph = (IGraphBuilder *)0xdeadbeef;
2448 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &ret_graph);
2449 ok(hr == S_OK, "Got hr %#x.\n", hr);
2450 ok(!ret_graph, "Got unexpected graph %p.\n", ret_graph);
2452 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
2453 ok(hr == S_OK, "Got hr %#x.\n", hr);
2454 ok(!!filter, "Expected a non-NULL filter.");
2456 graph.got_add_filter = 0;
2457 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, (IGraphBuilder *)&graph.IFilterGraph2_iface);
2458 ok(hr == S_OK, "Got hr %#x.\n", hr);
2459 ok(graph.got_add_filter == 1, "Got %d calls to IGraphBuilder::AddFilter().\n", graph.got_add_filter);
2460 ok(graph.filter == (IBaseFilter *)filter, "Got filter %p.\n", filter);
2461 ok(!wcscmp(graph.filter_name, L"MediaStreamFilter"), "Got unexpected name %s.\n", wine_dbgstr_w(graph.filter_name));
2463 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &ret_graph);
2464 ok(hr == S_OK, "Got hr %#x.\n", hr);
2465 ok(ret_graph == (IGraphBuilder *)&graph, "Got unexpected graph %p.\n", ret_graph);
2466 IGraphBuilder_Release(ret_graph);
2468 graph.got_add_filter = 0;
2469 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, NULL);
2470 ok(hr == S_OK, "Got hr %#x.\n", hr);
2471 ok(!graph.got_add_filter, "Got %d calls to IGraphBuilder::AddFilter().\n", graph.got_add_filter);
2473 graph.got_add_filter = 0;
2474 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, NULL);
2475 ok(hr == S_OK, "Got hr %#x.\n", hr);
2476 ok(!graph.got_add_filter, "Got %d calls to IGraphBuilder::AddFilter().\n", graph.got_add_filter);
2478 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, (IGraphBuilder *)&graph);
2479 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2480 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
2481 ok(hr == S_OK, "Got hr %#x.\n", hr);
2482 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_WRITE, 0, NULL);
2483 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2484 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_TRANSFORM, 0, NULL);
2485 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
2487 IMediaStreamFilter_Release(filter);
2488 ref = IAMMultiMediaStream_Release(mmstream);
2489 ok(!ref, "Got outstanding refcount %d.\n", ref);
2491 graph_destroy(&graph);
2494 static IAMMultiMediaStream *mmstream_mmstream;
2495 static STREAM_STATE mmstream_state;
2497 static DWORD CALLBACK mmstream_set_state(void *param)
2499 HRESULT hr;
2501 hr = IAMMultiMediaStream_SetState(mmstream_mmstream, mmstream_state);
2502 ok(hr == S_OK, "Got hr %#x.\n", hr);
2504 return 0;
2507 static void test_set_state(void)
2509 IAMMultiMediaStream *mmstream = create_ammultimediastream();
2510 IMediaControl *media_control;
2511 struct testfilter source;
2512 IGraphBuilder *graph;
2513 STREAM_STATE state;
2514 HANDLE thread;
2515 HRESULT hr;
2516 ULONG ref;
2518 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
2519 ok(hr == S_OK, "Got hr %#x.\n", hr);
2520 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, NULL);
2521 ok(hr == S_OK, "Got hr %#x.\n", hr);
2522 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
2523 ok(hr == S_OK, "Got hr %#x.\n", hr);
2524 ok(graph != NULL, "Expected non-NULL graph.\n");
2525 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void **)&media_control);
2526 ok(hr == S_OK, "Got hr %#x.\n", hr);
2527 testfilter_init(&source);
2529 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
2530 ok(hr == S_OK, "Got hr %#x.\n", hr);
2532 source.init_stream_hr = E_FAIL;
2533 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
2534 ok(hr == E_FAIL, "Got hr %#x.\n", hr);
2535 source.init_stream_hr = S_OK;
2536 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
2537 ok(hr == S_OK, "Got hr %#x.\n", hr);
2539 source.init_stream_hr = S_FALSE;
2540 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
2541 ok(hr == S_OK, "Got hr %#x.\n", hr);
2542 source.init_stream_hr = S_OK;
2543 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
2544 ok(hr == S_OK, "Got hr %#x.\n", hr);
2546 source.wait_state_hr = E_FAIL;
2547 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
2548 ok(hr == S_OK, "Got hr %#x.\n", hr);
2549 source.wait_state_hr = S_OK;
2550 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
2551 ok(hr == S_OK, "Got hr %#x.\n", hr);
2553 source.wait_state_hr = VFW_S_STATE_INTERMEDIATE;
2554 ResetEvent(source.wait_state_event);
2556 mmstream_mmstream = mmstream;
2557 mmstream_state = STREAMSTATE_RUN;
2558 thread = CreateThread(NULL, 0, mmstream_set_state, NULL, 0, NULL);
2560 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "SetState returned prematurely.\n");
2562 EnterCriticalSection(&source.filter.filter_cs);
2563 source.wait_state_hr = S_OK;
2564 SetEvent(source.wait_state_event);
2565 LeaveCriticalSection(&source.filter.filter_cs);
2567 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
2568 CloseHandle(thread);
2570 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
2571 ok(hr == S_OK, "Got hr %#x.\n", hr);
2573 source.init_stream_hr = E_FAIL;
2574 source.wait_state_hr = VFW_S_STATE_INTERMEDIATE;
2575 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
2576 ok(hr == E_FAIL, "Got hr %#x.\n", hr);
2577 source.init_stream_hr = S_OK;
2578 source.wait_state_hr = S_OK;
2579 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
2580 ok(hr == S_OK, "Got hr %#x.\n", hr);
2582 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
2583 ok(hr == S_OK, "Got hr %#x.\n", hr);
2584 source.cleanup_stream_hr = E_FAIL;
2585 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
2586 ok(hr == E_FAIL, "Got hr %#x.\n", hr);
2587 source.cleanup_stream_hr = S_OK;
2588 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
2589 ok(hr == S_OK, "Got hr %#x.\n", hr);
2591 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
2592 ok(hr == S_OK, "Got hr %#x.\n", hr);
2593 source.cleanup_stream_hr = S_FALSE;
2594 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
2595 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2596 source.cleanup_stream_hr = S_OK;
2598 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
2599 ok(hr == S_OK, "Got hr %#x.\n", hr);
2600 source.wait_state_hr = VFW_S_STATE_INTERMEDIATE;
2601 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
2602 ok(hr == S_OK, "Got hr %#x.\n", hr);
2603 source.wait_state_hr = S_OK;
2605 /* Crashes on native. */
2606 if (0)
2608 hr = IAMMultiMediaStream_GetState(mmstream, NULL);
2609 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2612 state = 0xdeadbeef;
2613 hr = IAMMultiMediaStream_GetState(mmstream, &state);
2614 ok(hr == S_OK, "Got hr %#x.\n", hr);
2615 ok(state == STREAMSTATE_STOP, "Got state %#x.\n", state);
2617 hr = IMediaControl_Run(media_control);
2618 ok(hr == S_OK, "Got hr %#x.\n", hr);
2620 state = 0xdeadbeef;
2621 hr = IAMMultiMediaStream_GetState(mmstream, &state);
2622 ok(hr == S_OK, "Got hr %#x.\n", hr);
2623 ok(state == STREAMSTATE_STOP, "Got state %#x.\n", state);
2625 hr = IMediaControl_Stop(media_control);
2626 ok(hr == S_OK, "Got hr %#x.\n", hr);
2628 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
2629 ok(hr == S_OK, "Got hr %#x.\n", hr);
2631 state = 0xdeadbeef;
2632 hr = IAMMultiMediaStream_GetState(mmstream, &state);
2633 ok(hr == S_OK, "Got hr %#x.\n", hr);
2634 ok(state == STREAMSTATE_RUN, "Got state %#x.\n", state);
2636 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
2637 ok(hr == S_OK, "Got hr %#x.\n", hr);
2639 state = 0xdeadbeef;
2640 hr = IAMMultiMediaStream_GetState(mmstream, &state);
2641 ok(hr == S_OK, "Got hr %#x.\n", hr);
2642 ok(state == STREAMSTATE_STOP, "Got state %#x.\n", state);
2644 source.init_stream_hr = E_FAIL;
2645 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
2646 ok(hr == E_FAIL, "Got hr %#x.\n", hr);
2648 state = 0xdeadbeef;
2649 hr = IAMMultiMediaStream_GetState(mmstream, &state);
2650 ok(hr == S_OK, "Got hr %#x.\n", hr);
2651 ok(state == STREAMSTATE_STOP, "Got state %#x.\n", state);
2653 ref = IAMMultiMediaStream_Release(mmstream);
2654 ok(!ref, "Got outstanding refcount %d.\n", ref);
2655 IMediaControl_Release(media_control);
2656 ref = IGraphBuilder_Release(graph);
2657 ok(!ref, "Got outstanding refcount %d.\n", ref);
2660 static void test_enum_media_types(void)
2662 IAMMultiMediaStream *mmstream = create_ammultimediastream();
2663 IEnumMediaTypes *enum1, *enum2;
2664 AM_MEDIA_TYPE *mts[2];
2665 IMediaStream *stream;
2666 ULONG ref, count;
2667 HRESULT hr;
2668 IPin *pin;
2670 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
2671 ok(hr == S_OK, "Got hr %#x.\n", hr);
2672 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
2673 ok(hr == S_OK, "Got hr %#x.\n", hr);
2675 hr = IPin_EnumMediaTypes(pin, &enum1);
2676 ok(hr == S_OK, "Got hr %#x.\n", hr);
2678 hr = IEnumMediaTypes_Next(enum1, 1, mts, NULL);
2679 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2681 hr = IEnumMediaTypes_Next(enum1, 0, mts, &count);
2682 ok(hr == S_OK, "Got hr %#x.\n", hr);
2683 ok(!count, "Got count %u.\n", count);
2685 hr = IEnumMediaTypes_Next(enum1, 1, mts, &count);
2686 ok(hr == S_OK, "Got hr %#x.\n", hr);
2687 ok(count == 1, "Got count %u.\n", count);
2688 CoTaskMemFree(mts[0]);
2690 hr = IEnumMediaTypes_Next(enum1, 1, mts, &count);
2691 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2692 ok(!count, "Got count %u.\n", count);
2694 hr = IEnumMediaTypes_Reset(enum1);
2695 ok(hr == S_OK, "Got hr %#x.\n", hr);
2697 hr = IEnumMediaTypes_Next(enum1, 2, mts, &count);
2698 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2699 ok(count == 1, "Got count %u.\n", count);
2700 CoTaskMemFree(mts[0]);
2702 hr = IEnumMediaTypes_Reset(enum1);
2703 ok(hr == S_OK, "Got hr %#x.\n", hr);
2705 hr = IEnumMediaTypes_Clone(enum1, &enum2);
2706 ok(hr == S_OK, "Got hr %#x.\n", hr);
2708 hr = IEnumMediaTypes_Skip(enum1, 2);
2709 ok(hr == S_OK, "Got hr %#x.\n", hr);
2711 hr = IEnumMediaTypes_Next(enum1, 1, mts, &count);
2712 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2713 ok(!count, "Got count %u.\n", count);
2715 hr = IEnumMediaTypes_Next(enum2, 1, mts, &count);
2716 ok(hr == S_OK, "Got hr %#x.\n", hr);
2717 ok(count == 1, "Got count %u.\n", count);
2718 CoTaskMemFree(mts[0]);
2720 IEnumMediaTypes_Release(enum2);
2721 IEnumMediaTypes_Release(enum1);
2722 IPin_Release(pin);
2723 IMediaStream_Release(stream);
2725 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
2726 ok(hr == S_OK, "Got hr %#x.\n", hr);
2727 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
2728 ok(hr == S_OK, "Got hr %#x.\n", hr);
2730 hr = IPin_EnumMediaTypes(pin, &enum1);
2731 ok(hr == S_OK, "Got hr %#x.\n", hr);
2733 hr = IEnumMediaTypes_Next(enum1, 1, mts, NULL);
2734 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2736 hr = IEnumMediaTypes_Next(enum1, 0, mts, &count);
2737 ok(hr == S_OK, "Got hr %#x.\n", hr);
2738 ok(!count, "Got count %u.\n", count);
2740 hr = IEnumMediaTypes_Next(enum1, 1, mts, &count);
2741 ok(hr == S_OK, "Got hr %#x.\n", hr);
2742 ok(count == 1, "Got count %u.\n", count);
2743 CoTaskMemFree(mts[0]->pbFormat);
2744 CoTaskMemFree(mts[0]);
2746 hr = IEnumMediaTypes_Next(enum1, 1, mts, &count);
2747 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2748 ok(!count, "Got count %u.\n", count);
2750 hr = IEnumMediaTypes_Reset(enum1);
2751 ok(hr == S_OK, "Got hr %#x.\n", hr);
2753 hr = IEnumMediaTypes_Next(enum1, 2, mts, &count);
2754 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2755 ok(count == 1, "Got count %u.\n", count);
2756 CoTaskMemFree(mts[0]->pbFormat);
2757 CoTaskMemFree(mts[0]);
2759 hr = IEnumMediaTypes_Reset(enum1);
2760 ok(hr == S_OK, "Got hr %#x.\n", hr);
2762 hr = IEnumMediaTypes_Clone(enum1, &enum2);
2763 ok(hr == S_OK, "Got hr %#x.\n", hr);
2765 hr = IEnumMediaTypes_Skip(enum1, 2);
2766 ok(hr == S_OK, "Got hr %#x.\n", hr);
2768 hr = IEnumMediaTypes_Next(enum1, 1, mts, &count);
2769 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2770 ok(!count, "Got count %u.\n", count);
2772 hr = IEnumMediaTypes_Next(enum2, 1, mts, &count);
2773 ok(hr == S_OK, "Got hr %#x.\n", hr);
2774 ok(count == 1, "Got count %u.\n", count);
2775 CoTaskMemFree(mts[0]->pbFormat);
2776 CoTaskMemFree(mts[0]);
2778 IEnumMediaTypes_Release(enum2);
2779 IEnumMediaTypes_Release(enum1);
2780 IPin_Release(pin);
2781 IMediaStream_Release(stream);
2783 ref = IAMMultiMediaStream_Release(mmstream);
2784 ok(!ref, "Got outstanding refcount %d.\n", ref);
2787 static void test_media_types(void)
2789 static const VIDEOINFOHEADER2 req_vih2;
2790 static const VIDEOINFOHEADER req_vih;
2791 static const MPEG2VIDEOINFO req_m2vi;
2792 static const MPEG1VIDEOINFO req_m1vi;
2793 static const WAVEFORMATEX req_wfx;
2794 static const WAVEFORMATEX expect_wfx =
2796 .wFormatTag = WAVE_FORMAT_PCM,
2797 .nChannels = 1,
2798 .nSamplesPerSec = 11025,
2799 .nAvgBytesPerSec = 11025 * 2,
2800 .nBlockAlign = 2,
2801 .wBitsPerSample = 16,
2802 .cbSize = 0,
2804 IAMMultiMediaStream *mmstream = create_ammultimediastream();
2805 IEnumMediaTypes *enummt;
2806 IMediaStream *stream;
2807 AM_MEDIA_TYPE *pmt;
2808 ULONG ref, count;
2809 unsigned int i;
2810 HRESULT hr;
2811 IPin *pin;
2813 static const struct
2815 const GUID *type;
2816 BYTE *format;
2817 ULONG size;
2819 tests[] =
2821 {&GUID_NULL, NULL, 0 },
2822 {&FORMAT_None, NULL, 0 },
2823 {&FORMAT_WaveFormatEx, (BYTE *)&req_wfx, sizeof(WAVEFORMATEX)},
2824 {&FORMAT_MPEG2Video, (BYTE *)&req_m2vi, sizeof(MPEG2VIDEOINFO)},
2825 {&FORMAT_MPEGVideo, (BYTE *)&req_m1vi, sizeof(MPEG2VIDEOINFO)},
2826 {&FORMAT_VideoInfo2, (BYTE *)&req_vih2, sizeof(VIDEOINFOHEADER2)},
2827 {&FORMAT_VideoInfo, (BYTE *)&req_vih, sizeof(VIDEOINFOHEADER)},
2830 static const GUID *rejected_subtypes[] =
2832 &MEDIASUBTYPE_RGB1,
2833 &MEDIASUBTYPE_RGB4,
2834 &MEDIASUBTYPE_RGB565,
2835 &MEDIASUBTYPE_RGB555,
2836 &MEDIASUBTYPE_RGB24,
2837 &MEDIASUBTYPE_RGB32,
2838 &MEDIASUBTYPE_ARGB32,
2839 &MEDIASUBTYPE_ARGB1555,
2840 &MEDIASUBTYPE_ARGB4444,
2841 &MEDIASUBTYPE_Avi,
2842 &MEDIASUBTYPE_I420,
2843 &MEDIASUBTYPE_AYUV,
2844 &MEDIASUBTYPE_YV12,
2845 &MEDIASUBTYPE_YUY2,
2846 &MEDIASUBTYPE_UYVY,
2847 &MEDIASUBTYPE_YVYU,
2848 &MEDIASUBTYPE_NV12,
2849 &GUID_NULL,
2852 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
2853 ok(hr == S_OK, "Got hr %#x.\n", hr);
2854 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
2855 ok(hr == S_OK, "Got hr %#x.\n", hr);
2857 hr = IPin_EnumMediaTypes(pin, &enummt);
2858 ok(hr == S_OK, "Got hr %#x.\n", hr);
2860 hr = IEnumMediaTypes_Next(enummt, 1, &pmt, NULL);
2861 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2863 hr = IEnumMediaTypes_Next(enummt, 1, &pmt, &count);
2864 ok(hr == S_OK, "Got hr %#x.\n", hr);
2865 ok(count == 1, "Got count %u.\n", count);
2866 ok(IsEqualGUID(&pmt->majortype, &MEDIATYPE_Video), "Got major type %s\n",
2867 wine_dbgstr_guid(&pmt->majortype));
2868 ok(IsEqualGUID(&pmt->subtype, &MEDIASUBTYPE_RGB8), "Got subtype %s\n",
2869 wine_dbgstr_guid(&pmt->subtype));
2870 ok(pmt->bFixedSizeSamples == TRUE, "Got fixed size %d.\n", pmt->bFixedSizeSamples);
2871 ok(!pmt->bTemporalCompression, "Got temporal compression %d.\n", pmt->bTemporalCompression);
2872 ok(pmt->lSampleSize == 10000, "Got sample size %u.\n", pmt->lSampleSize);
2873 ok(IsEqualGUID(&pmt->formattype, &GUID_NULL), "Got format type %s.\n",
2874 wine_dbgstr_guid(&pmt->formattype));
2875 ok(!pmt->pUnk, "Got pUnk %p.\n", pmt->pUnk);
2877 for (i = 0; i < ARRAY_SIZE(tests); ++i)
2879 pmt->formattype = *tests[i].type;
2880 pmt->cbFormat = tests[i].size;
2881 pmt->pbFormat = tests[i].format;
2882 hr = IPin_QueryAccept(pin, pmt);
2883 ok(hr == (i == 6 ? S_OK : VFW_E_TYPE_NOT_ACCEPTED), "Got hr %#x.\n", hr);
2886 pmt->bFixedSizeSamples = FALSE;
2887 pmt->bTemporalCompression = TRUE;
2888 pmt->lSampleSize = 123;
2889 hr = IPin_QueryAccept(pin, pmt);
2890 ok(hr == S_OK, "Got hr %#x.\n", hr);
2892 pmt->majortype = MEDIATYPE_NULL;
2893 hr = IPin_QueryAccept(pin, pmt);
2894 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
2895 pmt->majortype = MEDIATYPE_Audio;
2896 hr = IPin_QueryAccept(pin, pmt);
2897 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
2898 pmt->majortype = MEDIATYPE_Stream;
2899 hr = IPin_QueryAccept(pin, pmt);
2900 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
2901 pmt->majortype = MEDIATYPE_Video;
2903 for (i = 0; i < ARRAY_SIZE(rejected_subtypes); ++i)
2905 pmt->subtype = *rejected_subtypes[i];
2906 hr = IPin_QueryAccept(pin, pmt);
2907 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x for subtype %s.\n",
2908 hr, wine_dbgstr_guid(rejected_subtypes[i]));
2911 CoTaskMemFree(pmt);
2913 hr = IEnumMediaTypes_Next(enummt, 1, &pmt, &count);
2914 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2916 IEnumMediaTypes_Release(enummt);
2917 IPin_Release(pin);
2918 IMediaStream_Release(stream);
2920 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
2921 ok(hr == S_OK, "Got hr %#x.\n", hr);
2922 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
2923 ok(hr == S_OK, "Got hr %#x.\n", hr);
2925 hr = IPin_EnumMediaTypes(pin, &enummt);
2926 ok(hr == S_OK, "Got hr %#x.\n", hr);
2928 hr = IEnumMediaTypes_Next(enummt, 1, &pmt, NULL);
2929 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
2931 hr = IEnumMediaTypes_Next(enummt, 1, &pmt, &count);
2932 ok(hr == S_OK, "Got hr %#x.\n", hr);
2933 ok(count == 1, "Got count %u.\n", count);
2934 ok(IsEqualGUID(&pmt->majortype, &MEDIATYPE_Audio), "Got major type %s\n",
2935 wine_dbgstr_guid(&pmt->majortype));
2936 ok(IsEqualGUID(&pmt->subtype, &GUID_NULL), "Got subtype %s\n",
2937 wine_dbgstr_guid(&pmt->subtype));
2938 ok(pmt->bFixedSizeSamples == TRUE, "Got fixed size %d.\n", pmt->bFixedSizeSamples);
2939 ok(!pmt->bTemporalCompression, "Got temporal compression %d.\n", pmt->bTemporalCompression);
2940 ok(pmt->lSampleSize == 2, "Got sample size %u.\n", pmt->lSampleSize);
2941 ok(IsEqualGUID(&pmt->formattype, &FORMAT_WaveFormatEx), "Got format type %s.\n",
2942 wine_dbgstr_guid(&pmt->formattype));
2943 ok(!pmt->pUnk, "Got pUnk %p.\n", pmt->pUnk);
2944 ok(pmt->cbFormat == sizeof(WAVEFORMATEX), "Got format size %u.\n", pmt->cbFormat);
2945 ok(!memcmp(pmt->pbFormat, &expect_wfx, pmt->cbFormat), "Format blocks didn't match.\n");
2947 hr = IPin_QueryAccept(pin, pmt);
2948 ok(hr == E_NOTIMPL, "Got hr %#x.\n", hr);
2950 CoTaskMemFree(pmt->pbFormat);
2951 CoTaskMemFree(pmt);
2953 hr = IEnumMediaTypes_Next(enummt, 1, &pmt, &count);
2954 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
2956 IEnumMediaTypes_Release(enummt);
2957 IPin_Release(pin);
2958 IMediaStream_Release(stream);
2960 ref = IAMMultiMediaStream_Release(mmstream);
2961 ok(!ref, "Got outstanding refcount %d.\n", ref);
2964 static IUnknown *create_audio_data(void)
2966 IUnknown *audio_data = NULL;
2967 HRESULT result = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER,
2968 &IID_IUnknown, (void **)&audio_data);
2969 ok(S_OK == result, "got 0x%08x\n", result);
2970 return audio_data;
2973 static void test_audiodata_query_interface(void)
2975 IUnknown *unknown = create_audio_data();
2976 IMemoryData *memory_data = NULL;
2977 IAudioData *audio_data = NULL;
2979 HRESULT result;
2981 result = IUnknown_QueryInterface(unknown, &IID_IMemoryData, (void **)&memory_data);
2982 ok(E_NOINTERFACE == result, "got 0x%08x\n", result);
2984 result = IUnknown_QueryInterface(unknown, &IID_IAudioData, (void **)&audio_data);
2985 ok(S_OK == result, "got 0x%08x\n", result);
2986 if (S_OK == result)
2988 result = IAudioData_QueryInterface(audio_data, &IID_IMemoryData, (void **)&memory_data);
2989 ok(E_NOINTERFACE == result, "got 0x%08x\n", result);
2991 IAudioData_Release(audio_data);
2994 IUnknown_Release(unknown);
2997 static void test_audiodata_get_info(void)
2999 IUnknown *unknown = create_audio_data();
3000 IAudioData *audio_data = NULL;
3002 HRESULT result;
3004 result = IUnknown_QueryInterface(unknown, &IID_IAudioData, (void **)&audio_data);
3005 if (FAILED(result))
3007 /* test_audiodata_query_interface handles this case */
3008 skip("No IAudioData\n");
3009 goto out_unknown;
3012 result = IAudioData_GetInfo(audio_data, NULL, NULL, NULL);
3013 ok(MS_E_NOTINIT == result, "got 0x%08x\n", result);
3015 IAudioData_Release(audio_data);
3017 out_unknown:
3018 IUnknown_Release(unknown);
3021 static void test_audiodata_set_buffer(void)
3023 IUnknown *unknown = create_audio_data();
3024 IAudioData *audio_data = NULL;
3025 BYTE buffer[100] = {0};
3026 DWORD length = 0;
3027 BYTE *data = NULL;
3029 HRESULT result;
3031 result = IUnknown_QueryInterface(unknown, &IID_IAudioData, (void **)&audio_data);
3032 if (FAILED(result))
3034 /* test_audiodata_query_interface handles this case */
3035 skip("No IAudioData\n");
3036 goto out_unknown;
3039 result = IAudioData_SetBuffer(audio_data, 100, NULL, 0);
3040 ok(S_OK == result, "got 0x%08x\n", result);
3042 data = (BYTE *)0xdeadbeef;
3043 length = 0xdeadbeef;
3044 result = IAudioData_GetInfo(audio_data, &length, &data, NULL);
3045 ok(S_OK == result, "got 0x%08x\n", result);
3046 ok(100 == length, "got %u\n", length);
3047 ok(NULL != data, "got %p\n", data);
3049 result = IAudioData_SetBuffer(audio_data, 0, buffer, 0);
3050 ok(E_INVALIDARG == result, "got 0x%08x\n", result);
3052 result = IAudioData_SetBuffer(audio_data, sizeof(buffer), buffer, 0);
3053 ok(S_OK == result, "got 0x%08x\n", result);
3055 data = (BYTE *)0xdeadbeef;
3056 length = 0xdeadbeef;
3057 result = IAudioData_GetInfo(audio_data, &length, &data, NULL);
3058 ok(S_OK == result, "got 0x%08x\n", result);
3059 ok(sizeof(buffer) == length, "got %u\n", length);
3060 ok(buffer == data, "got %p\n", data);
3062 IAudioData_Release(audio_data);
3064 out_unknown:
3065 IUnknown_Release(unknown);
3068 static void test_audiodata_set_actual(void)
3070 IUnknown *unknown = create_audio_data();
3071 IAudioData *audio_data = NULL;
3072 BYTE buffer[100] = {0};
3073 DWORD actual_data = 0;
3075 HRESULT result;
3077 result = IUnknown_QueryInterface(unknown, &IID_IAudioData, (void **)&audio_data);
3078 if (FAILED(result))
3080 /* test_audiodata_query_interface handles this case */
3081 skip("No IAudioData\n");
3082 goto out_unknown;
3085 result = IAudioData_SetActual(audio_data, 0);
3086 ok(S_OK == result, "got 0x%08x\n", result);
3088 result = IAudioData_SetBuffer(audio_data, sizeof(buffer), buffer, 0);
3089 ok(S_OK == result, "got 0x%08x\n", result);
3091 result = IAudioData_SetActual(audio_data, sizeof(buffer) + 1);
3092 ok(E_INVALIDARG == result, "got 0x%08x\n", result);
3094 result = IAudioData_SetActual(audio_data, sizeof(buffer));
3095 ok(S_OK == result, "got 0x%08x\n", result);
3097 actual_data = 0xdeadbeef;
3098 result = IAudioData_GetInfo(audio_data, NULL, NULL, &actual_data);
3099 ok(S_OK == result, "got 0x%08x\n", result);
3100 ok(sizeof(buffer) == actual_data, "got %u\n", actual_data);
3102 result = IAudioData_SetActual(audio_data, 0);
3103 ok(S_OK == result, "got 0x%08x\n", result);
3105 actual_data = 0xdeadbeef;
3106 result = IAudioData_GetInfo(audio_data, NULL, NULL, &actual_data);
3107 ok(S_OK == result, "got 0x%08x\n", result);
3108 ok(0 == actual_data, "got %u\n", actual_data);
3110 IAudioData_Release(audio_data);
3112 out_unknown:
3113 IUnknown_Release(unknown);
3116 static void test_audiodata_get_format(void)
3118 IUnknown *unknown = create_audio_data();
3119 IAudioData *audio_data = NULL;
3120 WAVEFORMATEX wave_format = {0};
3122 HRESULT result;
3124 result = IUnknown_QueryInterface(unknown, &IID_IAudioData, (void **)&audio_data);
3125 if (FAILED(result))
3127 /* test_audiodata_query_interface handles this case */
3128 skip("No IAudioData\n");
3129 goto out_unknown;
3132 result = IAudioData_GetFormat(audio_data, NULL);
3133 ok(E_POINTER == result, "got 0x%08x\n", result);
3135 wave_format.wFormatTag = 0xdead;
3136 wave_format.nChannels = 0xdead;
3137 wave_format.nSamplesPerSec = 0xdeadbeef;
3138 wave_format.nAvgBytesPerSec = 0xdeadbeef;
3139 wave_format.nBlockAlign = 0xdead;
3140 wave_format.wBitsPerSample = 0xdead;
3141 wave_format.cbSize = 0xdead;
3142 result = IAudioData_GetFormat(audio_data, &wave_format);
3143 ok(S_OK == result, "got 0x%08x\n", result);
3144 ok(WAVE_FORMAT_PCM == wave_format.wFormatTag, "got %u\n", wave_format.wFormatTag);
3145 ok(1 == wave_format.nChannels, "got %u\n", wave_format.nChannels);
3146 ok(11025 == wave_format.nSamplesPerSec, "got %u\n", wave_format.nSamplesPerSec);
3147 ok(22050 == wave_format.nAvgBytesPerSec, "got %u\n", wave_format.nAvgBytesPerSec);
3148 ok(2 == wave_format.nBlockAlign, "got %u\n", wave_format.nBlockAlign);
3149 ok(16 == wave_format.wBitsPerSample, "got %u\n", wave_format.wBitsPerSample);
3150 ok(0 == wave_format.cbSize, "got %u\n", wave_format.cbSize);
3152 IAudioData_Release(audio_data);
3154 out_unknown:
3155 IUnknown_Release(unknown);
3158 static void test_audiodata_set_format(void)
3160 IUnknown *unknown = create_audio_data();
3161 IAudioData *audio_data = NULL;
3162 WAVEFORMATPCMEX wave_format = {{0}};
3164 HRESULT result;
3166 result = IUnknown_QueryInterface(unknown, &IID_IAudioData, (void **)&audio_data);
3167 if (FAILED(result))
3169 /* test_audiodata_query_interface handles this case */
3170 skip("No IAudioData\n");
3171 goto out_unknown;
3174 result = IAudioData_SetFormat(audio_data, NULL);
3175 ok(E_POINTER == result, "got 0x%08x\n", result);
3177 wave_format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
3178 wave_format.Format.nChannels = 2;
3179 wave_format.Format.nSamplesPerSec = 44100;
3180 wave_format.Format.nAvgBytesPerSec = 176400;
3181 wave_format.Format.nBlockAlign = 4;
3182 wave_format.Format.wBitsPerSample = 16;
3183 wave_format.Format.cbSize = 22;
3184 wave_format.Samples.wValidBitsPerSample = 16;
3185 wave_format.dwChannelMask = KSAUDIO_SPEAKER_STEREO;
3186 wave_format.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
3187 result = IAudioData_SetFormat(audio_data, &wave_format.Format);
3188 ok(E_INVALIDARG == result, "got 0x%08x\n", result);
3190 wave_format.Format.wFormatTag = WAVE_FORMAT_PCM;
3191 wave_format.Format.nChannels = 2;
3192 wave_format.Format.nSamplesPerSec = 44100;
3193 wave_format.Format.nAvgBytesPerSec = 176400;
3194 wave_format.Format.nBlockAlign = 4;
3195 wave_format.Format.wBitsPerSample = 16;
3196 wave_format.Format.cbSize = 0;
3197 result = IAudioData_SetFormat(audio_data, &wave_format.Format);
3198 ok(S_OK == result, "got 0x%08x\n", result);
3200 wave_format.Format.wFormatTag = 0xdead;
3201 wave_format.Format.nChannels = 0xdead;
3202 wave_format.Format.nSamplesPerSec = 0xdeadbeef;
3203 wave_format.Format.nAvgBytesPerSec = 0xdeadbeef;
3204 wave_format.Format.nBlockAlign = 0xdead;
3205 wave_format.Format.wBitsPerSample = 0xdead;
3206 wave_format.Format.cbSize = 0xdead;
3207 result = IAudioData_GetFormat(audio_data, &wave_format.Format);
3208 ok(S_OK == result, "got 0x%08x\n", result);
3209 ok(WAVE_FORMAT_PCM == wave_format.Format.wFormatTag, "got %u\n", wave_format.Format.wFormatTag);
3210 ok(2 == wave_format.Format.nChannels, "got %u\n", wave_format.Format.nChannels);
3211 ok(44100 == wave_format.Format.nSamplesPerSec, "got %u\n", wave_format.Format.nSamplesPerSec);
3212 ok(176400 == wave_format.Format.nAvgBytesPerSec, "got %u\n", wave_format.Format.nAvgBytesPerSec);
3213 ok(4 == wave_format.Format.nBlockAlign, "got %u\n", wave_format.Format.nBlockAlign);
3214 ok(16 == wave_format.Format.wBitsPerSample, "got %u\n", wave_format.Format.wBitsPerSample);
3215 ok(0 == wave_format.Format.cbSize, "got %u\n", wave_format.Format.cbSize);
3217 IAudioData_Release(audio_data);
3219 out_unknown:
3220 IUnknown_Release(unknown);
3223 struct advise_time_cookie
3225 LONGLONG base;
3226 LONGLONG offset;
3227 HANDLE event;
3228 HANDLE advise_time_called_event;
3229 BOOL unadvise_called;
3232 struct testclock
3234 IReferenceClock IReferenceClock_iface;
3235 LONG refcount;
3236 LONGLONG time;
3237 struct advise_time_cookie *advise_time_cookie;
3238 HRESULT get_time_hr;
3241 static inline struct testclock *impl_from_IReferenceClock(IReferenceClock *iface)
3243 return CONTAINING_RECORD(iface, struct testclock, IReferenceClock_iface);
3246 static HRESULT WINAPI testclock_QueryInterface(IReferenceClock *iface, REFIID iid, void **out)
3248 if (winetest_debug > 1) trace("QueryInterface(%s)\n", wine_dbgstr_guid(iid));
3249 if (IsEqualGUID(iid, &IID_IReferenceClock)
3250 || IsEqualGUID(iid, &IID_IUnknown))
3252 *out = iface;
3253 IReferenceClock_AddRef(iface);
3254 return S_OK;
3256 return E_NOINTERFACE;
3259 static ULONG WINAPI testclock_AddRef(IReferenceClock *iface)
3261 struct testclock *clock = impl_from_IReferenceClock(iface);
3262 return InterlockedIncrement(&clock->refcount);
3265 static ULONG WINAPI testclock_Release(IReferenceClock *iface)
3267 struct testclock *clock = impl_from_IReferenceClock(iface);
3268 return InterlockedDecrement(&clock->refcount);
3271 static HRESULT WINAPI testclock_GetTime(IReferenceClock *iface, REFERENCE_TIME *time)
3273 struct testclock *clock = impl_from_IReferenceClock(iface);
3274 if (SUCCEEDED(clock->get_time_hr))
3275 *time = clock->time;
3276 return clock->get_time_hr;
3279 static HRESULT WINAPI testclock_AdviseTime(IReferenceClock *iface, REFERENCE_TIME base, REFERENCE_TIME offset, HEVENT event, DWORD_PTR *cookie)
3281 struct testclock *clock = impl_from_IReferenceClock(iface);
3282 if (clock->advise_time_cookie)
3284 clock->advise_time_cookie->base = base;
3285 clock->advise_time_cookie->offset = offset;
3286 clock->advise_time_cookie->event = (HANDLE)event;
3287 SetEvent(clock->advise_time_cookie->advise_time_called_event);
3289 else
3291 SetEvent((HANDLE)event);
3293 *cookie = (DWORD_PTR)clock->advise_time_cookie;
3294 return S_OK;
3297 static HRESULT WINAPI testclock_AdvisePeriodic(IReferenceClock *iface, REFERENCE_TIME start, REFERENCE_TIME period, HSEMAPHORE semaphore, DWORD_PTR *cookie)
3299 ok(0, "Unexpected call.\n");
3300 return E_NOTIMPL;
3303 static HRESULT WINAPI testclock_Unadvise(IReferenceClock *iface, DWORD_PTR cookie)
3305 if (cookie)
3306 ((struct advise_time_cookie *)cookie)->unadvise_called = TRUE;
3307 return S_OK;
3310 static IReferenceClockVtbl testclock_vtbl =
3312 testclock_QueryInterface,
3313 testclock_AddRef,
3314 testclock_Release,
3315 testclock_GetTime,
3316 testclock_AdviseTime,
3317 testclock_AdvisePeriodic,
3318 testclock_Unadvise,
3321 static void testclock_init(struct testclock *clock)
3323 memset(clock, 0, sizeof(*clock));
3324 clock->IReferenceClock_iface.lpVtbl = &testclock_vtbl;
3327 static void test_audiostream_get_format(void)
3329 static const WAVEFORMATEX pin_format =
3331 .wFormatTag = WAVE_FORMAT_PCM,
3332 .nChannels = 2,
3333 .nSamplesPerSec = 44100,
3334 .wBitsPerSample = 16,
3335 .nBlockAlign = 4,
3336 .nAvgBytesPerSec = 4 * 44100,
3338 AM_MEDIA_TYPE mt =
3340 .majortype = MEDIATYPE_Audio,
3341 .subtype = MEDIASUBTYPE_PCM,
3342 .formattype = FORMAT_WaveFormatEx,
3343 .cbFormat = sizeof(WAVEFORMATEX),
3344 .pbFormat = (BYTE *)&pin_format,
3346 IAMMultiMediaStream *mmstream = create_ammultimediastream();
3347 IAudioMediaStream *audio_stream;
3348 struct testfilter source;
3349 IGraphBuilder *graph;
3350 IMediaStream *stream;
3351 WAVEFORMATEX format;
3352 HRESULT hr;
3353 ULONG ref;
3354 IPin *pin;
3356 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
3357 ok(hr == S_OK, "Got hr %#x.\n", hr);
3358 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
3359 ok(hr == S_OK, "Got hr %#x.\n", hr);
3360 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
3361 ok(hr == S_OK, "Got hr %#x.\n", hr);
3363 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
3364 ok(hr == S_OK, "Got hr %#x.\n", hr);
3365 ok(!!graph, "Expected non-NULL graph.\n");
3367 testfilter_init(&source);
3369 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, L"source");
3370 ok(hr == S_OK, "Got hr %#x.\n", hr);
3372 hr = IAudioMediaStream_GetFormat(audio_stream, NULL);
3373 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
3375 hr = IAudioMediaStream_GetFormat(audio_stream, &format);
3376 ok(hr == MS_E_NOSTREAM, "Got hr %#x.\n", hr);
3378 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
3379 ok(hr == S_OK, "Got hr %#x.\n", hr);
3381 memset(&format, 0xcc, sizeof(format));
3382 hr = IAudioMediaStream_GetFormat(audio_stream, &format);
3383 ok(hr == S_OK, "Got hr %#x.\n", hr);
3384 ok(format.wFormatTag == WAVE_FORMAT_PCM, "Got tag %#x.\n", format.wFormatTag);
3385 ok(format.nChannels == 2, "Got %u channels.\n", format.nChannels);
3386 ok(format.nSamplesPerSec == 44100, "Got sample rate %u.\n", format.nSamplesPerSec);
3387 ok(format.nAvgBytesPerSec == 176400, "Got %u bytes/sec.\n", format.nAvgBytesPerSec);
3388 ok(format.nBlockAlign == 4, "Got alignment %u.\n", format.nBlockAlign);
3389 ok(format.wBitsPerSample == 16, "Got %u bits/sample.\n", format.wBitsPerSample);
3390 ok(!format.cbSize, "Got extra size %u.\n", format.cbSize);
3392 hr = IGraphBuilder_Disconnect(graph, pin);
3393 ok(hr == S_OK, "Got hr %#x.\n", hr);
3394 hr = IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
3395 ok(hr == S_OK, "Got hr %#x.\n", hr);
3397 hr = IAudioMediaStream_GetFormat(audio_stream, &format);
3398 ok(hr == MS_E_NOSTREAM, "Got hr %#x.\n", hr);
3400 ref = IAMMultiMediaStream_Release(mmstream);
3401 ok(!ref, "Got outstanding refcount %d.\n", ref);
3402 ref = IGraphBuilder_Release(graph);
3403 ok(!ref, "Got outstanding refcount %d.\n", ref);
3404 IPin_Release(pin);
3405 IAudioMediaStream_Release(audio_stream);
3406 ref = IMediaStream_Release(stream);
3407 ok(!ref, "Got outstanding refcount %d.\n", ref);
3408 ref = IBaseFilter_Release(&source.filter.IBaseFilter_iface);
3409 ok(!ref, "Got outstanding refcount %d.\n", ref);
3412 static HRESULT set_audiostream_format(const WAVEFORMATEX *format)
3414 IAMMultiMediaStream *mmstream = create_ammultimediastream();
3415 IAudioMediaStream *audio_stream;
3416 IMediaStream *stream;
3417 HRESULT hr;
3418 ULONG ref;
3420 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
3421 ok(hr == S_OK, "Got hr %#x.\n", hr);
3422 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
3423 ok(hr == S_OK, "Got hr %#x.\n", hr);
3425 hr = IAudioMediaStream_SetFormat(audio_stream, format);
3427 ref = IAMMultiMediaStream_Release(mmstream);
3428 ok(!ref, "Got outstanding refcount %d.\n", ref);
3429 IAudioMediaStream_Release(audio_stream);
3430 ref = IMediaStream_Release(stream);
3431 ok(!ref, "Got outstanding refcount %d.\n", ref);
3433 return hr;
3436 static void test_audiostream_set_format(void)
3438 static const WAVEFORMATEX valid_format =
3440 .wFormatTag = WAVE_FORMAT_PCM,
3441 .nChannels = 2,
3442 .nSamplesPerSec = 44100,
3443 .wBitsPerSample = 16,
3444 .nBlockAlign = 4,
3445 .nAvgBytesPerSec = 4 * 44100,
3448 const AM_MEDIA_TYPE mt =
3450 .majortype = MEDIATYPE_Audio,
3451 .subtype = MEDIASUBTYPE_PCM,
3452 .formattype = FORMAT_WaveFormatEx,
3453 .cbFormat = sizeof(WAVEFORMATEX),
3454 .pbFormat = (BYTE *)&valid_format,
3457 WAVEFORMATEXTENSIBLE extensible_format;
3458 IAudioMediaStream *audio_stream;
3459 IAMMultiMediaStream *mmstream;
3460 struct testfilter source;
3461 IGraphBuilder *graph;
3462 IMediaStream *stream;
3463 WAVEFORMATEX format;
3464 HRESULT hr;
3465 ULONG ref;
3466 IPin *pin;
3468 hr = set_audiostream_format(&valid_format);
3469 ok(hr == S_OK, "Got hr %#x.\n", hr);
3470 hr = set_audiostream_format(NULL);
3471 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
3473 extensible_format.Format = valid_format;
3474 extensible_format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
3475 extensible_format.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
3476 extensible_format.Samples.wValidBitsPerSample = valid_format.wBitsPerSample;
3477 extensible_format.dwChannelMask = KSAUDIO_SPEAKER_STEREO;
3478 extensible_format.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
3479 hr = set_audiostream_format(&extensible_format.Format);
3480 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
3482 format = valid_format;
3483 format.nBlockAlign = 1;
3484 hr = set_audiostream_format(&format);
3485 ok(hr == S_OK, "Got hr %#x.\n", hr);
3487 format = valid_format;
3488 format.nAvgBytesPerSec = 1234;
3489 hr = set_audiostream_format(&format);
3490 ok(hr == S_OK, "Got hr %#x.\n", hr);
3492 mmstream = create_ammultimediastream();
3494 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
3495 ok(hr == S_OK, "Got hr %#x.\n", hr);
3496 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
3497 ok(hr == S_OK, "Got hr %#x.\n", hr);
3499 hr = IAudioMediaStream_SetFormat(audio_stream, &valid_format);
3500 ok(hr == S_OK, "Got hr %#x.\n", hr);
3502 hr = IAudioMediaStream_GetFormat(audio_stream, &format);
3503 ok(hr == MS_E_NOSTREAM, "Got hr %#x.\n", hr);
3505 format = valid_format;
3506 format.nChannels = 1;
3507 hr = IAudioMediaStream_SetFormat(audio_stream, &format);
3508 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
3510 format = valid_format;
3511 format.nSamplesPerSec = 11025;
3512 hr = IAudioMediaStream_SetFormat(audio_stream, &format);
3513 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
3515 format = valid_format;
3516 format.nAvgBytesPerSec = 1234;
3517 hr = IAudioMediaStream_SetFormat(audio_stream, &format);
3518 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
3520 format = valid_format;
3521 format.nBlockAlign = 1;
3522 hr = IAudioMediaStream_SetFormat(audio_stream, &format);
3523 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
3525 format = valid_format;
3526 format.wBitsPerSample = 8;
3527 hr = IAudioMediaStream_SetFormat(audio_stream, &format);
3528 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
3530 format = valid_format;
3531 format.cbSize = 1;
3532 hr = IAudioMediaStream_SetFormat(audio_stream, &format);
3533 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
3535 hr = IAudioMediaStream_SetFormat(audio_stream, &valid_format);
3536 ok(hr == S_OK, "Got hr %#x.\n", hr);
3538 ref = IAMMultiMediaStream_Release(mmstream);
3539 ok(!ref, "Got outstanding refcount %d.\n", ref);
3540 IAudioMediaStream_Release(audio_stream);
3541 ref = IMediaStream_Release(stream);
3542 ok(!ref, "Got outstanding refcount %d.\n", ref);
3544 mmstream = create_ammultimediastream();
3546 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
3547 ok(hr == S_OK, "Got hr %#x.\n", hr);
3548 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
3549 ok(hr == S_OK, "Got hr %#x.\n", hr);
3550 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
3551 ok(hr == S_OK, "Got hr %#x.\n", hr);
3553 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
3554 ok(hr == S_OK, "Got hr %#x.\n", hr);
3555 ok(!!graph, "Expected non-NULL graph.\n");
3557 testfilter_init(&source);
3559 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
3560 ok(hr == S_OK, "Got hr %#x.\n", hr);
3562 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
3563 ok(hr == S_OK, "Got hr %#x.\n", hr);
3565 format = valid_format;
3566 format.nChannels = 1;
3567 hr = IAudioMediaStream_SetFormat(audio_stream, &format);
3568 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
3570 hr = IGraphBuilder_Disconnect(graph, pin);
3571 ok(hr == S_OK, "Got hr %#x.\n", hr);
3572 hr = IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
3573 ok(hr == S_OK, "Got hr %#x.\n", hr);
3575 format = valid_format;
3576 format.nChannels = 1;
3577 hr = IAudioMediaStream_SetFormat(audio_stream, &format);
3578 ok(hr == S_OK, "Got hr %#x.\n", hr);
3580 ref = IAMMultiMediaStream_Release(mmstream);
3581 ok(!ref, "Got outstanding refcount %d.\n", ref);
3582 ref = IGraphBuilder_Release(graph);
3583 ok(!ref, "Got outstanding refcount %d.\n", ref);
3584 IPin_Release(pin);
3585 IAudioMediaStream_Release(audio_stream);
3586 ref = IMediaStream_Release(stream);
3587 ok(!ref, "Got outstanding refcount %d.\n", ref);
3588 ref = IBaseFilter_Release(&source.filter.IBaseFilter_iface);
3589 ok(!ref, "Got outstanding refcount %d.\n", ref);
3592 static void test_audiostream_receive_connection(void)
3594 WAVEFORMATEXTENSIBLE extensible_format;
3595 IAudioMediaStream *audio_stream;
3596 IAMMultiMediaStream *mmstream;
3597 struct testfilter source;
3598 IGraphBuilder *graph;
3599 IMediaStream *stream;
3600 WAVEFORMATEX format;
3601 AM_MEDIA_TYPE mt;
3602 HRESULT hr;
3603 ULONG ref;
3604 IPin *pin;
3606 mmstream = create_ammultimediastream();
3607 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
3608 ok(hr == S_OK, "Got hr %#x.\n", hr);
3609 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
3610 ok(hr == S_OK, "Got hr %#x.\n", hr);
3611 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
3612 ok(hr == S_OK, "Got hr %#x.\n", hr);
3613 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
3614 ok(hr == S_OK, "Got hr %#x.\n", hr);
3615 ok(graph != NULL, "Expected non-null graph\n");
3616 testfilter_init(&source);
3617 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
3618 ok(hr == S_OK, "Got hr %#x.\n", hr);
3620 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &audio_mt);
3621 ok(hr == S_OK, "Got hr %#x.\n", hr);
3622 IGraphBuilder_Disconnect(graph, pin);
3623 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
3625 mt = audio_mt;
3626 mt.majortype = GUID_NULL;
3627 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &mt);
3628 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
3630 mt = audio_mt;
3631 mt.subtype = MEDIASUBTYPE_RGB24;
3632 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
3633 ok(hr == S_OK, "Got hr %#x.\n", hr);
3634 IGraphBuilder_Disconnect(graph, pin);
3635 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
3637 mt = audio_mt;
3638 mt.formattype = GUID_NULL;
3639 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &mt);
3640 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
3642 mt = audio_mt;
3643 mt.cbFormat = sizeof(WAVEFORMATEX) - 1;
3644 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
3645 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
3647 extensible_format.Format = audio_format;
3648 extensible_format.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
3649 extensible_format.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
3650 extensible_format.Samples.wValidBitsPerSample = audio_format.wBitsPerSample;
3651 extensible_format.dwChannelMask = KSAUDIO_SPEAKER_STEREO;
3652 extensible_format.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
3653 mt = audio_mt;
3654 mt.cbFormat = sizeof(extensible_format);
3655 mt.pbFormat = (BYTE *)&extensible_format;
3656 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
3657 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
3659 hr = IAudioMediaStream_SetFormat(audio_stream, &audio_format);
3660 ok(hr == S_OK, "Got hr %#x.\n", hr);
3662 format = audio_format;
3663 format.nChannels = 2;
3664 mt = audio_mt;
3665 mt.pbFormat = (BYTE *)&format;
3666 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
3667 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
3669 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &audio_mt);
3670 ok(hr == S_OK, "Got hr %#x.\n", hr);
3671 IGraphBuilder_Disconnect(graph, pin);
3672 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
3674 ref = IAMMultiMediaStream_Release(mmstream);
3675 ok(!ref, "Got outstanding refcount %d.\n", ref);
3676 ref = IGraphBuilder_Release(graph);
3677 ok(!ref, "Got outstanding refcount %d.\n", ref);
3678 IPin_Release(pin);
3679 IAudioMediaStream_Release(audio_stream);
3680 ref = IMediaStream_Release(stream);
3681 ok(!ref, "Got outstanding refcount %d.\n", ref);
3682 ref = IBaseFilter_Release(&source.filter.IBaseFilter_iface);
3683 ok(!ref, "Got outstanding refcount %d.\n", ref);
3686 static void test_ddrawstream_receive_connection(void)
3688 static const VIDEOINFOHEADER req_vih;
3689 IDirectDrawMediaStream *ddraw_stream;
3690 IAMMultiMediaStream *mmstream;
3691 struct testfilter source;
3692 DDSURFACEDESC format;
3693 IMediaStream *stream;
3694 VIDEOINFO video_info;
3695 AM_MEDIA_TYPE mt;
3696 HRESULT hr;
3697 ULONG ref;
3698 IPin *pin;
3699 int i;
3701 static const VIDEOINFO yuy2_video_info =
3703 .bmiHeader.biSize = sizeof(BITMAPINFOHEADER),
3704 .bmiHeader.biWidth = 333,
3705 .bmiHeader.biHeight = -444,
3706 .bmiHeader.biPlanes = 1,
3707 .bmiHeader.biBitCount = 16,
3708 .bmiHeader.biCompression = MAKEFOURCC('Y', 'U', 'Y', '2'),
3711 const AM_MEDIA_TYPE yuy2_mt =
3713 .majortype = MEDIATYPE_Video,
3714 .subtype = MEDIASUBTYPE_YUY2,
3715 .formattype = FORMAT_VideoInfo,
3716 .cbFormat = sizeof(VIDEOINFOHEADER),
3717 .pbFormat = (BYTE *)&yuy2_video_info,
3720 const AM_MEDIA_TYPE video_mt =
3722 .majortype = MEDIATYPE_Video,
3723 .subtype = MEDIASUBTYPE_RGB8,
3724 .formattype = FORMAT_VideoInfo,
3725 .cbFormat = sizeof(VIDEOINFOHEADER),
3726 .pbFormat = (BYTE *)&req_vih,
3729 static const GUID *subtypes[] =
3731 &MEDIASUBTYPE_RGB24,
3732 &MEDIASUBTYPE_RGB32,
3733 &MEDIASUBTYPE_RGB555,
3734 &MEDIASUBTYPE_RGB565,
3735 &MEDIASUBTYPE_RGB1,
3736 &MEDIASUBTYPE_RGB4,
3737 &MEDIASUBTYPE_ARGB32,
3738 &MEDIASUBTYPE_ARGB1555,
3739 &MEDIASUBTYPE_ARGB4444,
3740 &MEDIASUBTYPE_Avi,
3741 &MEDIASUBTYPE_I420,
3742 &MEDIASUBTYPE_AYUV,
3743 &MEDIASUBTYPE_YV12,
3744 &MEDIASUBTYPE_YUY2,
3745 &MEDIASUBTYPE_UYVY,
3746 &MEDIASUBTYPE_YVYU,
3747 &MEDIASUBTYPE_NV12,
3748 &GUID_NULL,
3751 mmstream = create_ammultimediastream();
3752 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
3753 ok(hr == S_OK, "Got hr %#x.\n", hr);
3754 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
3755 ok(hr == S_OK, "Got hr %#x.\n", hr);
3756 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
3757 ok(hr == S_OK, "Got hr %#x.\n", hr);
3759 testfilter_init(&source);
3761 mt = video_mt;
3762 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &mt);
3763 ok(hr == S_OK, "Got hr %#x.\n", hr);
3764 hr = IPin_Disconnect(pin);
3765 ok(hr == S_OK, "Got hr %#x.\n", hr);
3767 for (i = 0; i < ARRAY_SIZE(subtypes); ++i)
3769 mt = video_mt;
3770 mt.subtype = *subtypes[i];
3771 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &mt);
3772 ok(hr == (i < 4 ? S_OK : VFW_E_TYPE_NOT_ACCEPTED), "Got hr %#x.\n", hr);
3773 if (hr == S_OK)
3775 hr = IPin_Disconnect(pin);
3776 ok(hr == S_OK, "Got hr %#x.\n", hr);
3780 format = rgb8_format;
3781 format.dwFlags = DDSD_WIDTH;
3782 format.dwWidth = 222;
3783 format.dwHeight = 555;
3784 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &format, NULL);
3785 ok(hr == S_OK, "Got hr %#x.\n", hr);
3787 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb32_mt);
3788 ok(hr == S_OK, "Got hr %#x.\n", hr);
3789 hr = IPin_Disconnect(pin);
3790 ok(hr == S_OK, "Got hr %#x.\n", hr);
3792 format = rgb8_format;
3793 format.dwFlags = DDSD_HEIGHT;
3794 format.dwWidth = 333;
3795 format.dwHeight = 444;
3796 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &format, NULL);
3797 ok(hr == S_OK, "Got hr %#x.\n", hr);
3799 video_info = rgb555_video_info;
3800 video_info.bmiHeader.biWidth = 333;
3801 video_info.bmiHeader.biHeight = 444;
3802 mt = rgb555_mt;
3803 mt.pbFormat = (BYTE *)&video_info;
3804 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &mt);
3805 ok(hr == S_OK, "Got hr %#x.\n", hr);
3806 hr = IPin_Disconnect(pin);
3807 ok(hr == S_OK, "Got hr %#x.\n", hr);
3809 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb32_mt);
3810 ok(hr == S_OK, "Got hr %#x.\n", hr);
3811 hr = IPin_Disconnect(pin);
3812 ok(hr == S_OK, "Got hr %#x.\n", hr);
3814 video_info = rgb32_video_info;
3815 video_info.bmiHeader.biWidth = 332;
3816 video_info.bmiHeader.biHeight = 444;
3817 mt = rgb32_mt;
3818 mt.pbFormat = (BYTE *)&video_info;
3819 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &mt);
3820 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
3822 video_info = rgb32_video_info;
3823 video_info.bmiHeader.biWidth = 333;
3824 video_info.bmiHeader.biHeight = 443;
3825 mt = rgb32_mt;
3826 mt.pbFormat = (BYTE *)&video_info;
3827 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &mt);
3828 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
3830 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb8_format, NULL);
3831 ok(hr == S_OK, "Got hr %#x.\n", hr);
3833 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb555_mt);
3834 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
3836 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb8_mt);
3837 ok(hr == S_OK, "Got hr %#x.\n", hr);
3838 hr = IPin_Disconnect(pin);
3839 ok(hr == S_OK, "Got hr %#x.\n", hr);
3841 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb555_format, NULL);
3842 ok(hr == S_OK, "Got hr %#x.\n", hr);
3844 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb565_mt);
3845 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
3847 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb555_mt);
3848 ok(hr == S_OK, "Got hr %#x.\n", hr);
3849 hr = IPin_Disconnect(pin);
3850 ok(hr == S_OK, "Got hr %#x.\n", hr);
3852 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb565_format, NULL);
3853 ok(hr == S_OK, "Got hr %#x.\n", hr);
3855 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb24_mt);
3856 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
3858 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb565_mt);
3859 ok(hr == S_OK, "Got hr %#x.\n", hr);
3860 hr = IPin_Disconnect(pin);
3861 ok(hr == S_OK, "Got hr %#x.\n", hr);
3863 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb24_format, NULL);
3864 ok(hr == S_OK, "Got hr %#x.\n", hr);
3866 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb32_mt);
3867 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
3869 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb24_mt);
3870 ok(hr == S_OK, "Got hr %#x.\n", hr);
3871 hr = IPin_Disconnect(pin);
3872 ok(hr == S_OK, "Got hr %#x.\n", hr);
3874 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb32_format, NULL);
3875 ok(hr == S_OK, "Got hr %#x.\n", hr);
3877 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb8_mt);
3878 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
3880 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb32_mt);
3881 ok(hr == S_OK, "Got hr %#x.\n", hr);
3882 hr = IPin_Disconnect(pin);
3883 ok(hr == S_OK, "Got hr %#x.\n", hr);
3885 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &yuy2_format, NULL);
3886 ok(hr == S_OK, "Got hr %#x.\n", hr);
3888 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &yuy2_mt);
3889 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
3891 format = yuy2_format;
3892 format.ddpfPixelFormat.u2.dwRBitMask = 0xf800;
3893 format.ddpfPixelFormat.u3.dwGBitMask = 0x07e0;
3894 format.ddpfPixelFormat.u4.dwBBitMask = 0x001f;
3895 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &format, NULL);
3896 ok(hr == S_OK, "Got hr %#x.\n", hr);
3898 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb565_mt);
3899 ok(hr == VFW_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
3901 format = rgb8_format;
3902 format.dwFlags = 0;
3903 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &format, NULL);
3904 ok(hr == S_OK, "Got hr %#x.\n", hr);
3906 hr = IPin_ReceiveConnection(pin, &source.source.pin.IPin_iface, &rgb565_mt);
3907 ok(hr == S_OK, "Got hr %#x.\n", hr);
3908 hr = IPin_Disconnect(pin);
3909 ok(hr == S_OK, "Got hr %#x.\n", hr);
3911 ref = IAMMultiMediaStream_Release(mmstream);
3912 ok(!ref, "Got outstanding refcount %d.\n", ref);
3913 IPin_Release(pin);
3914 IDirectDrawMediaStream_Release(ddraw_stream);
3915 ref = IMediaStream_Release(stream);
3916 ok(!ref, "Got outstanding refcount %d.\n", ref);
3917 ref = IBaseFilter_Release(&source.filter.IBaseFilter_iface);
3918 ok(!ref, "Got outstanding refcount %d.\n", ref);
3921 static void test_audiostream_receive(void)
3923 ALLOCATOR_PROPERTIES properties =
3925 .cBuffers = 3,
3926 .cbBuffer = 16,
3927 .cbAlign = 1,
3930 IAMMultiMediaStream *mmstream = create_ammultimediastream();
3931 ALLOCATOR_PROPERTIES actual;
3932 struct testfilter source;
3933 IMemAllocator *allocator;
3934 IGraphBuilder *graph;
3935 IMediaStream *stream;
3936 IMediaSample *sample1;
3937 IMediaSample *sample2;
3938 IMediaSample *sample3;
3939 HRESULT hr;
3940 ULONG ref;
3941 IPin *pin;
3943 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
3944 ok(hr == S_OK, "Got hr %#x.\n", hr);
3945 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
3946 ok(hr == S_OK, "Got hr %#x.\n", hr);
3947 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
3948 ok(hr == S_OK, "Got hr %#x.\n", hr);
3949 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
3950 ok(hr == S_OK, "Got hr %#x.\n", hr);
3951 ok(graph != NULL, "Expected non-NULL graph.\n");
3952 testfilter_init(&source);
3953 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
3954 ok(hr == S_OK, "Got hr %#x.\n", hr);
3955 hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER, &IID_IMemAllocator, (void **)&allocator);
3956 ok(hr == S_OK, "Got hr %#x.\n", hr);
3957 hr = IMemAllocator_SetProperties(allocator, &properties, &actual);
3958 ok(hr == S_OK, "Got hr %#x.\n", hr);
3959 hr = IMemAllocator_Commit(allocator);
3960 ok(hr == S_OK, "Got hr %#x.\n", hr);
3962 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &audio_mt);
3963 ok(hr == S_OK, "Got hr %#x.\n", hr);
3965 hr = IMemAllocator_GetBuffer(allocator, &sample1, NULL, NULL, 0);
3966 ok(hr == S_OK, "Got hr %#x.\n", hr);
3967 hr = IMemInputPin_Receive(source.source.pMemInputPin, sample1);
3968 ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
3969 ref = IMediaSample_Release(sample1);
3970 ok(!ref, "Got outstanding refcount %d.\n", ref);
3972 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
3973 ok(hr == S_OK, "Got hr %#x.\n", hr);
3975 hr = IMemAllocator_GetBuffer(allocator, &sample1, NULL, NULL, 0);
3976 ok(hr == S_OK, "Got hr %#x.\n", hr);
3977 hr = IMemInputPin_Receive(source.source.pMemInputPin, sample1);
3978 ok(hr == S_OK, "Got hr %#x.\n", hr);
3979 ref = get_refcount(sample1);
3980 ok(ref == 2, "Got unexpected refcount %d.\n", ref);
3982 hr = IMemAllocator_GetBuffer(allocator, &sample2, NULL, NULL, 0);
3983 ok(hr == S_OK, "Got hr %#x.\n", hr);
3984 hr = IMemInputPin_Receive(source.source.pMemInputPin, sample2);
3985 ok(hr == S_OK, "Got hr %#x.\n", hr);
3986 ref = get_refcount(sample2);
3987 ok(ref == 2, "Got unexpected refcount %d.\n", ref);
3989 hr = IPin_EndOfStream(pin);
3990 ok(hr == S_OK, "Got hr %#x.\n", hr);
3992 hr = IMemAllocator_GetBuffer(allocator, &sample3, NULL, NULL, 0);
3993 ok(hr == S_OK, "Got hr %#x.\n", hr);
3994 hr = IMemInputPin_Receive(source.source.pMemInputPin, sample3);
3995 ok(hr == S_OK, "Got hr %#x.\n", hr);
3996 ref = get_refcount(sample3);
3997 ok(ref == 2, "Got unexpected refcount %d.\n", ref);
3999 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4000 ok(hr == S_OK, "Got hr %#x.\n", hr);
4002 ref = IMediaSample_Release(sample1);
4003 ok(!ref, "Got outstanding refcount %d.\n", ref);
4004 ref = IMediaSample_Release(sample2);
4005 ok(!ref, "Got outstanding refcount %d.\n", ref);
4006 ref = IMediaSample_Release(sample3);
4007 ok(!ref, "Got outstanding refcount %d.\n", ref);
4009 hr = IMemAllocator_GetBuffer(allocator, &sample1, NULL, NULL, 0);
4010 ok(hr == S_OK, "Got hr %#x.\n", hr);
4011 hr = IMemInputPin_Receive(source.source.pMemInputPin, sample1);
4012 ok(hr == VFW_E_WRONG_STATE, "Got hr %#x.\n", hr);
4013 ref = IMediaSample_Release(sample1);
4014 ok(!ref, "Got outstanding refcount %d.\n", ref);
4016 IGraphBuilder_Disconnect(graph, pin);
4017 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
4019 hr = IMemAllocator_Decommit(allocator);
4020 ok(hr == S_OK, "Got hr %#x.\n", hr);
4022 ref = IAMMultiMediaStream_Release(mmstream);
4023 ok(!ref, "Got outstanding refcount %d.\n", ref);
4024 ref = IGraphBuilder_Release(graph);
4025 ok(!ref, "Got outstanding refcount %d.\n", ref);
4026 IPin_Release(pin);
4027 ref = IMediaStream_Release(stream);
4028 ok(!ref, "Got outstanding refcount %d.\n", ref);
4029 ref = IMemAllocator_Release(allocator);
4030 ok(!ref, "Got outstanding refcount %d.\n", ref);
4033 static void test_audiostream_initialize(void)
4035 IAMMediaStream *stream;
4036 STREAM_TYPE type;
4037 MSPID mspid;
4038 HRESULT hr;
4039 ULONG ref;
4041 hr = CoCreateInstance(&CLSID_AMAudioStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream);
4042 ok(hr == S_OK, "Got hr %#x.\n", hr);
4044 /* Crashes on native. */
4045 if (0)
4047 hr = IAMMediaStream_Initialize(stream, NULL, 0, NULL, STREAMTYPE_WRITE);
4048 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
4051 hr = IAMMediaStream_Initialize(stream, NULL, 0, &test_mspid, STREAMTYPE_WRITE);
4052 ok(hr == S_OK, "Got hr %#x.\n", hr);
4054 hr = IAMMediaStream_GetInformation(stream, &mspid, &type);
4055 ok(hr == S_OK, "Got hr %#x.\n", hr);
4056 ok(IsEqualGUID(&mspid, &test_mspid), "Got mspid %s.\n", wine_dbgstr_guid(&mspid));
4057 ok(type == STREAMTYPE_WRITE, "Got type %u.\n", type);
4059 hr = IAMMediaStream_Initialize(stream, NULL, 0, &MSPID_PrimaryAudio, STREAMTYPE_READ);
4060 ok(hr == S_OK, "Got hr %#x.\n", hr);
4062 hr = IAMMediaStream_GetInformation(stream, &mspid, &type);
4063 ok(hr == S_OK, "Got hr %#x.\n", hr);
4064 ok(IsEqualGUID(&mspid, &MSPID_PrimaryAudio), "Got mspid %s.\n", wine_dbgstr_guid(&mspid));
4065 ok(type == STREAMTYPE_READ, "Got type %u.\n", type);
4067 ref = IAMMediaStream_Release(stream);
4068 ok(!ref, "Got outstanding refcount %d.\n", ref);
4071 static void test_audiostream_begin_flush_end_flush(void)
4073 IAMMultiMediaStream *mmstream = create_ammultimediastream();
4074 IAudioStreamSample *stream_sample;
4075 IAudioMediaStream *audio_stream;
4076 IMediaSample *media_sample;
4077 struct testfilter source;
4078 IAudioData *audio_data;
4079 IGraphBuilder *graph;
4080 IMediaStream *stream;
4081 HRESULT hr;
4082 ULONG ref;
4083 IPin *pin;
4085 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
4086 ok(hr == S_OK, "Got hr %#x.\n", hr);
4087 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
4088 ok(hr == S_OK, "Got hr %#x.\n", hr);
4089 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
4090 ok(hr == S_OK, "Got hr %#x.\n", hr);
4091 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
4092 ok(hr == S_OK, "Got hr %#x.\n", hr);
4093 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
4094 ok(hr == S_OK, "Got hr %#x.\n", hr);
4095 ok(graph != NULL, "Expected non-NULL graph.\n");
4096 testfilter_init(&source);
4097 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
4098 ok(hr == S_OK, "Got hr %#x.\n", hr);
4099 hr = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER, &IID_IAudioData, (void **)&audio_data);
4100 ok(hr == S_OK, "Got hr %#x.\n", hr);
4101 hr = IAudioData_SetBuffer(audio_data, 16, NULL, 0);
4102 ok(hr == S_OK, "Got hr %#x.\n", hr);
4103 hr = IAudioMediaStream_CreateSample(audio_stream, audio_data, 0, &stream_sample);
4104 ok(hr == S_OK, "Got hr %#x.\n", hr);
4106 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &audio_mt);
4107 ok(hr == S_OK, "Got hr %#x.\n", hr);
4109 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4110 ok(hr == S_OK, "Got hr %#x.\n", hr);
4112 hr = BaseOutputPinImpl_GetDeliveryBuffer(&source.source, &media_sample, NULL, NULL, 0);
4113 ok(hr == S_OK, "Got hr %#x.\n", hr);
4114 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
4115 ok(hr == S_OK, "Got hr %#x.\n", hr);
4116 ref = get_refcount(media_sample);
4117 ok(ref == 2, "Got unexpected refcount %d.\n", ref);
4119 hr = IPin_EndOfStream(pin);
4120 ok(hr == S_OK, "Got hr %#x.\n", hr);
4122 hr = IPin_BeginFlush(pin);
4123 ok(hr == S_OK, "Got hr %#x.\n", hr);
4125 ref = IMediaSample_Release(media_sample);
4126 ok(!ref, "Got outstanding refcount %d.\n", ref);
4128 hr = BaseOutputPinImpl_GetDeliveryBuffer(&source.source, &media_sample, NULL, NULL, 0);
4129 ok(hr == S_OK, "Got hr %#x.\n", hr);
4130 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
4131 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
4133 ref = IMediaSample_Release(media_sample);
4134 ok(!ref, "Got outstanding refcount %d.\n", ref);
4136 hr = IAudioStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
4137 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
4139 hr = IPin_EndOfStream(pin);
4140 ok(hr == E_FAIL, "Got hr %#x.\n", hr);
4142 hr = IPin_EndFlush(pin);
4143 ok(hr == S_OK, "Got hr %#x.\n", hr);
4145 hr = BaseOutputPinImpl_GetDeliveryBuffer(&source.source, &media_sample, NULL, NULL, 0);
4146 ok(hr == S_OK, "Got hr %#x.\n", hr);
4147 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
4148 ok(hr == S_OK, "Got hr %#x.\n", hr);
4149 ref = IMediaSample_Release(media_sample);
4150 ok(ref == 1, "Got outstanding refcount %d.\n", ref);
4152 hr = IPin_EndOfStream(pin);
4153 ok(hr == S_OK, "Got hr %#x.\n", hr);
4155 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4156 ok(hr == S_OK, "Got hr %#x.\n", hr);
4158 IGraphBuilder_Disconnect(graph, pin);
4159 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
4161 ref = IAudioStreamSample_Release(stream_sample);
4162 ok(!ref, "Got outstanding refcount %d.\n", ref);
4163 ref = IAudioData_Release(audio_data);
4164 ok(!ref, "Got outstanding refcount %d.\n", ref);
4165 ref = IAMMultiMediaStream_Release(mmstream);
4166 ok(!ref, "Got outstanding refcount %d.\n", ref);
4167 ref = IGraphBuilder_Release(graph);
4168 ok(!ref, "Got outstanding refcount %d.\n", ref);
4169 IPin_Release(pin);
4170 IAudioMediaStream_Release(audio_stream);
4171 ref = IMediaStream_Release(stream);
4172 ok(!ref, "Got outstanding refcount %d.\n", ref);
4175 static IMediaSample *ammediastream_allocate_sample(struct testfilter *source, const BYTE *input_data, DWORD input_length)
4177 IMediaSample *sample;
4178 BYTE *sample_data;
4179 HRESULT hr;
4181 hr = BaseOutputPinImpl_GetDeliveryBuffer(&source->source, &sample, NULL, NULL, 0);
4182 ok(hr == S_OK, "Got hr %#x.\n", hr);
4184 hr = IMediaSample_GetPointer(sample, &sample_data);
4185 ok(hr == S_OK, "Got hr %#x.\n", hr);
4187 hr = IMediaSample_SetActualDataLength(sample, input_length);
4188 ok(hr == S_OK, "Got hr %#x.\n", hr);
4190 memcpy(sample_data, input_data, input_length);
4192 return sample;
4195 static void test_audiostream_new_segment(void)
4197 IAMMultiMediaStream *mmstream = create_ammultimediastream();
4198 static const BYTE test_data[8] = { 0 };
4199 IAudioStreamSample *stream_sample;
4200 IAudioMediaStream *audio_stream;
4201 IMemInputPin *mem_input_pin;
4202 IMediaSample *media_sample;
4203 struct testfilter source;
4204 IAudioData *audio_data;
4205 STREAM_TIME start_time;
4206 STREAM_TIME end_time;
4207 IGraphBuilder *graph;
4208 IMediaStream *stream;
4209 HRESULT hr;
4210 ULONG ref;
4211 IPin *pin;
4213 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
4214 ok(hr == S_OK, "Got hr %#x.\n", hr);
4215 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
4216 ok(hr == S_OK, "Got hr %#x.\n", hr);
4217 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
4218 ok(hr == S_OK, "Got hr %#x.\n", hr);
4219 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
4220 ok(hr == S_OK, "Got hr %#x.\n", hr);
4221 hr = IMediaStream_QueryInterface(stream, &IID_IMemInputPin, (void **)&mem_input_pin);
4222 ok(hr == S_OK, "Got hr %#x.\n", hr);
4223 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
4224 ok(hr == S_OK, "Got hr %#x.\n", hr);
4225 ok(graph != NULL, "Expected non-NULL graph.\n");
4226 testfilter_init(&source);
4227 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
4228 ok(hr == S_OK, "Got hr %#x.\n", hr);
4229 hr = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER, &IID_IAudioData, (void **)&audio_data);
4230 ok(hr == S_OK, "Got hr %#x.\n", hr);
4231 hr = IAudioMediaStream_CreateSample(audio_stream, audio_data, 0, &stream_sample);
4232 ok(hr == S_OK, "Got hr %#x.\n", hr);
4233 hr = IAudioData_SetBuffer(audio_data, 5, NULL, 0);
4234 ok(hr == S_OK, "Got hr %#x.\n", hr);
4236 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &audio_mt);
4237 ok(hr == S_OK, "Got hr %#x.\n", hr);
4238 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4239 ok(hr == S_OK, "Got hr %#x.\n", hr);
4241 hr = IPin_NewSegment(pin, 11111111, 22222222, 1.0);
4242 ok(hr == S_OK, "Got hr %#x.\n", hr);
4244 media_sample = ammediastream_allocate_sample(&source, test_data, 5);
4245 start_time = 12345678;
4246 end_time = 23456789;
4247 hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
4248 ok(hr == S_OK, "Got hr %#x.\n", hr);
4249 hr = IMemInputPin_Receive(mem_input_pin, media_sample);
4250 ok(hr == S_OK, "Got hr %#x.\n", hr);
4251 IMediaSample_Release(media_sample);
4253 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4254 ok(hr == S_OK, "Got hr %#x.\n", hr);
4256 start_time = 0xdeadbeefdeadbeef;
4257 end_time = 0xdeadbeefdeadbeef;
4258 hr = IAudioStreamSample_GetSampleTimes(stream_sample, &start_time, &end_time, NULL);
4259 ok(hr == S_OK, "Got hr %#x.\n", hr);
4260 ok(start_time == 23456789, "Got start time %s.\n", wine_dbgstr_longlong(start_time));
4261 ok(end_time == 23459057, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
4263 hr = IPin_NewSegment(pin, 11111111, 22222222, 2.0);
4264 ok(hr == S_OK, "Got hr %#x.\n", hr);
4266 media_sample = ammediastream_allocate_sample(&source, test_data, 5);
4267 start_time = 12345678;
4268 end_time = 23456789;
4269 hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
4270 ok(hr == S_OK, "Got hr %#x.\n", hr);
4271 hr = IMemInputPin_Receive(mem_input_pin, media_sample);
4272 ok(hr == S_OK, "Got hr %#x.\n", hr);
4273 IMediaSample_Release(media_sample);
4275 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4276 ok(hr == S_OK, "Got hr %#x.\n", hr);
4278 start_time = 0xdeadbeefdeadbeef;
4279 end_time = 0xdeadbeefdeadbeef;
4280 hr = IAudioStreamSample_GetSampleTimes(stream_sample, &start_time, &end_time, NULL);
4281 ok(hr == S_OK, "Got hr %#x.\n", hr);
4282 ok(start_time == 23456789, "Got start time %s.\n", wine_dbgstr_longlong(start_time));
4283 ok(end_time == 23459057, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
4285 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4286 ok(hr == S_OK, "Got hr %#x.\n", hr);
4287 IGraphBuilder_Disconnect(graph, pin);
4288 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
4290 ref = IAudioStreamSample_Release(stream_sample);
4291 ok(!ref, "Got outstanding refcount %d.\n", ref);
4292 ref = IAudioData_Release(audio_data);
4293 ok(!ref, "Got outstanding refcount %d.\n", ref);
4294 ref = IAMMultiMediaStream_Release(mmstream);
4295 ok(!ref, "Got outstanding refcount %d.\n", ref);
4296 ref = IGraphBuilder_Release(graph);
4297 ok(!ref, "Got outstanding refcount %d.\n", ref);
4298 IPin_Release(pin);
4299 IMemInputPin_Release(mem_input_pin);
4300 IAudioMediaStream_Release(audio_stream);
4301 ref = IMediaStream_Release(stream);
4302 ok(!ref, "Got outstanding refcount %d.\n", ref);
4305 static void CALLBACK apc_func(ULONG_PTR param)
4309 static IPin *ammediastream_pin;
4310 static IMemInputPin *ammediastream_mem_input_pin;
4311 static IMediaSample *ammediastream_media_sample;
4312 static DWORD ammediastream_sleep_time;
4313 static HRESULT ammediastream_expected_hr;
4315 static DWORD CALLBACK ammediastream_end_of_stream(void *param)
4317 HRESULT hr;
4319 Sleep(ammediastream_sleep_time);
4320 hr = IPin_EndOfStream(ammediastream_pin);
4321 ok(hr == ammediastream_expected_hr, "Got hr %#x.\n", hr);
4323 return 0;
4326 static DWORD CALLBACK ammediastream_receive(void *param)
4328 HRESULT hr;
4330 Sleep(ammediastream_sleep_time);
4331 hr = IMemInputPin_Receive(ammediastream_mem_input_pin, ammediastream_media_sample);
4332 ok(hr == ammediastream_expected_hr, "Got hr %#x.\n", hr);
4334 return 0;
4337 struct ammediastream_receive_release_param
4339 IMemInputPin *mem_input_pin;
4340 IMediaSample *media_sample;
4343 static DWORD CALLBACK ammediastream_receive_release(void *p)
4345 struct ammediastream_receive_release_param *param = (struct ammediastream_receive_release_param *)p;
4346 HRESULT hr;
4347 ULONG ref;
4349 hr = IMemInputPin_Receive(param->mem_input_pin, param->media_sample);
4350 ok(hr == S_OK, "Got hr %#x.\n", hr);
4352 ref = IMediaSample_Release(param->media_sample);
4353 ok(!ref, "Got outstanding refcount %d.\n", ref);
4355 free(p);
4357 return 0;
4360 static HANDLE ammediastream_async_receive_time(struct testfilter *source,
4361 REFERENCE_TIME start_time, REFERENCE_TIME end_time, const BYTE *input_data, DWORD input_length)
4363 struct ammediastream_receive_release_param *param;
4364 IMediaSample *sample;
4365 HRESULT hr;
4367 sample = ammediastream_allocate_sample(source, input_data, input_length);
4368 hr = IMediaSample_SetTime(sample, &start_time, &end_time);
4369 ok(hr == S_OK, "Got hr %#x.\n", hr);
4371 param = calloc(1, sizeof(*param));
4372 param->mem_input_pin = source->source.pMemInputPin;
4373 param->media_sample = sample;
4374 return CreateThread(NULL, 0, ammediastream_receive_release, param, 0, NULL);
4377 static IStreamSample *streamsample_sample;
4378 static DWORD streamsample_flags;
4379 static DWORD streamsample_timeout;
4380 static HRESULT streamsample_expected_hr;
4382 static DWORD CALLBACK streamsample_completion_status(void *param)
4384 HRESULT hr;
4386 hr = IStreamSample_CompletionStatus(streamsample_sample, streamsample_flags, streamsample_timeout);
4387 ok(hr == streamsample_expected_hr, "Got hr %#x.\n", hr);
4389 return 0;
4392 static void test_audiostreamsample_update(void)
4394 static const BYTE test_data[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
4395 IAMMultiMediaStream *mmstream = create_ammultimediastream();
4396 IAudioStreamSample *stream_sample;
4397 IAudioMediaStream *audio_stream;
4398 IMediaControl *media_control;
4399 IMemInputPin *mem_input_pin;
4400 IMediaSample *media_sample1;
4401 IMediaSample *media_sample2;
4402 struct testfilter source;
4403 IAudioData *audio_data;
4404 IGraphBuilder *graph;
4405 IMediaStream *stream;
4406 DWORD actual_length;
4407 BYTE buffer[6];
4408 HANDLE thread;
4409 HANDLE event;
4410 HRESULT hr;
4411 ULONG ref;
4412 IPin *pin;
4414 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
4415 ok(hr == S_OK, "Got hr %#x.\n", hr);
4416 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
4417 ok(hr == S_OK, "Got hr %#x.\n", hr);
4418 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
4419 ok(hr == S_OK, "Got hr %#x.\n", hr);
4420 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
4421 ok(hr == S_OK, "Got hr %#x.\n", hr);
4422 hr = IMediaStream_QueryInterface(stream, &IID_IMemInputPin, (void **)&mem_input_pin);
4423 ok(hr == S_OK, "Got hr %#x.\n", hr);
4424 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
4425 ok(hr == S_OK, "Got hr %#x.\n", hr);
4426 ok(graph != NULL, "Expected non-NULL graph.\n");
4427 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void **)&media_control);
4428 ok(hr == S_OK, "Got hr %#x.\n", hr);
4429 testfilter_init(&source);
4430 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
4431 ok(hr == S_OK, "Got hr %#x.\n", hr);
4432 hr = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER, &IID_IAudioData, (void **)&audio_data);
4433 ok(hr == S_OK, "Got hr %#x.\n", hr);
4434 hr = IAudioMediaStream_CreateSample(audio_stream, audio_data, 0, &stream_sample);
4435 ok(hr == S_OK, "Got hr %#x.\n", hr);
4436 event = CreateEventW(NULL, FALSE, FALSE, NULL);
4437 ok(event != NULL, "Expected non-NULL event.");
4439 hr = IAudioStreamSample_Update(stream_sample, 0, event, apc_func, 0);
4440 ok(hr == MS_E_NOTINIT, "Got hr %#x.\n", hr);
4442 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4443 ok(hr == MS_E_NOTINIT, "Got hr %#x.\n", hr);
4445 hr = IAudioData_SetBuffer(audio_data, sizeof(buffer), buffer, 0);
4446 ok(hr == S_OK, "Got hr %#x.\n", hr);
4448 hr = IAudioStreamSample_Update(stream_sample, 0, event, apc_func, 0);
4449 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
4451 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4452 ok(hr == MS_E_NOTRUNNING, "Got hr %#x.\n", hr);
4454 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4455 ok(hr == S_OK, "Got hr %#x.\n", hr);
4457 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4458 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
4460 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4461 ok(hr == S_OK, "Got hr %#x.\n", hr);
4462 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &audio_mt);
4463 ok(hr == S_OK, "Got hr %#x.\n", hr);
4464 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4465 ok(hr == S_OK, "Got hr %#x.\n", hr);
4467 media_sample1 = ammediastream_allocate_sample(&source, test_data, 8);
4468 hr = IMemInputPin_Receive(mem_input_pin, media_sample1);
4469 ok(hr == S_OK, "Got hr %#x.\n", hr);
4470 ref = get_refcount(media_sample1);
4471 ok(ref == 2, "Got unexpected refcount %d.\n", ref);
4473 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4474 ok(hr == S_OK, "Got hr %#x.\n", hr);
4476 hr = IAudioData_GetInfo(audio_data, NULL, NULL, &actual_length);
4477 ok(hr == S_OK, "Got hr %#x.\n", hr);
4478 ok(actual_length == 6, "Got actual length %u.\n", actual_length);
4480 ok(memcmp(buffer, test_data, 6) == 0, "Sample data didn't match.\n");
4482 ref = get_refcount(media_sample1);
4483 ok(ref == 2, "Got unexpected refcount %d.\n", ref);
4485 media_sample2 = ammediastream_allocate_sample(&source, test_data, 8);
4486 hr = IMemInputPin_Receive(mem_input_pin, media_sample2);
4487 ok(hr == S_OK, "Got hr %#x.\n", hr);
4488 ref = get_refcount(media_sample2);
4489 ok(ref == 2, "Got unexpected refcount %d.\n", ref);
4491 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4492 ok(hr == S_OK, "Got hr %#x.\n", hr);
4494 hr = IAudioData_GetInfo(audio_data, NULL, NULL, &actual_length);
4495 ok(hr == S_OK, "Got hr %#x.\n", hr);
4496 ok(actual_length == 6, "Got actual length %u.\n", actual_length);
4498 ok(memcmp(buffer, &test_data[6], 2) == 0, "Sample data didn't match.\n");
4499 ok(memcmp(&buffer[2], test_data, 4) == 0, "Sample data didn't match.\n");
4501 ref = IMediaSample_Release(media_sample1);
4502 ok(!ref, "Got outstanding refcount %d.\n", ref);
4504 hr = IPin_EndOfStream(pin);
4505 ok(hr == S_OK, "Got hr %#x.\n", hr);
4507 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4508 ok(hr == S_OK, "Got hr %#x.\n", hr);
4510 hr = IAudioData_GetInfo(audio_data, NULL, NULL, &actual_length);
4511 ok(hr == S_OK, "Got hr %#x.\n", hr);
4512 ok(actual_length == 4, "Got actual length %u.\n", actual_length);
4514 ok(memcmp(buffer, &test_data[4], 4) == 0, "Sample data didn't match.\n");
4516 ref = IMediaSample_Release(media_sample2);
4517 ok(!ref, "Got outstanding refcount %d.\n", ref);
4519 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4520 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
4522 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4523 ok(hr == S_OK, "Got hr %#x.\n", hr);
4524 hr = IMediaControl_Pause(media_control);
4525 ok(hr == S_OK, "Got hr %#x.\n", hr);
4527 media_sample1 = ammediastream_allocate_sample(&source, test_data, 6);
4528 hr = IMemInputPin_Receive(mem_input_pin, media_sample1);
4529 ok(hr == S_OK, "Got hr %#x.\n", hr);
4530 ref = IMediaSample_Release(media_sample1);
4531 ok(ref == 1, "Got outstanding refcount %d.\n", ref);
4533 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4534 ok(hr == MS_E_NOTRUNNING, "Got hr %#x.\n", hr);
4536 hr = IMediaControl_Stop(media_control);
4537 ok(hr == S_OK, "Got hr %#x.\n", hr);
4538 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4539 ok(hr == S_OK, "Got hr %#x.\n", hr);
4541 media_sample1 = ammediastream_allocate_sample(&source, test_data, 6);
4543 ammediastream_mem_input_pin = mem_input_pin;
4544 ammediastream_media_sample = media_sample1;
4545 ammediastream_sleep_time = 100;
4546 ammediastream_expected_hr = S_OK;
4547 thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
4549 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4550 ok(hr == S_OK, "Got hr %#x.\n", hr);
4552 hr = IAudioData_GetInfo(audio_data, NULL, NULL, &actual_length);
4553 ok(hr == S_OK, "Got hr %#x.\n", hr);
4554 ok(actual_length == 6, "Got actual length %u.\n", actual_length);
4556 ok(memcmp(buffer, test_data, 6) == 0, "Sample data didn't match.\n");
4558 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
4559 CloseHandle(thread);
4561 ref = IMediaSample_Release(media_sample1);
4562 ok(!ref, "Got outstanding refcount %d.\n", ref);
4564 ammediastream_pin = pin;
4565 ammediastream_sleep_time = 100;
4566 ammediastream_expected_hr = S_OK;
4567 thread = CreateThread(NULL, 0, ammediastream_end_of_stream, NULL, 0, NULL);
4569 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4570 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
4572 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
4573 CloseHandle(thread);
4575 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4576 ok(hr == S_OK, "Got hr %#x.\n", hr);
4577 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4578 ok(hr == S_OK, "Got hr %#x.\n", hr);
4580 hr = IAudioStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
4581 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
4583 IAudioStreamSample_AddRef(stream_sample);
4584 ref = IAudioStreamSample_Release(stream_sample);
4585 ok(ref == 1, "Got outstanding refcount %d.\n", ref);
4587 hr = IAudioStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
4588 ok(hr == MS_E_BUSY, "Got hr %#x.\n", hr);
4590 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4591 ok(hr == S_OK, "Got hr %#x.\n", hr);
4592 IGraphBuilder_Disconnect(graph, pin);
4593 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
4594 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4595 ok(hr == S_OK, "Got hr %#x.\n", hr);
4597 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4598 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
4600 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4602 CloseHandle(event);
4603 ref = IAudioStreamSample_Release(stream_sample);
4604 ok(!ref, "Got outstanding refcount %d.\n", ref);
4605 ref = IAudioData_Release(audio_data);
4606 ok(!ref, "Got outstanding refcount %d.\n", ref);
4607 ref = IAMMultiMediaStream_Release(mmstream);
4608 ok(!ref, "Got outstanding refcount %d.\n", ref);
4609 IMediaControl_Release(media_control);
4610 ref = IGraphBuilder_Release(graph);
4611 ok(!ref, "Got outstanding refcount %d.\n", ref);
4612 IPin_Release(pin);
4613 IMemInputPin_Release(mem_input_pin);
4614 IAudioMediaStream_Release(audio_stream);
4615 ref = IMediaStream_Release(stream);
4616 ok(!ref, "Got outstanding refcount %d.\n", ref);
4619 void test_audiostreamsample_completion_status(void)
4621 static const BYTE test_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
4622 IAMMultiMediaStream *mmstream = create_ammultimediastream();
4623 IAudioStreamSample *stream_sample1;
4624 IAudioStreamSample *stream_sample2;
4625 IAudioMediaStream *audio_stream;
4626 IMediaSample *media_sample;
4627 struct testfilter source;
4628 IAudioData *audio_data1;
4629 IAudioData *audio_data2;
4630 IGraphBuilder *graph;
4631 IMediaStream *stream;
4632 HANDLE event;
4633 HRESULT hr;
4634 ULONG ref;
4635 IPin *pin;
4637 event = CreateEventW(NULL, FALSE, FALSE, NULL);
4638 ok(event != NULL, "Expected non-NULL event.");
4640 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
4641 ok(hr == S_OK, "Got hr %#x.\n", hr);
4642 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
4643 ok(hr == S_OK, "Got hr %#x.\n", hr);
4644 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
4645 ok(hr == S_OK, "Got hr %#x.\n", hr);
4646 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
4647 ok(hr == S_OK, "Got hr %#x.\n", hr);
4648 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
4649 ok(hr == S_OK, "Got hr %#x.\n", hr);
4650 ok(graph != NULL, "Expected non-NULL graph.\n");
4651 testfilter_init(&source);
4652 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
4653 ok(hr == S_OK, "Got hr %#x.\n", hr);
4654 hr = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER, &IID_IAudioData, (void **)&audio_data1);
4655 ok(hr == S_OK, "Got hr %#x.\n", hr);
4656 hr = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER, &IID_IAudioData, (void **)&audio_data2);
4657 ok(hr == S_OK, "Got hr %#x.\n", hr);
4658 hr = IAudioData_SetBuffer(audio_data1, 6, NULL, 0);
4659 ok(hr == S_OK, "Got hr %#x.\n", hr);
4660 hr = IAudioData_SetBuffer(audio_data2, 6, NULL, 0);
4661 ok(hr == S_OK, "Got hr %#x.\n", hr);
4662 hr = IAudioMediaStream_CreateSample(audio_stream, audio_data1, 0, &stream_sample1);
4663 ok(hr == S_OK, "Got hr %#x.\n", hr);
4664 hr = IAudioMediaStream_CreateSample(audio_stream, audio_data2, 0, &stream_sample2);
4665 ok(hr == S_OK, "Got hr %#x.\n", hr);
4667 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &audio_mt);
4668 ok(hr == S_OK, "Got hr %#x.\n", hr);
4669 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4670 ok(hr == S_OK, "Got hr %#x.\n", hr);
4672 hr = IAudioStreamSample_CompletionStatus(stream_sample1, 0, 0);
4673 ok(hr == S_OK, "Got hr %#x.\n", hr);
4675 hr = IAudioStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
4676 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
4678 hr = IAudioStreamSample_CompletionStatus(stream_sample1, 0, 0);
4679 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
4681 media_sample = ammediastream_allocate_sample(&source, test_data, 6);
4682 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
4683 ok(hr == S_OK, "Got hr %#x.\n", hr);
4684 ref = IMediaSample_Release(media_sample);
4685 ok(!ref, "Got outstanding refcount %d.\n", ref);
4687 hr = IAudioStreamSample_CompletionStatus(stream_sample1, 0, 0);
4688 ok(hr == S_OK, "Got hr %#x.\n", hr);
4690 hr = IAudioStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
4691 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
4693 hr = IAudioStreamSample_Update(stream_sample2, SSUPDATE_ASYNC, NULL, NULL, 0);
4694 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
4696 media_sample = ammediastream_allocate_sample(&source, test_data, 12);
4697 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
4698 ok(hr == S_OK, "Got hr %#x.\n", hr);
4699 ref = IMediaSample_Release(media_sample);
4700 ok(!ref, "Got outstanding refcount %d.\n", ref);
4702 hr = IAudioStreamSample_CompletionStatus(stream_sample1, 0, 0);
4703 ok(hr == S_OK, "Got hr %#x.\n", hr);
4705 hr = IAudioStreamSample_CompletionStatus(stream_sample2, 0, 0);
4706 ok(hr == S_OK, "Got hr %#x.\n", hr);
4708 hr = IAudioStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
4709 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
4711 hr = IPin_EndOfStream(pin);
4712 ok(hr == S_OK, "Got hr %#x.\n", hr);
4714 hr = IAudioStreamSample_CompletionStatus(stream_sample1, 0, 0);
4715 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
4717 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4718 ok(hr == S_OK, "Got hr %#x.\n", hr);
4719 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4720 ok(hr == S_OK, "Got hr %#x.\n", hr);
4722 hr = IAudioStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
4723 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
4725 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4726 ok(hr == S_OK, "Got hr %#x.\n", hr);
4728 hr = IAudioStreamSample_CompletionStatus(stream_sample1, 0, 0);
4729 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
4731 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4732 ok(hr == S_OK, "Got hr %#x.\n", hr);
4734 media_sample = ammediastream_allocate_sample(&source, test_data, 6);
4735 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
4736 ok(hr == S_OK, "Got hr %#x.\n", hr);
4737 ref = IMediaSample_Release(media_sample);
4738 ok(!ref, "Got outstanding refcount %d.\n", ref);
4740 hr = IAudioStreamSample_CompletionStatus(stream_sample1, 0, 0);
4741 ok(hr == S_OK, "Got hr %#x.\n", hr);
4743 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4744 ok(hr == S_OK, "Got hr %#x.\n", hr);
4746 IGraphBuilder_Disconnect(graph, pin);
4747 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
4749 ref = IAudioStreamSample_Release(stream_sample1);
4750 ok(!ref, "Got outstanding refcount %d.\n", ref);
4751 ref = IAudioStreamSample_Release(stream_sample2);
4752 ok(!ref, "Got outstanding refcount %d.\n", ref);
4753 ref = IAudioData_Release(audio_data1);
4754 ok(!ref, "Got outstanding refcount %d.\n", ref);
4755 ref = IAudioData_Release(audio_data2);
4756 ok(!ref, "Got outstanding refcount %d.\n", ref);
4757 ref = IAMMultiMediaStream_Release(mmstream);
4758 ok(!ref, "Got outstanding refcount %d.\n", ref);
4759 ref = IGraphBuilder_Release(graph);
4760 ok(!ref, "Got outstanding refcount %d.\n", ref);
4761 IPin_Release(pin);
4762 IAudioMediaStream_Release(audio_stream);
4763 ref = IMediaStream_Release(stream);
4764 ok(!ref, "Got outstanding refcount %d.\n", ref);
4766 CloseHandle(event);
4769 static void test_audiostreamsample_get_sample_times(void)
4771 IAMMultiMediaStream *mmstream = create_ammultimediastream();
4772 static const BYTE test_data[8] = { 0 };
4773 IAudioStreamSample *stream_sample;
4774 IMediaFilter *graph_media_filter;
4775 IAudioMediaStream *audio_stream;
4776 STREAM_TIME filter_start_time;
4777 IMemInputPin *mem_input_pin;
4778 IMediaStreamFilter *filter;
4779 IMediaSample *media_sample;
4780 struct testfilter source;
4781 STREAM_TIME current_time;
4782 struct testclock clock;
4783 IAudioData *audio_data;
4784 STREAM_TIME start_time;
4785 STREAM_TIME end_time;
4786 IGraphBuilder *graph;
4787 IMediaStream *stream;
4788 HRESULT hr;
4789 ULONG ref;
4790 IPin *pin;
4792 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
4793 ok(hr == S_OK, "Got hr %#x.\n", hr);
4794 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
4795 ok(hr == S_OK, "Got hr %#x.\n", hr);
4796 ok(!!filter, "Expected non-null filter.\n");
4797 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
4798 ok(hr == S_OK, "Got hr %#x.\n", hr);
4799 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
4800 ok(hr == S_OK, "Got hr %#x.\n", hr);
4801 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
4802 ok(hr == S_OK, "Got hr %#x.\n", hr);
4803 hr = IMediaStream_QueryInterface(stream, &IID_IMemInputPin, (void **)&mem_input_pin);
4804 ok(hr == S_OK, "Got hr %#x.\n", hr);
4805 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
4806 ok(hr == S_OK, "Got hr %#x.\n", hr);
4807 ok(graph != NULL, "Expected non-NULL graph.\n");
4808 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void **)&graph_media_filter);
4809 ok(hr == S_OK, "Got hr %#x.\n", hr);
4810 testfilter_init(&source);
4811 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
4812 ok(hr == S_OK, "Got hr %#x.\n", hr);
4813 hr = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER, &IID_IAudioData, (void **)&audio_data);
4814 ok(hr == S_OK, "Got hr %#x.\n", hr);
4815 hr = IAudioMediaStream_CreateSample(audio_stream, audio_data, 0, &stream_sample);
4816 ok(hr == S_OK, "Got hr %#x.\n", hr);
4817 hr = IAudioData_SetBuffer(audio_data, 5, NULL, 0);
4818 ok(hr == S_OK, "Got hr %#x.\n", hr);
4819 testclock_init(&clock);
4821 clock.time = 12345678;
4823 current_time = 0xdeadbeefdeadbeef;
4824 hr = IAudioStreamSample_GetSampleTimes(stream_sample, NULL, NULL, &current_time);
4825 ok(hr == S_OK, "Got hr %#x.\n", hr);
4826 ok(current_time == 0, "Got current time %s.\n", wine_dbgstr_longlong(current_time));
4828 IMediaFilter_SetSyncSource(graph_media_filter, &clock.IReferenceClock_iface);
4829 ok(hr == S_OK, "Got hr %#x.\n", hr);
4831 current_time = 0xdeadbeefdeadbeef;
4832 hr = IAudioStreamSample_GetSampleTimes(stream_sample, NULL, NULL, &current_time);
4833 ok(hr == S_OK, "Got hr %#x.\n", hr);
4834 ok(current_time == 0, "Got current time %s.\n", wine_dbgstr_longlong(current_time));
4836 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &audio_mt);
4837 ok(hr == S_OK, "Got hr %#x.\n", hr);
4838 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
4839 ok(hr == S_OK, "Got hr %#x.\n", hr);
4841 hr = IMediaStreamFilter_GetCurrentStreamTime(filter, &filter_start_time);
4842 ok(hr == S_OK, "Got hr %#x.\n", hr);
4844 clock.get_time_hr = E_FAIL;
4846 current_time = 0xdeadbeefdeadbeef;
4847 hr = IAudioStreamSample_GetSampleTimes(stream_sample, NULL, NULL, &current_time);
4848 ok(hr == S_OK, "Got hr %#x.\n", hr);
4849 ok(current_time == 0xdeadbeefddf15da1 + filter_start_time, "Expected current time %s, got %s.\n",
4850 wine_dbgstr_longlong(0xdeadbeefddf15da1 + filter_start_time), wine_dbgstr_longlong(current_time));
4852 clock.get_time_hr = S_OK;
4854 current_time = 0xdeadbeefdeadbeef;
4855 hr = IAudioStreamSample_GetSampleTimes(stream_sample, NULL, NULL, &current_time);
4856 ok(hr == S_OK, "Got hr %#x.\n", hr);
4857 ok(current_time == filter_start_time, "Expected current time %s, got %s.\n",
4858 wine_dbgstr_longlong(filter_start_time), wine_dbgstr_longlong(current_time));
4860 clock.time = 23456789;
4862 current_time = 0xdeadbeefdeadbeef;
4863 hr = IAudioStreamSample_GetSampleTimes(stream_sample, NULL, NULL, &current_time);
4864 ok(hr == S_OK, "Got hr %#x.\n", hr);
4865 ok(current_time == filter_start_time + 11111111, "Expected current time %s, got %s.\n",
4866 wine_dbgstr_longlong(filter_start_time + 11111111), wine_dbgstr_longlong(current_time));
4868 start_time = 0xdeadbeefdeadbeef;
4869 end_time = 0xdeadbeefdeadbeef;
4870 hr = IAudioStreamSample_GetSampleTimes(stream_sample, &start_time, &end_time, NULL);
4871 ok(hr == S_OK, "Got hr %#x.\n", hr);
4872 ok(start_time == 0, "Got start time %s.\n", wine_dbgstr_longlong(start_time));
4873 ok(end_time == 0, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
4875 media_sample = ammediastream_allocate_sample(&source, test_data, 8);
4876 start_time = 12345678;
4877 end_time = 23456789;
4878 hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
4879 ok(hr == S_OK, "Got hr %#x.\n", hr);
4880 hr = IMemInputPin_Receive(mem_input_pin, media_sample);
4881 ok(hr == S_OK, "Got hr %#x.\n", hr);
4882 IMediaSample_Release(media_sample);
4884 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4885 ok(hr == S_OK, "Got hr %#x.\n", hr);
4887 start_time = 0xdeadbeefdeadbeef;
4888 end_time = 0xdeadbeefdeadbeef;
4889 hr = IAudioStreamSample_GetSampleTimes(stream_sample, &start_time, &end_time, NULL);
4890 ok(hr == S_OK, "Got hr %#x.\n", hr);
4891 ok(start_time == 12345678, "Got start time %s.\n", wine_dbgstr_longlong(start_time));
4892 ok(end_time == 12347946, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
4894 media_sample = ammediastream_allocate_sample(&source, test_data, 6);
4895 start_time = 12345678;
4896 end_time = 23456789;
4897 hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
4898 ok(hr == S_OK, "Got hr %#x.\n", hr);
4899 hr = IMemInputPin_Receive(mem_input_pin, media_sample);
4900 ok(hr == S_OK, "Got hr %#x.\n", hr);
4901 IMediaSample_Release(media_sample);
4903 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4904 ok(hr == S_OK, "Got hr %#x.\n", hr);
4906 start_time = 0xdeadbeefdeadbeef;
4907 end_time = 0xdeadbeefdeadbeef;
4908 hr = IAudioStreamSample_GetSampleTimes(stream_sample, &start_time, &end_time, NULL);
4909 ok(hr == S_OK, "Got hr %#x.\n", hr);
4910 ok(start_time == 12347946, "Got start time %s.\n", wine_dbgstr_longlong(start_time));
4911 ok(end_time == 12346585, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
4913 hr = IPin_EndOfStream(pin);
4914 ok(hr == S_OK, "Got hr %#x.\n", hr);
4916 hr = IAudioStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
4917 ok(hr == S_OK, "Got hr %#x.\n", hr);
4919 start_time = 0xdeadbeefdeadbeef;
4920 end_time = 0xdeadbeefdeadbeef;
4921 hr = IAudioStreamSample_GetSampleTimes(stream_sample, &start_time, &end_time, NULL);
4922 ok(hr == S_OK, "Got hr %#x.\n", hr);
4923 ok(start_time == 12346585, "Got start time %s.\n", wine_dbgstr_longlong(start_time));
4924 ok(end_time == 12348399, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
4926 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
4927 ok(hr == S_OK, "Got hr %#x.\n", hr);
4928 IGraphBuilder_Disconnect(graph, pin);
4929 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
4931 ref = IAudioStreamSample_Release(stream_sample);
4932 ok(!ref, "Got outstanding refcount %d.\n", ref);
4933 ref = IAudioData_Release(audio_data);
4934 ok(!ref, "Got outstanding refcount %d.\n", ref);
4935 ref = IAMMultiMediaStream_Release(mmstream);
4936 ok(!ref, "Got outstanding refcount %d.\n", ref);
4937 IMediaFilter_Release(graph_media_filter);
4938 ref = IGraphBuilder_Release(graph);
4939 ok(!ref, "Got outstanding refcount %d.\n", ref);
4940 ref = IMediaStreamFilter_Release(filter);
4941 ok(!ref, "Got outstanding refcount %d.\n", ref);
4942 IPin_Release(pin);
4943 IMemInputPin_Release(mem_input_pin);
4944 IAudioMediaStream_Release(audio_stream);
4945 ref = IMediaStream_Release(stream);
4946 ok(!ref, "Got outstanding refcount %d.\n", ref);
4949 static void test_ddrawstream_initialize(void)
4951 IDirectDrawMediaStream *ddraw_stream;
4952 IAMMediaStream *stream;
4953 IDirectDraw *ddraw2;
4954 IDirectDraw *ddraw;
4955 STREAM_TYPE type;
4956 MSPID mspid;
4957 HRESULT hr;
4958 ULONG ref;
4960 hr = DirectDrawCreate(NULL, &ddraw, NULL);
4961 ok(hr == S_OK, "Got hr %#x.\n", hr);
4963 hr = CoCreateInstance(&CLSID_AMDirectDrawStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream);
4964 ok(hr == S_OK, "Got hr %#x.\n", hr);
4966 hr = IAMMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
4967 ok(hr == S_OK, "Got hr %#x.\n", hr);
4969 /* Crashes on native. */
4970 if (0)
4972 hr = IAMMediaStream_Initialize(stream, NULL, 0, NULL, STREAMTYPE_WRITE);
4973 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
4976 hr = IAMMediaStream_Initialize(stream, NULL, 0, &test_mspid, STREAMTYPE_WRITE);
4977 ok(hr == S_OK, "Got hr %#x.\n", hr);
4979 hr = IAMMediaStream_GetInformation(stream, &mspid, &type);
4980 ok(hr == S_OK, "Got hr %#x.\n", hr);
4981 ok(IsEqualGUID(&mspid, &test_mspid), "Got mspid %s.\n", wine_dbgstr_guid(&mspid));
4982 ok(type == STREAMTYPE_WRITE, "Got type %u.\n", type);
4984 hr = IAMMediaStream_Initialize(stream, (IUnknown *)ddraw, 0, &MSPID_PrimaryAudio, STREAMTYPE_READ);
4985 ok(hr == S_OK, "Got hr %#x.\n", hr);
4987 hr = IAMMediaStream_GetInformation(stream, &mspid, &type);
4988 ok(hr == S_OK, "Got hr %#x.\n", hr);
4989 ok(IsEqualGUID(&mspid, &MSPID_PrimaryAudio), "Got mspid %s.\n", wine_dbgstr_guid(&mspid));
4990 ok(type == STREAMTYPE_READ, "Got type %u.\n", type);
4992 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw2);
4993 ok(hr == S_OK, "Got hr %#x.\n", hr);
4994 ok(ddraw2 == ddraw, "Expected ddraw %p, got %p.\n", ddraw, ddraw2);
4996 IDirectDrawMediaStream_Release(ddraw_stream);
4997 ref = IAMMediaStream_Release(stream);
4998 ok(!ref, "Got outstanding refcount %d.\n", ref);
4999 IDirectDraw_Release(ddraw2);
5000 ref = IDirectDraw_Release(ddraw);
5001 ok(!ref, "Got outstanding refcount %d.\n", ref);
5004 #define check_ddrawstream_get_format(a,b,c) check_ddrawstream_get_format_(__LINE__,a,b,c)
5005 static void check_ddrawstream_get_format_(int line, IDirectDrawMediaStream *stream,
5006 const AM_MEDIA_TYPE *mt, const DDSURFACEDESC *expected_format)
5008 DDSURFACEDESC current_format;
5009 DDSURFACEDESC desired_format;
5010 struct testfilter source;
5011 FILTER_INFO filter_info;
5012 DDSURFACEDESC format;
5013 PIN_INFO pin_info;
5014 DWORD flags;
5015 HRESULT hr;
5016 IPin *pin;
5018 hr = IDirectDrawMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
5019 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
5020 hr = IPin_QueryPinInfo(pin, &pin_info);
5021 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
5022 hr = IBaseFilter_QueryFilterInfo(pin_info.pFilter, &filter_info);
5023 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
5025 testfilter_init(&source);
5027 hr = IFilterGraph_AddFilter(filter_info.pGraph, &source.filter.IBaseFilter_iface, L"source");
5028 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
5030 hr = IFilterGraph_ConnectDirect(filter_info.pGraph, &source.source.pin.IPin_iface, pin, mt);
5031 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
5033 hr = IDirectDrawMediaStream_GetFormat(stream, NULL, NULL, NULL, NULL);
5034 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
5036 memset(&current_format, 0xcc, sizeof(current_format));
5037 current_format.dwSize = sizeof(current_format);
5038 memset(&desired_format, 0xcc, sizeof(desired_format));
5039 desired_format.dwSize = sizeof(desired_format);
5040 flags = 0xdeadbeef;
5041 hr = IDirectDrawMediaStream_GetFormat(stream, &current_format, NULL, &desired_format, &flags);
5042 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
5043 memset(&format, 0xcc, sizeof(format));
5044 format.dwSize = sizeof(format);
5045 format.ddpfPixelFormat = expected_format->ddpfPixelFormat;
5046 format.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
5047 format.dwWidth = 333;
5048 format.dwHeight = 444;
5049 format.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
5050 ok_(__FILE__, line)(memcmp(&current_format, &format, sizeof(DDSURFACEDESC)) == 0, "Current format didn't match.\n");
5051 format.dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
5052 ok_(__FILE__, line)(memcmp(&desired_format, &format, sizeof(DDSURFACEDESC)) == 0, "Desired format didn't match.\n");
5054 hr = IFilterGraph_Disconnect(filter_info.pGraph, &source.source.pin.IPin_iface);
5055 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
5056 hr = IFilterGraph_Disconnect(filter_info.pGraph, pin);
5057 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
5059 hr = IFilterGraph_RemoveFilter(filter_info.pGraph, &source.filter.IBaseFilter_iface);
5060 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
5062 IFilterGraph_Release(filter_info.pGraph);
5063 IBaseFilter_Release(pin_info.pFilter);
5064 IPin_Release(pin);
5067 static void test_ddrawstream_get_format(void)
5069 IAMMultiMediaStream *mmstream = create_ammultimediastream();
5070 IDirectDrawMediaStream *ddraw_stream;
5071 DDSURFACEDESC current_format;
5072 DDSURFACEDESC desired_format;
5073 IDirectDrawPalette *palette;
5074 IMediaStream *stream;
5075 VIDEOINFO video_info;
5076 AM_MEDIA_TYPE mt;
5077 DWORD flags;
5078 HRESULT hr;
5079 ULONG ref;
5081 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
5082 ok(hr == S_OK, "Got hr %#x.\n", hr);
5083 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
5084 ok(hr == S_OK, "Got hr %#x.\n", hr);
5086 current_format.dwSize = sizeof(current_format);
5087 desired_format.dwSize = sizeof(desired_format);
5088 hr = IDirectDrawMediaStream_GetFormat(ddraw_stream, &current_format, &palette, &desired_format, &flags);
5089 ok(hr == MS_E_NOSTREAM, "Got hr %#x.\n", hr);
5091 video_info = rgb32_video_info;
5092 video_info.rcSource.right = 222;
5093 video_info.rcSource.bottom = 333;
5094 video_info.rcTarget.right = 444;
5095 video_info.rcTarget.bottom = 666;
5096 mt = rgb32_mt;
5097 mt.pbFormat = (BYTE *)&video_info;
5098 check_ddrawstream_get_format(ddraw_stream, &mt, &rgb32_format);
5100 video_info = rgb32_video_info;
5101 video_info.bmiHeader.biHeight = 444;
5102 mt = rgb32_mt;
5103 mt.pbFormat = (BYTE *)&video_info;
5104 check_ddrawstream_get_format(ddraw_stream, &mt, &rgb32_format);
5106 check_ddrawstream_get_format(ddraw_stream, &rgb8_mt, &rgb8_format);
5107 check_ddrawstream_get_format(ddraw_stream, &rgb555_mt, &rgb555_format);
5108 check_ddrawstream_get_format(ddraw_stream, &rgb565_mt, &rgb565_format);
5109 check_ddrawstream_get_format(ddraw_stream, &rgb24_mt, &rgb24_format);
5110 check_ddrawstream_get_format(ddraw_stream, &rgb32_mt, &rgb32_format);
5112 current_format.dwSize = sizeof(current_format);
5113 desired_format.dwSize = sizeof(desired_format);
5114 hr = IDirectDrawMediaStream_GetFormat(ddraw_stream, &current_format, &palette, &desired_format, &flags);
5115 ok(hr == MS_E_NOSTREAM, "Got hr %#x.\n", hr);
5117 ref = IAMMultiMediaStream_Release(mmstream);
5118 ok(!ref, "Got outstanding refcount %d.\n", ref);
5119 IDirectDrawMediaStream_Release(ddraw_stream);
5120 ref = IMediaStream_Release(stream);
5121 ok(!ref, "Got outstanding refcount %d.\n", ref);
5124 #define check_ddrawstream_set_format(a,b,c,d) check_ddrawstream_set_format_(__LINE__,a,b,c,d)
5125 static void check_ddrawstream_set_format_(int line, IDirectDrawMediaStream *stream,
5126 const DDSURFACEDESC *format, const AM_MEDIA_TYPE *mt, HRESULT expected_hr)
5128 struct testfilter source;
5129 FILTER_INFO filter_info;
5130 PIN_INFO pin_info;
5131 HRESULT hr;
5132 IPin *pin;
5134 hr = IDirectDrawMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
5135 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
5136 hr = IPin_QueryPinInfo(pin, &pin_info);
5137 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
5138 hr = IBaseFilter_QueryFilterInfo(pin_info.pFilter, &filter_info);
5139 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
5141 testfilter_init(&source);
5143 hr = IFilterGraph_AddFilter(filter_info.pGraph, &source.filter.IBaseFilter_iface, L"source");
5144 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
5146 hr = IDirectDrawMediaStream_SetFormat(stream, format, NULL);
5147 ok_(__FILE__, line)(hr == expected_hr, "Got hr %#x.\n", hr);
5149 if (mt)
5151 DDSURFACEDESC current_format;
5152 DDSURFACEDESC desired_format;
5153 DWORD flags;
5155 hr = IFilterGraph_ConnectDirect(filter_info.pGraph, &source.source.pin.IPin_iface, pin, mt);
5156 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
5158 memset(&current_format, 0xcc, sizeof(current_format));
5159 memset(&desired_format, 0xcc, sizeof(desired_format));
5160 flags = 0xdeadbeef;
5161 current_format.dwSize = sizeof(current_format);
5162 desired_format.dwSize = sizeof(desired_format);
5163 hr = IDirectDrawMediaStream_GetFormat(stream, &current_format, NULL, &desired_format, &flags);
5164 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
5165 if (format->dwFlags & DDSD_PIXELFORMAT)
5167 ok_(__FILE__, line)(current_format.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT),
5168 "Got current format flags %#x.\n", current_format.dwFlags);
5169 ok_(__FILE__, line)(memcmp(&current_format.ddpfPixelFormat, &format->ddpfPixelFormat, sizeof(DDPIXELFORMAT)) == 0,
5170 "Current pixel format didn't match.\n");
5171 ok_(__FILE__, line)(memcmp(&desired_format.ddpfPixelFormat, &format->ddpfPixelFormat, sizeof(DDPIXELFORMAT)) == 0,
5172 "Desired pixel format didn't match.\n");
5174 else
5176 ok_(__FILE__, line)(current_format.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS),
5177 "Got flags %#x.\n", current_format.dwFlags);
5179 ok_(__FILE__, line)(desired_format.dwFlags == (DDSD_WIDTH | DDSD_HEIGHT),
5180 "Got desired format flags %#x.\n", desired_format.dwFlags);
5181 ok_(__FILE__, line)(current_format.ddsCaps.dwCaps == (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY),
5182 "Got current format caps %#x.\n", current_format.ddsCaps.dwCaps);
5183 ok_(__FILE__, line)(desired_format.ddsCaps.dwCaps == (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY),
5184 "Got desired format caps %#x.\n", desired_format.ddsCaps.dwCaps);
5185 ok_(__FILE__, line)(flags == 0, "Got flags %#x.\n", flags);
5187 hr = IFilterGraph_Disconnect(filter_info.pGraph, &source.source.pin.IPin_iface);
5188 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
5189 hr = IFilterGraph_Disconnect(filter_info.pGraph, pin);
5190 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
5193 hr = IFilterGraph_RemoveFilter(filter_info.pGraph, &source.filter.IBaseFilter_iface);
5194 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
5196 IFilterGraph_Release(filter_info.pGraph);
5197 IBaseFilter_Release(pin_info.pFilter);
5198 IPin_Release(pin);
5201 static void test_ddrawstream_set_format(void)
5203 static const DDSURFACEDESC rgb1_format =
5205 .dwSize = sizeof(DDSURFACEDESC),
5206 .dwFlags = DDSD_PIXELFORMAT,
5207 .ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT),
5208 .ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED1,
5209 .ddpfPixelFormat.u1.dwRGBBitCount = 1,
5211 static const DDSURFACEDESC rgb2_format =
5213 .dwSize = sizeof(DDSURFACEDESC),
5214 .dwFlags = DDSD_PIXELFORMAT,
5215 .ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT),
5216 .ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED2,
5217 .ddpfPixelFormat.u1.dwRGBBitCount = 2,
5219 static const DDSURFACEDESC rgb4_format =
5221 .dwSize = sizeof(DDSURFACEDESC),
5222 .dwFlags = DDSD_PIXELFORMAT,
5223 .ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT),
5224 .ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED4,
5225 .ddpfPixelFormat.u1.dwRGBBitCount = 4,
5227 static const DDSURFACEDESC rgb4to8_format =
5229 .dwSize = sizeof(DDSURFACEDESC),
5230 .dwFlags = DDSD_PIXELFORMAT,
5231 .ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT),
5232 .ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXEDTO8,
5233 .ddpfPixelFormat.u1.dwRGBBitCount = 4,
5235 static const DDSURFACEDESC rgb332_format =
5237 .dwSize = sizeof(DDSURFACEDESC),
5238 .dwFlags = DDSD_PIXELFORMAT,
5239 .ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT),
5240 .ddpfPixelFormat.dwFlags = DDPF_RGB,
5241 .ddpfPixelFormat.u1.dwRGBBitCount = 8,
5242 .ddpfPixelFormat.u2.dwRBitMask = 0xe0,
5243 .ddpfPixelFormat.u3.dwGBitMask = 0x1c,
5244 .ddpfPixelFormat.u4.dwBBitMask = 0x03,
5247 IDirectDrawMediaStream *ddraw_stream;
5248 IAMMultiMediaStream *mmstream;
5249 DDSURFACEDESC current_format;
5250 DDSURFACEDESC desired_format;
5251 struct testfilter source;
5252 IGraphBuilder *graph;
5253 DDSURFACEDESC format;
5254 IMediaStream *stream;
5255 VIDEOINFO video_info;
5256 AM_MEDIA_TYPE mt;
5257 HRESULT hr;
5258 ULONG ref;
5259 IPin *pin;
5261 mmstream = create_ammultimediastream();
5263 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
5264 ok(hr == S_OK, "Got hr %#x.\n", hr);
5265 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
5266 ok(hr == S_OK, "Got hr %#x.\n", hr);
5268 check_ddrawstream_set_format(ddraw_stream, &rgb8_format, &rgb8_mt, S_OK);
5269 check_ddrawstream_set_format(ddraw_stream, &rgb555_format, &rgb555_mt, S_OK);
5270 check_ddrawstream_set_format(ddraw_stream, &rgb565_format, &rgb565_mt, S_OK);
5271 check_ddrawstream_set_format(ddraw_stream, &rgb24_format, &rgb24_mt, S_OK);
5272 check_ddrawstream_set_format(ddraw_stream, &rgb32_format, &rgb32_mt, S_OK);
5273 check_ddrawstream_set_format(ddraw_stream, &argb32_format, &rgb32_mt, S_OK);
5274 check_ddrawstream_set_format(ddraw_stream, &yuy2_format, NULL, S_OK);
5275 check_ddrawstream_set_format(ddraw_stream, &yv12_format, NULL, S_OK);
5277 format = rgb32_format;
5278 format.ddpfPixelFormat.dwFlags |= DDPF_ALPHAPIXELS | DDPF_ALPHA
5279 | DDPF_COMPRESSED | DDPF_RGBTOYUV | DDPF_ZBUFFER | DDPF_ZPIXELS | DDPF_STENCILBUFFER
5280 | DDPF_ALPHAPREMULT | DDPF_LUMINANCE | DDPF_BUMPLUMINANCE | DDPF_BUMPDUDV;
5281 check_ddrawstream_set_format(ddraw_stream, &format, &rgb32_mt, S_OK);
5283 format = yuy2_format;
5284 format.ddpfPixelFormat.dwFlags |= DDPF_ALPHAPIXELS | DDPF_ALPHA
5285 | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXEDTO8 | DDPF_PALETTEINDEXED8
5286 | DDPF_RGB | DDPF_COMPRESSED | DDPF_RGBTOYUV | DDPF_YUV | DDPF_ZBUFFER
5287 | DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 | DDPF_ZPIXELS
5288 | DDPF_STENCILBUFFER | DDPF_ALPHAPREMULT | DDPF_LUMINANCE
5289 | DDPF_BUMPLUMINANCE | DDPF_BUMPDUDV;
5290 check_ddrawstream_set_format(ddraw_stream, &format, NULL, S_OK);
5292 format = rgb32_format;
5293 format.dwFlags |= DDSD_CAPS;
5294 format.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
5295 check_ddrawstream_set_format(ddraw_stream, &format, &rgb32_mt, S_OK);
5297 format = rgb8_format;
5298 format.dwFlags = 0;
5299 check_ddrawstream_set_format(ddraw_stream, &format, &rgb32_mt, S_OK);
5301 check_ddrawstream_set_format(ddraw_stream, &rgb1_format, NULL, DDERR_INVALIDSURFACETYPE);
5302 check_ddrawstream_set_format(ddraw_stream, &rgb2_format, NULL, DDERR_INVALIDSURFACETYPE);
5303 check_ddrawstream_set_format(ddraw_stream, &rgb4_format, NULL, DDERR_INVALIDSURFACETYPE);
5304 check_ddrawstream_set_format(ddraw_stream, &rgb4to8_format, NULL, DDERR_INVALIDSURFACETYPE);
5305 check_ddrawstream_set_format(ddraw_stream, &rgb332_format, NULL, DDERR_INVALIDSURFACETYPE);
5307 format = rgb8_format;
5308 format.ddpfPixelFormat.dwFlags &= ~DDPF_RGB;
5309 check_ddrawstream_set_format(ddraw_stream, &format, NULL, DDERR_INVALIDSURFACETYPE);
5311 format = rgb8_format;
5312 format.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED1;
5313 check_ddrawstream_set_format(ddraw_stream, &format, NULL, DDERR_INVALIDSURFACETYPE);
5315 format = rgb32_format;
5316 format.ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED8;
5317 check_ddrawstream_set_format(ddraw_stream, &format, NULL, DDERR_INVALIDSURFACETYPE);
5319 format = rgb32_format;
5320 format.ddpfPixelFormat.dwFlags |= DDPF_YUV;
5321 check_ddrawstream_set_format(ddraw_stream, &format, NULL, DDERR_INVALIDSURFACETYPE);
5323 format = rgb565_format;
5324 format.ddpfPixelFormat.u2.dwRBitMask = 0x001f;
5325 format.ddpfPixelFormat.u3.dwGBitMask = 0x07e0;
5326 format.ddpfPixelFormat.u4.dwBBitMask = 0xf800;
5327 check_ddrawstream_set_format(ddraw_stream, &format, NULL, DDERR_INVALIDSURFACETYPE);
5329 format = rgb32_format;
5330 format.ddpfPixelFormat.u2.dwRBitMask = 0x00ff00;
5331 format.ddpfPixelFormat.u3.dwGBitMask = 0x0000ff;
5332 format.ddpfPixelFormat.u4.dwBBitMask = 0xff0000;
5333 check_ddrawstream_set_format(ddraw_stream, &format, NULL, DDERR_INVALIDSURFACETYPE);
5335 format = yuy2_format;
5336 format.ddpfPixelFormat.u1.dwYUVBitCount = 0;
5337 check_ddrawstream_set_format(ddraw_stream, &format, NULL, E_INVALIDARG);
5339 format = rgb32_format;
5340 format.dwSize = sizeof(DDSURFACEDESC) + 1;
5341 check_ddrawstream_set_format(ddraw_stream, &format, NULL, E_INVALIDARG);
5343 format = rgb32_format;
5344 format.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT) + 1;
5345 check_ddrawstream_set_format(ddraw_stream, &format, NULL, DDERR_INVALIDSURFACETYPE);
5347 ref = IAMMultiMediaStream_Release(mmstream);
5348 ok(!ref, "Got outstanding refcount %d.\n", ref);
5349 IDirectDrawMediaStream_Release(ddraw_stream);
5350 ref = IMediaStream_Release(stream);
5351 ok(!ref, "Got outstanding refcount %d.\n", ref);
5353 mmstream = create_ammultimediastream();
5355 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
5356 ok(hr == S_OK, "Got hr %#x.\n", hr);
5357 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
5358 ok(hr == S_OK, "Got hr %#x.\n", hr);
5359 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
5360 ok(hr == S_OK, "Got hr %#x.\n", hr);
5362 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
5363 ok(hr == S_OK, "Got hr %#x.\n", hr);
5364 ok(!!graph, "Expected non-NULL graph.\n");
5366 testfilter_init(&source);
5368 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, L"source");
5369 ok(hr == S_OK, "Got hr %#x.\n", hr);
5371 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &rgb8_mt);
5372 ok(hr == S_OK, "Got hr %#x.\n", hr);
5374 source.preferred_mt = NULL;
5376 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb555_format, NULL);
5377 ok(hr == DDERR_INVALIDSURFACETYPE, "Got hr %#x.\n", hr);
5378 ok(IsEqualGUID(&source.source.pin.mt.subtype, &MEDIASUBTYPE_RGB8),
5379 "Got subtype %s.\n", wine_dbgstr_guid(&source.source.pin.mt.subtype));
5380 hr = IDirectDrawMediaStream_GetFormat(ddraw_stream, &current_format, NULL, &desired_format, NULL);
5381 ok(hr == S_OK, "Got hr %#x.\n", hr);
5382 ok(current_format.ddpfPixelFormat.u1.dwRGBBitCount == 8,
5383 "Got rgb bit count %u.\n", current_format.ddpfPixelFormat.u1.dwRGBBitCount);
5384 ok(desired_format.ddpfPixelFormat.u1.dwRGBBitCount == 8,
5385 "Got rgb bit count %u.\n", desired_format.ddpfPixelFormat.u1.dwRGBBitCount);
5387 format = rgb555_format;
5388 format.dwFlags = 0;
5389 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &format, NULL);
5390 ok(hr == S_OK, "Got hr %#x.\n", hr);
5391 ok(IsEqualGUID(&source.source.pin.mt.subtype, &MEDIASUBTYPE_RGB8),
5392 "Got subtype %s.\n", wine_dbgstr_guid(&source.source.pin.mt.subtype));
5394 source.preferred_mt = &rgb555_mt;
5396 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb8_format, NULL);
5397 ok(hr == S_OK, "Got hr %#x.\n", hr);
5399 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &rgb555_format, NULL);
5400 ok(hr == S_OK, "Got hr %#x.\n", hr);
5401 ok(IsEqualGUID(&source.source.pin.mt.subtype, &MEDIASUBTYPE_RGB555),
5402 "Got subtype %s.\n", wine_dbgstr_guid(&source.source.pin.mt.subtype));
5403 hr = IDirectDrawMediaStream_GetFormat(ddraw_stream, &current_format, NULL, &desired_format, NULL);
5404 ok(hr == S_OK, "Got hr %#x.\n", hr);
5405 ok(current_format.ddpfPixelFormat.u1.dwRGBBitCount == 16,
5406 "Got rgb bit count %u.\n", current_format.ddpfPixelFormat.u1.dwRGBBitCount);
5407 ok(desired_format.ddpfPixelFormat.u1.dwRGBBitCount == 16,
5408 "Got rgb bit count %u.\n", desired_format.ddpfPixelFormat.u1.dwRGBBitCount);
5410 video_info = rgb555_video_info;
5411 video_info.bmiHeader.biWidth = 222;
5412 video_info.bmiHeader.biHeight = -555;
5413 mt = rgb555_mt;
5414 mt.pbFormat = (BYTE *)&video_info;
5415 source.preferred_mt = &mt;
5417 format = rgb555_format;
5418 format.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT;
5419 format.dwWidth = 222;
5420 format.dwHeight = 555;
5421 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, &format, NULL);
5422 ok(hr == S_OK, "Got hr %#x.\n", hr);
5423 ok(IsEqualGUID(&source.source.pin.mt.subtype, &MEDIASUBTYPE_RGB555),
5424 "Got subtype %s.\n", wine_dbgstr_guid(&source.source.pin.mt.subtype));
5425 ok(((VIDEOINFO *)source.source.pin.mt.pbFormat)->bmiHeader.biWidth == 222,
5426 "Got width %d.\n", ((VIDEOINFO *)source.source.pin.mt.pbFormat)->bmiHeader.biWidth);
5427 ok(((VIDEOINFO *)source.source.pin.mt.pbFormat)->bmiHeader.biHeight == -555,
5428 "Got height %d.\n", ((VIDEOINFO *)source.source.pin.mt.pbFormat)->bmiHeader.biHeight);
5430 hr = IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
5431 ok(hr == S_OK, "Got hr %#x.\n", hr);
5432 hr = IGraphBuilder_Disconnect(graph, pin);
5433 ok(hr == S_OK, "Got hr %#x.\n", hr);
5435 ref = IAMMultiMediaStream_Release(mmstream);
5436 ok(!ref, "Got outstanding refcount %d.\n", ref);
5437 ref = IGraphBuilder_Release(graph);
5438 ok(!ref, "Got outstanding refcount %d.\n", ref);
5439 IPin_Release(pin);
5440 IDirectDrawMediaStream_Release(ddraw_stream);
5441 ref = IMediaStream_Release(stream);
5442 ok(!ref, "Got outstanding refcount %d.\n", ref);
5445 static void test_ddrawstream_receive(void)
5447 ALLOCATOR_PROPERTIES properties =
5449 .cBuffers = 1,
5450 .cbBuffer = 16,
5451 .cbAlign = 1,
5454 IAMMultiMediaStream *mmstream = create_ammultimediastream();
5455 ALLOCATOR_PROPERTIES actual;
5456 IMediaStreamFilter *filter;
5457 struct testfilter source;
5458 IMemAllocator *allocator;
5459 IGraphBuilder *graph;
5460 IMediaStream *stream;
5461 IMediaSample *sample;
5462 HANDLE thread;
5463 HRESULT hr;
5464 ULONG ref;
5465 IPin *pin;
5467 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
5468 ok(hr == S_OK, "Got hr %#x.\n", hr);
5469 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
5470 ok(hr == S_OK, "Got hr %#x.\n", hr);
5471 ok(!!filter, "Expected non-null filter.\n");
5472 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
5473 ok(hr == S_OK, "Got hr %#x.\n", hr);
5474 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
5475 ok(hr == S_OK, "Got hr %#x.\n", hr);
5476 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
5477 ok(hr == S_OK, "Got hr %#x.\n", hr);
5478 ok(graph != NULL, "Expected non-NULL graph.\n");
5479 testfilter_init(&source);
5480 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
5481 ok(hr == S_OK, "Got hr %#x.\n", hr);
5482 hr = CoCreateInstance(&CLSID_MemoryAllocator, NULL, CLSCTX_INPROC_SERVER, &IID_IMemAllocator, (void **)&allocator);
5483 ok(hr == S_OK, "Got hr %#x.\n", hr);
5484 hr = IMemAllocator_SetProperties(allocator, &properties, &actual);
5485 ok(hr == S_OK, "Got hr %#x.\n", hr);
5486 hr = IMemAllocator_Commit(allocator);
5487 ok(hr == S_OK, "Got hr %#x.\n", hr);
5489 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &rgb32_mt);
5490 ok(hr == S_OK, "Got hr %#x.\n", hr);
5492 hr = IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0);
5493 ok(hr == S_OK, "Got hr %#x.\n", hr);
5494 hr = IMemInputPin_Receive(source.source.pMemInputPin, sample);
5495 ok(hr == S_OK, "Got hr %#x.\n", hr);
5496 ref = IMediaSample_Release(sample);
5497 ok(!ref, "Got outstanding refcount %d.\n", ref);
5499 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
5500 ok(hr == S_OK, "Got hr %#x.\n", hr);
5502 hr = IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0);
5503 ok(hr == S_OK, "Got hr %#x.\n", hr);
5505 ammediastream_mem_input_pin = source.source.pMemInputPin;
5506 ammediastream_media_sample = sample;
5507 ammediastream_sleep_time = 0;
5508 ammediastream_expected_hr = S_OK;
5509 thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
5511 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
5513 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
5514 ok(hr == S_OK, "Got hr %#x.\n", hr);
5516 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
5517 CloseHandle(thread);
5519 ref = IMediaSample_Release(sample);
5520 ok(!ref, "Got outstanding refcount %d.\n", ref);
5522 hr = IMemAllocator_GetBuffer(allocator, &sample, NULL, NULL, 0);
5523 ok(hr == S_OK, "Got hr %#x.\n", hr);
5524 hr = IMemInputPin_Receive(source.source.pMemInputPin, sample);
5525 ok(hr == S_OK, "Got hr %#x.\n", hr);
5526 ref = IMediaSample_Release(sample);
5527 ok(!ref, "Got outstanding refcount %d.\n", ref);
5529 IGraphBuilder_Disconnect(graph, pin);
5530 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
5532 hr = IMemAllocator_Decommit(allocator);
5533 ok(hr == S_OK, "Got hr %#x.\n", hr);
5535 ref = IAMMultiMediaStream_Release(mmstream);
5536 ok(!ref, "Got outstanding refcount %d.\n", ref);
5537 ref = IGraphBuilder_Release(graph);
5538 ok(!ref, "Got outstanding refcount %d.\n", ref);
5539 ref = IMediaStreamFilter_Release(filter);
5540 ok(!ref, "Got outstanding refcount %d.\n", ref);
5541 IPin_Release(pin);
5542 ref = IMediaStream_Release(stream);
5543 ok(!ref, "Got outstanding refcount %d.\n", ref);
5544 ref = IMemAllocator_Release(allocator);
5545 ok(!ref, "Got outstanding refcount %d.\n", ref);
5548 static void test_ddrawstream_begin_flush_end_flush(void)
5550 IAMMultiMediaStream *mmstream = create_ammultimediastream();
5551 IDirectDrawStreamSample *stream_sample;
5552 IDirectDrawMediaStream *ddraw_stream;
5553 IMediaSample *media_sample;
5554 IMediaFilter *media_filter;
5555 struct testfilter source;
5556 IGraphBuilder *graph;
5557 IMediaStream *stream;
5558 VIDEOINFO video_info;
5559 AM_MEDIA_TYPE mt;
5560 HANDLE thread;
5561 HRESULT hr;
5562 ULONG ref;
5563 IPin *pin;
5565 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
5566 ok(hr == S_OK, "Got hr %#x.\n", hr);
5567 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
5568 ok(hr == S_OK, "Got hr %#x.\n", hr);
5569 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
5570 ok(hr == S_OK, "Got hr %#x.\n", hr);
5571 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
5572 ok(hr == S_OK, "Got hr %#x.\n", hr);
5573 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
5574 ok(hr == S_OK, "Got hr %#x.\n", hr);
5575 ok(graph != NULL, "Expected non-NULL graph.\n");
5576 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void **)&media_filter);
5577 ok(hr == S_OK, "Got hr %#x.\n", hr);
5578 testfilter_init(&source);
5579 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
5580 ok(hr == S_OK, "Got hr %#x.\n", hr);
5582 hr = IMediaFilter_SetSyncSource(media_filter, NULL);
5583 ok(hr == S_OK, "Got hr %#x.\n", hr);
5585 video_info = rgb32_video_info;
5586 video_info.bmiHeader.biWidth = 3;
5587 video_info.bmiHeader.biHeight = 1;
5588 mt = rgb32_mt;
5589 mt.pbFormat = (BYTE *)&video_info;
5590 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
5591 ok(hr == S_OK, "Got hr %#x.\n", hr);
5593 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &stream_sample);
5594 ok(hr == S_OK, "Got hr %#x.\n", hr);
5596 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
5597 ok(hr == S_OK, "Got hr %#x.\n", hr);
5599 hr = BaseOutputPinImpl_GetDeliveryBuffer(&source.source, &media_sample, NULL, NULL, 0);
5600 ok(hr == S_OK, "Got hr %#x.\n", hr);
5602 ammediastream_mem_input_pin = source.source.pMemInputPin;
5603 ammediastream_media_sample = media_sample;
5604 ammediastream_sleep_time = 0;
5605 ammediastream_expected_hr = S_FALSE;
5606 thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
5608 hr = IPin_BeginFlush(pin);
5609 ok(hr == S_OK, "Got hr %#x.\n", hr);
5611 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
5612 CloseHandle(thread);
5614 ref = IMediaSample_Release(media_sample);
5615 ok(!ref, "Got outstanding refcount %d.\n", ref);
5617 hr = BaseOutputPinImpl_GetDeliveryBuffer(&source.source, &media_sample, NULL, NULL, 0);
5618 ok(hr == S_OK, "Got hr %#x.\n", hr);
5619 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
5620 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
5622 ref = IMediaSample_Release(media_sample);
5623 ok(!ref, "Got outstanding refcount %d.\n", ref);
5625 hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
5626 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
5628 hr = IPin_EndOfStream(pin);
5629 ok(hr == E_FAIL, "Got hr %#x.\n", hr);
5631 hr = IPin_EndFlush(pin);
5632 ok(hr == S_OK, "Got hr %#x.\n", hr);
5634 hr = BaseOutputPinImpl_GetDeliveryBuffer(&source.source, &media_sample, NULL, NULL, 0);
5635 ok(hr == S_OK, "Got hr %#x.\n", hr);
5636 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
5637 ok(hr == S_OK, "Got hr %#x.\n", hr);
5638 ref = IMediaSample_Release(media_sample);
5639 ok(!ref, "Got outstanding refcount %d.\n", ref);
5641 hr = IPin_EndOfStream(pin);
5642 ok(hr == S_OK, "Got hr %#x.\n", hr);
5644 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
5645 ok(hr == S_OK, "Got hr %#x.\n", hr);
5647 IGraphBuilder_Disconnect(graph, pin);
5648 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
5650 ref = IDirectDrawStreamSample_Release(stream_sample);
5651 ok(!ref, "Got outstanding refcount %d.\n", ref);
5652 ref = IAMMultiMediaStream_Release(mmstream);
5653 ok(!ref, "Got outstanding refcount %d.\n", ref);
5654 IMediaFilter_Release(media_filter);
5655 ref = IGraphBuilder_Release(graph);
5656 ok(!ref, "Got outstanding refcount %d.\n", ref);
5657 IPin_Release(pin);
5658 IDirectDrawMediaStream_Release(ddraw_stream);
5659 ref = IMediaStream_Release(stream);
5660 ok(!ref, "Got outstanding refcount %d.\n", ref);
5663 static void test_ddrawstream_new_segment(void)
5665 static const BYTE test_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
5666 IAMMultiMediaStream *mmstream = create_ammultimediastream();
5667 IDirectDrawStreamSample *stream_sample;
5668 IDirectDrawMediaStream *ddraw_stream;
5669 IMemInputPin *mem_input_pin;
5670 IMediaSample *media_sample;
5671 IMediaFilter *media_filter;
5672 struct testfilter source;
5673 STREAM_TIME start_time;
5674 STREAM_TIME end_time;
5675 IGraphBuilder *graph;
5676 IMediaStream *stream;
5677 VIDEOINFO video_info;
5678 AM_MEDIA_TYPE mt;
5679 HRESULT hr;
5680 ULONG ref;
5681 IPin *pin;
5683 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
5684 ok(hr == S_OK, "Got hr %#x.\n", hr);
5685 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
5686 ok(hr == S_OK, "Got hr %#x.\n", hr);
5687 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
5688 ok(hr == S_OK, "Got hr %#x.\n", hr);
5689 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
5690 ok(hr == S_OK, "Got hr %#x.\n", hr);
5691 hr = IMediaStream_QueryInterface(stream, &IID_IMemInputPin, (void **)&mem_input_pin);
5692 ok(hr == S_OK, "Got hr %#x.\n", hr);
5693 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
5694 ok(hr == S_OK, "Got hr %#x.\n", hr);
5695 ok(graph != NULL, "Expected non-NULL graph.\n");
5696 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void **)&media_filter);
5697 ok(hr == S_OK, "Got hr %#x.\n", hr);
5698 testfilter_init(&source);
5699 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
5700 ok(hr == S_OK, "Got hr %#x.\n", hr);
5702 hr = IMediaFilter_SetSyncSource(media_filter, NULL);
5703 ok(hr == S_OK, "Got hr %#x.\n", hr);
5705 video_info = rgb32_video_info;
5706 video_info.bmiHeader.biWidth = 3;
5707 video_info.bmiHeader.biHeight = 1;
5708 mt = rgb32_mt;
5709 mt.pbFormat = (BYTE *)&video_info;
5710 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
5711 ok(hr == S_OK, "Got hr %#x.\n", hr);
5713 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &stream_sample);
5714 ok(hr == S_OK, "Got hr %#x.\n", hr);
5716 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
5717 ok(hr == S_OK, "Got hr %#x.\n", hr);
5719 hr = IPin_NewSegment(pin, 11111111, 22222222, 1.0);
5720 ok(hr == S_OK, "Got hr %#x.\n", hr);
5722 hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
5723 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
5725 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
5726 start_time = 12345678;
5727 end_time = 23456789;
5728 hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
5729 ok(hr == S_OK, "Got hr %#x.\n", hr);
5730 hr = IMemInputPin_Receive(mem_input_pin, media_sample);
5731 ok(hr == S_OK, "Got hr %#x.\n", hr);
5732 IMediaSample_Release(media_sample);
5734 start_time = 0xdeadbeefdeadbeef;
5735 end_time = 0xdeadbeefdeadbeef;
5736 hr = IDirectDrawStreamSample_GetSampleTimes(stream_sample, &start_time, &end_time, NULL);
5737 ok(hr == S_OK, "Got hr %#x.\n", hr);
5738 ok(start_time == 23456789, "Got start time %s.\n", wine_dbgstr_longlong(start_time));
5739 ok(end_time == 34567900, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
5741 hr = IPin_NewSegment(pin, 11111111, 22222222, 2.0);
5742 ok(hr == S_OK, "Got hr %#x.\n", hr);
5744 hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
5745 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
5747 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
5748 start_time = 12345678;
5749 end_time = 23456789;
5750 hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
5751 ok(hr == S_OK, "Got hr %#x.\n", hr);
5752 hr = IMemInputPin_Receive(mem_input_pin, media_sample);
5753 ok(hr == S_OK, "Got hr %#x.\n", hr);
5754 IMediaSample_Release(media_sample);
5756 start_time = 0xdeadbeefdeadbeef;
5757 end_time = 0xdeadbeefdeadbeef;
5758 hr = IDirectDrawStreamSample_GetSampleTimes(stream_sample, &start_time, &end_time, NULL);
5759 ok(hr == S_OK, "Got hr %#x.\n", hr);
5760 ok(start_time == 23456789, "Got start time %s.\n", wine_dbgstr_longlong(start_time));
5761 ok(end_time == 34567900, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
5763 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
5764 ok(hr == S_OK, "Got hr %#x.\n", hr);
5765 IGraphBuilder_Disconnect(graph, pin);
5766 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
5768 ref = IDirectDrawStreamSample_Release(stream_sample);
5769 ok(!ref, "Got outstanding refcount %d.\n", ref);
5770 ref = IAMMultiMediaStream_Release(mmstream);
5771 ok(!ref, "Got outstanding refcount %d.\n", ref);
5772 IMediaFilter_Release(media_filter);
5773 ref = IGraphBuilder_Release(graph);
5774 ok(!ref, "Got outstanding refcount %d.\n", ref);
5775 IPin_Release(pin);
5776 IMemInputPin_Release(mem_input_pin);
5777 IDirectDrawMediaStream_Release(ddraw_stream);
5778 ref = IMediaStream_Release(stream);
5779 ok(!ref, "Got outstanding refcount %d.\n", ref);
5782 static void test_ddrawstream_get_time_per_frame(void)
5784 IAMMultiMediaStream *mmstream = create_ammultimediastream();
5785 IDirectDrawMediaStream *ddraw_stream;
5786 struct testfilter source;
5787 STREAM_TIME frame_time;
5788 IGraphBuilder *graph;
5789 IMediaStream *stream;
5790 VIDEOINFO video_info;
5791 AM_MEDIA_TYPE mt;
5792 HRESULT hr;
5793 ULONG ref;
5794 IPin *pin;
5796 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
5797 ok(hr == S_OK, "Got hr %#x.\n", hr);
5798 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
5799 ok(hr == S_OK, "Got hr %#x.\n", hr);
5800 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
5801 ok(hr == S_OK, "Got hr %#x.\n", hr);
5802 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
5803 ok(hr == S_OK, "Got hr %#x.\n", hr);
5804 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
5805 ok(hr == S_OK, "Got hr %#x.\n", hr);
5806 ok(graph != NULL, "Expected non-NULL graph.\n");
5807 testfilter_init(&source);
5808 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
5809 ok(hr == S_OK, "Got hr %#x.\n", hr);
5811 hr = IDirectDrawMediaStream_GetTimePerFrame(ddraw_stream, NULL);
5812 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
5814 hr = IDirectDrawMediaStream_GetTimePerFrame(ddraw_stream, &frame_time);
5815 ok(hr == MS_E_NOSTREAM, "Got hr %#x.\n", hr);
5817 video_info = rgb32_video_info;
5818 video_info.AvgTimePerFrame = 12345678;
5819 mt = rgb32_mt;
5820 mt.pbFormat = (BYTE *)&video_info;
5821 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
5822 ok(hr == S_OK, "Got hr %#x.\n", hr);
5824 frame_time = 0xdeadbeefdeadbeef;
5825 hr = IDirectDrawMediaStream_GetTimePerFrame(ddraw_stream, &frame_time);
5826 ok(hr == S_OK, "Got hr %#x.\n", hr);
5827 ok(frame_time == 12345678, "Got frame time %s.\n", wine_dbgstr_longlong(frame_time));
5829 ref = IAMMultiMediaStream_Release(mmstream);
5830 ok(!ref, "Got outstanding refcount %d.\n", ref);
5831 ref = IGraphBuilder_Release(graph);
5832 ok(!ref, "Got outstanding refcount %d.\n", ref);
5833 IPin_Release(pin);
5834 IDirectDrawMediaStream_Release(ddraw_stream);
5835 ref = IMediaStream_Release(stream);
5836 ok(!ref, "Got outstanding refcount %d.\n", ref);
5839 static void check_ammediastream_join_am_multi_media_stream(const CLSID *clsid)
5841 IAMMultiMediaStream *mmstream = create_ammultimediastream();
5842 IMultiMediaStream *mmstream2;
5843 IAMMediaStream *stream;
5844 HRESULT hr;
5845 ULONG mmstream_ref;
5846 ULONG ref;
5848 hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream);
5849 ok(hr == S_OK, "Got hr %#x.\n", hr);
5851 mmstream_ref = get_refcount(mmstream);
5853 hr = IAMMediaStream_JoinAMMultiMediaStream(stream, mmstream);
5854 ok(hr == S_OK, "Got hr %#x.\n", hr);
5856 ref = get_refcount(mmstream);
5857 ok(ref == mmstream_ref, "Expected outstanding refcount %d, got %d.\n", mmstream_ref, ref);
5859 hr = IAMMediaStream_GetMultiMediaStream(stream, &mmstream2);
5860 ok(hr == S_OK, "Got hr %#x.\n", hr);
5861 ok(mmstream2 == (IMultiMediaStream *)mmstream, "Expected mmstream %p, got %p.\n", mmstream, mmstream2);
5863 IMultiMediaStream_Release(mmstream2);
5865 hr = IAMMediaStream_JoinAMMultiMediaStream(stream, NULL);
5866 ok(hr == S_OK, "Got hr %#x.\n", hr);
5868 hr = IAMMediaStream_GetMultiMediaStream(stream, &mmstream2);
5869 ok(hr == S_OK, "Got hr %#x.\n", hr);
5870 ok(mmstream2 == NULL, "Got mmstream %p.\n", mmstream2);
5872 ref = IAMMediaStream_Release(stream);
5873 ok(!ref, "Got outstanding refcount %d.\n", ref);
5874 ref = IAMMultiMediaStream_Release(mmstream);
5875 ok(!ref, "Got outstanding refcount %d.\n", ref);
5878 static void test_ammediastream_join_am_multi_media_stream(void)
5880 check_ammediastream_join_am_multi_media_stream(&CLSID_AMAudioStream);
5881 check_ammediastream_join_am_multi_media_stream(&CLSID_AMDirectDrawStream);
5884 static void check_ammediastream_join_filter(const CLSID *clsid)
5886 IAMMultiMediaStream *mmstream = create_ammultimediastream();
5887 IMediaStreamFilter *filter, *filter2, *filter3;
5888 IAMMediaStream *stream;
5889 HRESULT hr;
5890 ULONG ref;
5892 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
5893 ok(hr == S_OK, "Got hr %#x.\n", hr);
5894 ok(!!filter, "Expected non-null filter.\n");
5895 EXPECT_REF(filter, 3);
5897 hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream);
5898 ok(hr == S_OK, "Got hr %#x.\n", hr);
5899 EXPECT_REF(filter, 3);
5901 hr = CoCreateInstance(&CLSID_MediaStreamFilter, NULL, CLSCTX_INPROC_SERVER,
5902 &IID_IMediaStreamFilter, (void **)&filter2);
5903 ok(hr == S_OK, "Got hr %#x.\n", hr);
5904 EXPECT_REF(filter, 3);
5905 EXPECT_REF(filter2, 1);
5907 hr = IAMMediaStream_JoinFilter(stream, filter2);
5908 ok(hr == S_OK, "Got hr %#x.\n", hr);
5909 EXPECT_REF(filter, 3);
5910 EXPECT_REF(filter2, 1);
5912 /* Crashes on native. */
5913 if (0)
5915 hr = IAMMediaStream_JoinFilter(stream, NULL);
5916 ok(hr == S_OK, "Got hr %#x.\n", hr);
5919 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter3);
5920 ok(hr == S_OK, "Got hr %#x.\n", hr);
5921 ok(filter3 == filter, "Expected filter %p, got %p.\n", filter, filter3);
5922 EXPECT_REF(filter, 4);
5924 IMediaStreamFilter_Release(filter3);
5925 EXPECT_REF(filter, 3);
5927 ref = IMediaStreamFilter_Release(filter2);
5928 ok(!ref, "Got outstanding refcount %d.\n", ref);
5929 ref = IAMMediaStream_Release(stream);
5930 ok(!ref, "Got outstanding refcount %d.\n", ref);
5931 EXPECT_REF(filter, 3);
5932 ref = IAMMultiMediaStream_Release(mmstream);
5933 ok(!ref, "Got outstanding refcount %d.\n", ref);
5934 EXPECT_REF(filter, 1);
5935 ref = IMediaStreamFilter_Release(filter);
5936 ok(!ref, "Got outstanding refcount %d.\n", ref);
5939 static void test_ammediastream_join_filter(void)
5941 check_ammediastream_join_filter(&CLSID_AMAudioStream);
5942 check_ammediastream_join_filter(&CLSID_AMDirectDrawStream);
5945 static void check_ammediastream_join_filter_graph(const MSPID *id)
5947 IAMMultiMediaStream *mmstream = create_ammultimediastream();
5948 IGraphBuilder *builder, *builder2;
5949 IMediaStreamFilter *filter;
5950 IAMMediaStream *stream;
5951 IFilterGraph *graph;
5952 FILTER_INFO info;
5953 HRESULT hr;
5954 ULONG ref;
5956 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
5957 ok(hr == S_OK, "Got hr %#x.\n", hr);
5958 ok(!!filter, "Expected non-null filter.\n");
5960 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, id, 0, (IMediaStream **)&stream);
5961 ok(hr == S_OK, "Got hr %#x.\n", hr);
5963 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &builder);
5964 ok(hr == S_OK, "Got hr %#x.\n", hr);
5965 ok(!!builder, "Expected non-null graph.\n");
5966 EXPECT_REF(builder, 4);
5968 hr = IMediaStreamFilter_QueryFilterInfo(filter, &info);
5969 ok(hr == S_OK, "Got hr %#x.\n", hr);
5970 ok(info.pGraph == (IFilterGraph *)builder, "Expected graph %p, got %p.\n", (IFilterGraph *)builder, info.pGraph);
5971 EXPECT_REF(builder, 5);
5972 IFilterGraph_Release(info.pGraph);
5973 EXPECT_REF(builder, 4);
5975 hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, &IID_IFilterGraph, (void **)&graph);
5976 ok(hr == S_OK, "Got hr %#x.\n", hr);
5977 EXPECT_REF(builder, 4);
5978 EXPECT_REF(graph, 1);
5980 /* Crashes on native. */
5981 if (0)
5983 hr = IAMMediaStream_JoinFilterGraph(stream, NULL);
5984 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
5987 hr = IAMMediaStream_JoinFilterGraph(stream, graph);
5988 ok(hr == S_OK, "Got hr %#x.\n", hr);
5989 EXPECT_REF(builder, 4);
5990 EXPECT_REF(graph, 1);
5992 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &builder2);
5993 ok(hr == S_OK, "Got hr %#x.\n", hr);
5994 ok(builder2 == builder, "Expected graph %p, got %p.\n", builder, builder2);
5995 EXPECT_REF(builder, 5);
5996 EXPECT_REF(graph, 1);
5997 IGraphBuilder_Release(builder2);
5998 EXPECT_REF(builder, 4);
5999 EXPECT_REF(graph, 1);
6001 hr = IMediaStreamFilter_QueryFilterInfo(filter, &info);
6002 ok(hr == S_OK, "Got hr %#x.\n", hr);
6003 ok(info.pGraph == (IFilterGraph *)builder, "Expected graph %p, got %p.\n", (IFilterGraph *)builder, info.pGraph);
6004 EXPECT_REF(builder, 5);
6005 EXPECT_REF(graph, 1);
6006 IFilterGraph_Release(info.pGraph);
6007 EXPECT_REF(builder, 4);
6008 EXPECT_REF(graph, 1);
6010 ref = IFilterGraph_Release(graph);
6011 ok(!ref, "Got outstanding refcount %d.\n", ref);
6012 ref = IAMMultiMediaStream_Release(mmstream);
6013 ok(!ref, "Got outstanding refcount %d.\n", ref);
6014 ref = IGraphBuilder_Release(builder);
6015 ok(!ref, "Got outstanding refcount %d.\n", ref);
6016 ref = IMediaStreamFilter_Release(filter);
6017 ok(!ref, "Got outstanding refcount %d.\n", ref);
6018 ref = IAMMediaStream_Release(stream);
6019 ok(!ref, "Got outstanding refcount %d.\n", ref);
6022 static void test_ammediastream_join_filter_graph(void)
6024 check_ammediastream_join_filter_graph(&MSPID_PrimaryAudio);
6025 check_ammediastream_join_filter_graph(&MSPID_PrimaryVideo);
6028 static void check_ammediastream_set_state(const MSPID *id)
6030 IAMMultiMediaStream *mmstream = create_ammultimediastream();
6031 IAMMediaStream *am_stream;
6032 IMediaStream *stream;
6033 HRESULT hr;
6034 ULONG ref;
6036 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
6037 ok(hr == S_OK, "Got hr %#x.\n", hr);
6038 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, id, 0, &stream);
6039 ok(hr == S_OK, "Got hr %#x.\n", hr);
6040 hr = IMediaStream_QueryInterface(stream, &IID_IAMMediaStream, (void **)&am_stream);
6041 ok(hr == S_OK, "Got hr %#x.\n", hr);
6043 hr = IAMMediaStream_SetState(am_stream, 4);
6044 ok(hr == S_OK, "Got hr %#x.\n", hr);
6046 hr = IAMMediaStream_SetState(am_stream, State_Running);
6047 ok(hr == S_OK, "Got hr %#x.\n", hr);
6049 hr = IAMMediaStream_SetState(am_stream, State_Paused);
6050 ok(hr == S_OK, "Got hr %#x.\n", hr);
6052 hr = IAMMediaStream_SetState(am_stream, State_Stopped);
6053 ok(hr == S_OK, "Got hr %#x.\n", hr);
6055 ref = IAMMultiMediaStream_Release(mmstream);
6056 ok(!ref, "Got outstanding refcount %d.\n", ref);
6057 IAMMediaStream_Release(am_stream);
6058 ref = IMediaStream_Release(stream);
6059 ok(!ref, "Got outstanding refcount %d.\n", ref);
6062 static void test_ammediastream_set_state(void)
6064 check_ammediastream_set_state(&MSPID_PrimaryAudio);
6065 check_ammediastream_set_state(&MSPID_PrimaryVideo);
6068 static void check_ammediastream_end_of_stream(const MSPID *id, const AM_MEDIA_TYPE *mt)
6070 IAMMultiMediaStream *mmstream = create_ammultimediastream();
6071 struct testfilter source;
6072 IGraphBuilder *graph;
6073 IMediaStream *stream;
6074 HRESULT hr;
6075 ULONG ref;
6076 IPin *pin;
6078 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
6079 ok(hr == S_OK, "Got hr %#x.\n", hr);
6080 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, id, 0, &stream);
6081 ok(hr == S_OK, "Got hr %#x.\n", hr);
6082 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
6083 ok(hr == S_OK, "Got hr %#x.\n", hr);
6084 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
6085 ok(hr == S_OK, "Got hr %#x.\n", hr);
6086 ok(!!graph, "Expected non-NULL graph.\n");
6087 testfilter_init(&source);
6088 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
6089 ok(hr == S_OK, "Got hr %#x.\n", hr);
6091 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, mt);
6092 ok(hr == S_OK, "Got hr %#x.\n", hr);
6094 hr = IPin_EndOfStream(pin);
6095 ok(hr == S_OK, "Got hr %#x.\n", hr);
6097 hr = IPin_EndOfStream(pin);
6098 ok(hr == E_FAIL, "Got hr %#x.\n", hr);
6100 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
6101 ok(hr == S_OK, "Got hr %#x.\n", hr);
6103 hr = IPin_EndOfStream(pin);
6104 ok(hr == S_OK, "Got hr %#x.\n", hr);
6106 hr = IPin_EndOfStream(pin);
6107 ok(hr == E_FAIL, "Got hr %#x.\n", hr);
6109 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
6110 ok(hr == S_OK, "Got hr %#x.\n", hr);
6112 hr = IPin_EndOfStream(pin);
6113 ok(hr == E_FAIL, "Got hr %#x.\n", hr);
6115 IGraphBuilder_Disconnect(graph, pin);
6116 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
6118 ref = IAMMultiMediaStream_Release(mmstream);
6119 ok(!ref, "Got outstanding refcount %d.\n", ref);
6120 ref = IGraphBuilder_Release(graph);
6121 ok(!ref, "Got outstanding refcount %d.\n", ref);
6122 IPin_Release(pin);
6123 ref = IMediaStream_Release(stream);
6124 ok(!ref, "Got outstanding refcount %d.\n", ref);
6127 static void test_ammediastream_end_of_stream(void)
6129 check_ammediastream_end_of_stream(&MSPID_PrimaryAudio, &audio_mt);
6130 check_ammediastream_end_of_stream(&MSPID_PrimaryVideo, &rgb32_mt);
6133 void test_mediastreamfilter_get_state(void)
6135 IAMMultiMediaStream *mmstream = create_ammultimediastream();
6136 IMediaStreamFilter *filter;
6137 FILTER_STATE state;
6138 HRESULT hr;
6139 ULONG ref;
6141 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
6142 ok(hr == S_OK, "Got hr %#x.\n", hr);
6143 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
6144 ok(hr == S_OK, "Got hr %#x.\n", hr);
6145 ok(!!filter, "Expected non-null filter.\n");
6147 /* Crashes on native. */
6148 if (0)
6150 hr = IMediaStreamFilter_GetState(filter, 0, NULL);
6151 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
6154 state = 0xcc;
6155 hr = IMediaStreamFilter_GetState(filter, 0, &state);
6156 ok(state == State_Stopped, "Got state %#x.\n", state);
6158 ref = IAMMultiMediaStream_Release(mmstream);
6159 ok(!ref, "Got outstanding refcount %d.\n", ref);
6160 ref = IMediaStreamFilter_Release(filter);
6161 ok(!ref, "Got outstanding refcount %d.\n", ref);
6164 void check_mediastreamfilter_state(FILTER_STATE expected_state, HRESULT (*set_state)(IMediaStreamFilter *),
6165 HRESULT (*reset_state)(IMediaStreamFilter *))
6167 IAMMultiMediaStream *mmstream = create_ammultimediastream();
6168 struct teststream teststream, teststream2;
6169 IMediaStreamFilter *filter;
6170 FILTER_STATE state;
6171 HRESULT hr;
6172 ULONG ref;
6174 teststream_init(&teststream);
6175 teststream_init(&teststream2);
6177 teststream2.mspid.Data2 = 1;
6179 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
6180 ok(hr == S_OK, "Got hr %#x.\n", hr);
6181 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)&teststream, &teststream.mspid, 0, NULL);
6182 ok(hr == S_OK, "Got hr %#x.\n", hr);
6183 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)&teststream2, &teststream2.mspid, 0, NULL);
6184 ok(hr == S_OK, "Got hr %#x.\n", hr);
6185 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
6186 ok(hr == S_OK, "Got hr %#x.\n", hr);
6187 ok(filter != NULL, "Expected non-null filter\n");
6189 hr = reset_state(filter);
6190 ok(hr == S_OK, "Got hr %#x.\n", hr);
6192 teststream.state = 0xcc;
6193 teststream2.state = 0xcc;
6194 hr = set_state(filter);
6195 ok(hr == S_OK, "Got hr %#x.\n", hr);
6196 ok(teststream.state == expected_state, "Got state %#x.\n", teststream.state);
6197 ok(teststream2.state == expected_state, "Got state %#x.\n", teststream2.state);
6198 hr = IMediaStreamFilter_GetState(filter, 0, &state);
6199 ok(hr == S_OK, "Got hr %#x.\n", hr);
6200 ok(state == expected_state, "Got state %#x.\n", state);
6202 teststream.state = 0xcc;
6203 teststream2.state = 0xcc;
6204 hr = set_state(filter);
6205 ok(hr == S_OK, "Got hr %#x.\n", hr);
6206 ok(teststream.state == 0xcc, "Got state %#x.\n", teststream.state);
6207 ok(teststream2.state == 0xcc, "Got state %#x.\n", teststream2.state);
6209 hr = reset_state(filter);
6210 ok(hr == S_OK, "Got hr %#x.\n", hr);
6212 teststream.set_state_result = E_FAIL;
6213 teststream.state = 0xcc;
6214 teststream2.state = 0xcc;
6215 hr = set_state(filter);
6216 ok(hr == S_OK, "Got hr %#x.\n", hr);
6217 ok(teststream.state == 0xcc, "Got state %#x.\n", teststream.state);
6218 ok(teststream2.state == expected_state, "Got state %#x.\n", teststream2.state);
6219 hr = IMediaStreamFilter_GetState(filter, 0, &state);
6220 ok(hr == S_OK, "Got hr %#x.\n", hr);
6221 ok(state == expected_state, "Got state %#x.\n", state);
6223 hr = reset_state(filter);
6224 ok(hr == S_OK, "Got hr %#x.\n", hr);
6226 teststream.set_state_result = E_FAIL;
6227 teststream2.set_state_result = E_FAIL;
6228 teststream.state = 0xcc;
6229 teststream2.state = 0xcc;
6230 hr = set_state(filter);
6231 ok(hr == S_OK, "Got hr %#x.\n", hr);
6232 ok(teststream.state == 0xcc, "Got state %#x.\n", teststream.state);
6233 ok(teststream2.state == 0xcc, "Got state %#x.\n", teststream2.state);
6234 hr = IMediaStreamFilter_GetState(filter, 0, &state);
6235 ok(hr == S_OK, "Got hr %#x.\n", hr);
6236 ok(state == expected_state, "Got state %#x.\n", state);
6238 ref = IAMMultiMediaStream_Release(mmstream);
6239 ok(!ref, "Got outstanding refcount %d.\n", ref);
6240 ref = IMediaStreamFilter_Release(filter);
6241 ok(!ref, "Got outstanding refcount %d.\n", ref);
6242 ok(teststream.refcount == 1, "Got outstanding refcount %d.\n", teststream.refcount);
6243 ok(teststream2.refcount == 1, "Got outstanding refcount %d.\n", teststream2.refcount);
6246 static HRESULT mediastreamfilter_stop(IMediaStreamFilter *filter)
6248 return IMediaStreamFilter_Stop(filter);
6251 static HRESULT mediastreamfilter_pause(IMediaStreamFilter *filter)
6253 return IMediaStreamFilter_Pause(filter);
6256 static HRESULT mediastreamfilter_run(IMediaStreamFilter *filter)
6258 return IMediaStreamFilter_Run(filter, 0);
6261 void test_mediastreamfilter_stop_pause_run(void)
6263 check_mediastreamfilter_state(State_Stopped, mediastreamfilter_stop, mediastreamfilter_run);
6264 check_mediastreamfilter_state(State_Paused, mediastreamfilter_pause, mediastreamfilter_stop);
6265 check_mediastreamfilter_state(State_Running, mediastreamfilter_run, mediastreamfilter_stop);
6268 static void test_mediastreamfilter_support_seeking(void)
6270 IAMMultiMediaStream *mmstream = create_ammultimediastream();
6271 static const MSPID mspid1 = {0x88888888, 1};
6272 static const MSPID mspid2 = {0x88888888, 2};
6273 static const MSPID mspid3 = {0x88888888, 3};
6274 struct testfilter source1, source2, source3;
6275 IAMMediaStream *stream1, *stream2, *stream3;
6276 IMediaStreamFilter *filter;
6277 IPin *pin1, *pin2, *pin3;
6278 ULONG ref, seeking_ref;
6279 IGraphBuilder *graph;
6280 HRESULT hr;
6282 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
6283 ok(hr == S_OK, "Got hr %#x.\n", hr);
6284 hr = CoCreateInstance(&CLSID_AMAudioStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream1);
6285 ok(hr == S_OK, "Got hr %#x.\n", hr);
6286 hr = CoCreateInstance(&CLSID_AMAudioStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream2);
6287 ok(hr == S_OK, "Got hr %#x.\n", hr);
6288 hr = CoCreateInstance(&CLSID_AMAudioStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream3);
6289 ok(hr == S_OK, "Got hr %#x.\n", hr);
6290 hr = IAMMediaStream_Initialize(stream1, NULL, 0, &mspid1, STREAMTYPE_READ);
6291 ok(hr == S_OK, "Got hr %#x.\n", hr);
6292 hr = IAMMediaStream_Initialize(stream2, NULL, 0, &mspid2, STREAMTYPE_READ);
6293 ok(hr == S_OK, "Got hr %#x.\n", hr);
6294 hr = IAMMediaStream_Initialize(stream3, NULL, 0, &mspid3, STREAMTYPE_READ);
6295 ok(hr == S_OK, "Got hr %#x.\n", hr);
6296 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)stream1, &mspid1, 0, NULL);
6297 ok(hr == S_OK, "Got hr %#x.\n", hr);
6298 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)stream2, &mspid2, 0, NULL);
6299 ok(hr == S_OK, "Got hr %#x.\n", hr);
6300 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)stream3, &mspid3, 0, NULL);
6301 ok(hr == S_OK, "Got hr %#x.\n", hr);
6302 hr = IAMMediaStream_QueryInterface(stream1, &IID_IPin, (void **)&pin1);
6303 ok(hr == S_OK, "Got hr %#x.\n", hr);
6304 hr = IAMMediaStream_QueryInterface(stream2, &IID_IPin, (void **)&pin2);
6305 ok(hr == S_OK, "Got hr %#x.\n", hr);
6306 hr = IAMMediaStream_QueryInterface(stream3, &IID_IPin, (void **)&pin3);
6307 ok(hr == S_OK, "Got hr %#x.\n", hr);
6308 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
6309 ok(hr == S_OK, "Got hr %#x.\n", hr);
6310 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
6311 ok(hr == S_OK, "Got hr %#x.\n", hr);
6312 ok(graph != NULL, "Expected non-NULL graph.\n");
6313 testfilter_init(&source1);
6314 testfilter_init(&source2);
6315 testfilter_init(&source3);
6316 source2.IMediaSeeking_iface.lpVtbl = &testsource_seeking_vtbl;
6317 source3.IMediaSeeking_iface.lpVtbl = &testsource_seeking_vtbl;
6318 hr = IGraphBuilder_AddFilter(graph, &source1.filter.IBaseFilter_iface, NULL);
6319 ok(hr == S_OK, "Got hr %#x.\n", hr);
6320 hr = IGraphBuilder_AddFilter(graph, &source2.filter.IBaseFilter_iface, NULL);
6321 ok(hr == S_OK, "Got hr %#x.\n", hr);
6322 hr = IGraphBuilder_AddFilter(graph, &source3.filter.IBaseFilter_iface, NULL);
6323 ok(hr == S_OK, "Got hr %#x.\n", hr);
6325 hr = IMediaStreamFilter_SupportSeeking(filter, TRUE);
6326 ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr);
6328 hr = IGraphBuilder_ConnectDirect(graph, &source1.source.pin.IPin_iface, pin1, &audio_mt);
6329 ok(hr == S_OK, "Got hr %#x.\n", hr);
6331 source2.get_duration_hr = E_FAIL;
6333 hr = IMediaStreamFilter_SupportSeeking(filter, TRUE);
6334 ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr);
6336 hr = IGraphBuilder_ConnectDirect(graph, &source2.source.pin.IPin_iface, pin2, &audio_mt);
6337 ok(hr == S_OK, "Got hr %#x.\n", hr);
6339 hr = IMediaStreamFilter_SupportSeeking(filter, TRUE);
6340 ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr);
6342 hr = IGraphBuilder_ConnectDirect(graph, &source3.source.pin.IPin_iface, pin3, &audio_mt);
6343 ok(hr == S_OK, "Got hr %#x.\n", hr);
6345 check_interface(filter, &IID_IMediaSeeking, FALSE);
6347 seeking_ref = get_refcount(&source3.IMediaSeeking_iface);
6349 hr = IMediaStreamFilter_SupportSeeking(filter, TRUE);
6350 ok(hr == S_OK, "Got hr %#x.\n", hr);
6352 check_interface(filter, &IID_IMediaSeeking, TRUE);
6354 ref = get_refcount(&source3.IMediaSeeking_iface);
6355 ok(ref == seeking_ref, "Expected outstanding refcount %d, got %d.\n", seeking_ref, ref);
6357 hr = IMediaStreamFilter_SupportSeeking(filter, TRUE);
6358 ok(hr == HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED), "Got hr %#x.\n", hr);
6360 IGraphBuilder_Disconnect(graph, pin1);
6361 IGraphBuilder_Disconnect(graph, &source1.source.pin.IPin_iface);
6363 IGraphBuilder_Disconnect(graph, pin2);
6364 IGraphBuilder_Disconnect(graph, &source2.source.pin.IPin_iface);
6366 IGraphBuilder_Disconnect(graph, pin3);
6367 IGraphBuilder_Disconnect(graph, &source3.source.pin.IPin_iface);
6369 ref = IAMMultiMediaStream_Release(mmstream);
6370 ok(!ref, "Got outstanding refcount %d.\n", ref);
6371 ref = IGraphBuilder_Release(graph);
6372 ok(!ref, "Got outstanding refcount %d.\n", ref);
6373 ref = IMediaStreamFilter_Release(filter);
6374 ok(!ref, "Got outstanding refcount %d.\n", ref);
6375 IPin_Release(pin1);
6376 ref = IAMMediaStream_Release(stream1);
6377 ok(!ref, "Got outstanding refcount %d.\n", ref);
6378 IPin_Release(pin2);
6379 ref = IAMMediaStream_Release(stream2);
6380 ok(!ref, "Got outstanding refcount %d.\n", ref);
6381 IPin_Release(pin3);
6382 ref = IAMMediaStream_Release(stream3);
6383 ok(!ref, "Got outstanding refcount %d.\n", ref);
6386 static void check_mediastreamfilter_seeking(void (*check)(IMediaSeeking *seeking, struct testfilter *source1,
6387 struct testfilter *source2, struct testfilter *source3, HRESULT source2_hr, HRESULT expected_hr))
6389 IAMMultiMediaStream *mmstream = create_ammultimediastream();
6390 static const MSPID mspid1 = {0x88888888, 1};
6391 static const MSPID mspid2 = {0x88888888, 2};
6392 static const MSPID mspid3 = {0x88888888, 3};
6393 IMediaStreamFilter *filter;
6394 struct testfilter source1;
6395 struct testfilter source2;
6396 struct testfilter source3;
6397 IAMMediaStream *stream1;
6398 IAMMediaStream *stream2;
6399 IAMMediaStream *stream3;
6400 IMediaSeeking *seeking;
6401 IGraphBuilder *graph;
6402 IPin *pin1;
6403 IPin *pin2;
6404 IPin *pin3;
6405 HRESULT hr;
6406 ULONG ref;
6408 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
6409 ok(hr == S_OK, "Got hr %#x.\n", hr);
6410 hr = CoCreateInstance(&CLSID_AMAudioStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream1);
6411 ok(hr == S_OK, "Got hr %#x.\n", hr);
6412 hr = CoCreateInstance(&CLSID_AMAudioStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream2);
6413 ok(hr == S_OK, "Got hr %#x.\n", hr);
6414 hr = CoCreateInstance(&CLSID_AMAudioStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMediaStream, (void **)&stream3);
6415 ok(hr == S_OK, "Got hr %#x.\n", hr);
6416 hr = IAMMediaStream_Initialize(stream1, NULL, 0, &mspid1, STREAMTYPE_READ);
6417 ok(hr == S_OK, "Got hr %#x.\n", hr);
6418 hr = IAMMediaStream_Initialize(stream2, NULL, 0, &mspid2, STREAMTYPE_READ);
6419 ok(hr == S_OK, "Got hr %#x.\n", hr);
6420 hr = IAMMediaStream_Initialize(stream3, NULL, 0, &mspid3, STREAMTYPE_READ);
6421 ok(hr == S_OK, "Got hr %#x.\n", hr);
6422 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)stream1, &mspid1, 0, NULL);
6423 ok(hr == S_OK, "Got hr %#x.\n", hr);
6424 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)stream2, &mspid2, 0, NULL);
6425 ok(hr == S_OK, "Got hr %#x.\n", hr);
6426 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)stream3, &mspid3, 0, NULL);
6427 ok(hr == S_OK, "Got hr %#x.\n", hr);
6428 hr = IAMMediaStream_QueryInterface(stream1, &IID_IPin, (void **)&pin1);
6429 ok(hr == S_OK, "Got hr %#x.\n", hr);
6430 hr = IAMMediaStream_QueryInterface(stream2, &IID_IPin, (void **)&pin2);
6431 ok(hr == S_OK, "Got hr %#x.\n", hr);
6432 hr = IAMMediaStream_QueryInterface(stream3, &IID_IPin, (void **)&pin3);
6433 ok(hr == S_OK, "Got hr %#x.\n", hr);
6434 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
6435 ok(hr == S_OK, "Got hr %#x.\n", hr);
6436 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
6437 ok(hr == S_OK, "Got hr %#x.\n", hr);
6438 ok(graph != NULL, "Expected non-NULL graph.\n");
6439 testfilter_init(&source1);
6440 testfilter_init(&source2);
6441 testfilter_init(&source3);
6442 source1.IMediaSeeking_iface.lpVtbl = &testsource_seeking_vtbl;
6443 source2.IMediaSeeking_iface.lpVtbl = &testsource_seeking_vtbl;
6444 source3.IMediaSeeking_iface.lpVtbl = &testsource_seeking_vtbl;
6445 hr = IGraphBuilder_AddFilter(graph, &source1.filter.IBaseFilter_iface, NULL);
6446 ok(hr == S_OK, "Got hr %#x.\n", hr);
6447 hr = IGraphBuilder_AddFilter(graph, &source2.filter.IBaseFilter_iface, NULL);
6448 ok(hr == S_OK, "Got hr %#x.\n", hr);
6449 hr = IGraphBuilder_AddFilter(graph, &source3.filter.IBaseFilter_iface, NULL);
6450 ok(hr == S_OK, "Got hr %#x.\n", hr);
6452 hr = IGraphBuilder_ConnectDirect(graph, &source2.source.pin.IPin_iface, pin2, &audio_mt);
6453 ok(hr == S_OK, "Got hr %#x.\n", hr);
6454 hr = IGraphBuilder_ConnectDirect(graph, &source3.source.pin.IPin_iface, pin3, &audio_mt);
6455 ok(hr == S_OK, "Got hr %#x.\n", hr);
6457 hr = IMediaStreamFilter_SupportSeeking(filter, TRUE);
6458 ok(hr == S_OK, "Got hr %#x.\n", hr);
6460 hr = IGraphBuilder_ConnectDirect(graph, &source1.source.pin.IPin_iface, pin1, &audio_mt);
6461 ok(hr == S_OK, "Got hr %#x.\n", hr);
6463 hr = IMediaStreamFilter_QueryInterface(filter, &IID_IMediaSeeking, (void **)&seeking);
6464 ok(hr == S_OK, "Got hr %#x.\n", hr);
6466 check(seeking, &source1, &source2, &source3, S_OK, S_OK);
6467 check(seeking, &source1, &source2, &source3, E_FAIL, E_FAIL);
6468 check(seeking, &source1, &source2, &source3, E_NOTIMPL, E_NOTIMPL);
6470 source2.IMediaSeeking_iface.lpVtbl = NULL;
6472 check(seeking, &source1, &source2, &source3, S_OK, E_NOTIMPL);
6474 source2.IMediaSeeking_iface.lpVtbl = &testsource_seeking_vtbl;
6476 IGraphBuilder_Disconnect(graph, pin2);
6477 IGraphBuilder_Disconnect(graph, &source2.source.pin.IPin_iface);
6479 check(seeking, &source1, &source2, &source3, S_OK, E_NOTIMPL);
6481 IGraphBuilder_Disconnect(graph, pin2);
6482 IGraphBuilder_Disconnect(graph, &source2.source.pin.IPin_iface);
6483 IGraphBuilder_Disconnect(graph, pin3);
6484 IGraphBuilder_Disconnect(graph, &source3.source.pin.IPin_iface);
6486 ref = IAMMultiMediaStream_Release(mmstream);
6487 ok(!ref, "Got outstanding refcount %d.\n", ref);
6488 ref = IGraphBuilder_Release(graph);
6489 ok(!ref, "Got outstanding refcount %d.\n", ref);
6490 IMediaSeeking_Release(seeking);
6491 ref = IMediaStreamFilter_Release(filter);
6492 ok(!ref, "Got outstanding refcount %d.\n", ref);
6493 IPin_Release(pin1);
6494 ref = IAMMediaStream_Release(stream1);
6495 ok(!ref, "Got outstanding refcount %d.\n", ref);
6496 IPin_Release(pin2);
6497 ref = IAMMediaStream_Release(stream2);
6498 ok(!ref, "Got outstanding refcount %d.\n", ref);
6499 IPin_Release(pin3);
6500 ref = IAMMediaStream_Release(stream3);
6501 ok(!ref, "Got outstanding refcount %d.\n", ref);
6504 static void check_mediastreamfilter_set_positions(IMediaSeeking *seeking, struct testfilter *source1,
6505 struct testfilter *source2, struct testfilter *source3, HRESULT source2_hr, HRESULT expected_hr)
6507 LONGLONG current_position = 12345678;
6508 LONGLONG stop_position = 87654321;
6509 HRESULT hr;
6511 source2->set_positions_hr = source2_hr;
6512 source1->current_position = 0xdeadbeefdeadbeefULL;
6513 source1->stop_position = 0xdeadbeefdeadbeefULL;
6514 source2->current_position = 0xdeadbeefdeadbeefULL;
6515 source2->stop_position = 0xdeadbeefdeadbeefULL;
6516 source3->current_position = 0xdeadbeefdeadbeefULL;
6517 source3->stop_position = 0xdeadbeefdeadbeefULL;
6518 hr = IMediaSeeking_SetPositions(seeking, &current_position, AM_SEEKING_AbsolutePositioning,
6519 &stop_position, AM_SEEKING_AbsolutePositioning);
6520 ok(hr == expected_hr, "Got hr %#x.\n", hr);
6521 ok(source1->current_position == 0xdeadbeefdeadbeefULL, "Got current position %s.\n",
6522 wine_dbgstr_longlong(source1->current_position));
6523 ok(source1->stop_position == 0xdeadbeefdeadbeefULL, "Got stop position %s.\n",
6524 wine_dbgstr_longlong(source1->stop_position));
6525 if (SUCCEEDED(expected_hr))
6527 ok(source2->current_position == 12345678, "Got current position %s.\n",
6528 wine_dbgstr_longlong(source2->current_position));
6529 ok(source2->stop_position == 87654321, "Got stop position %s.\n",
6530 wine_dbgstr_longlong(source2->stop_position));
6532 ok(source3->current_position == 0xdeadbeefdeadbeefULL, "Got current position %s.\n",
6533 wine_dbgstr_longlong(source3->current_position));
6534 ok(source3->stop_position == 0xdeadbeefdeadbeefULL, "Got stop position %s.\n",
6535 wine_dbgstr_longlong(source3->stop_position));
6538 static void check_mediastreamfilter_get_duration(IMediaSeeking *seeking, struct testfilter *source1,
6539 struct testfilter *source2, struct testfilter *source3, HRESULT source2_hr, HRESULT expected_hr)
6541 LONGLONG duration = 0xdeadbeefdeadbeefULL;
6542 HRESULT hr;
6544 source2->get_duration_hr = source2_hr;
6545 hr = IMediaSeeking_GetDuration(seeking, &duration);
6546 ok(hr == expected_hr, "Got hr %#x.\n", hr);
6547 if (SUCCEEDED(expected_hr))
6548 ok(duration == 0x8000000000000000ULL, "Got duration %s.\n", wine_dbgstr_longlong(duration));
6549 else
6550 ok(duration == 0xdeadbeefdeadbeefULL, "Got duration %s.\n", wine_dbgstr_longlong(duration));
6553 static void check_mediastreamfilter_get_stop_position(IMediaSeeking *seeking, struct testfilter *source1,
6554 struct testfilter *source2, struct testfilter *source3, HRESULT source2_hr, HRESULT expected_hr)
6556 LONGLONG stop = 0xdeadbeefdeadbeefULL;
6557 HRESULT hr;
6559 source2->get_stop_position_hr = source2_hr;
6560 hr = IMediaSeeking_GetStopPosition(seeking, &stop);
6561 ok(hr == expected_hr, "Got hr %#x.\n", hr);
6562 if (SUCCEEDED(expected_hr))
6563 ok(stop == 0x8000000000000000ULL, "Got stop position %s.\n", wine_dbgstr_longlong(stop));
6564 else
6565 ok(stop == 0xdeadbeefdeadbeefULL, "Got stop position %s.\n", wine_dbgstr_longlong(stop));
6568 static void check_mediastreamfilter_is_format_supported(IMediaSeeking *seeking, struct testfilter *source1,
6569 struct testfilter *source2, struct testfilter *source3, HRESULT source2_hr, HRESULT expected_hr)
6571 HRESULT hr;
6573 source2->is_format_supported_hr = source2_hr;
6574 hr = IMediaSeeking_IsFormatSupported(seeking, &TIME_FORMAT_MEDIA_TIME);
6575 ok(hr == expected_hr, "Got hr %#x.\n", hr);
6578 static void test_mediastreamfilter_seeking(void)
6580 check_mediastreamfilter_seeking(check_mediastreamfilter_set_positions);
6581 check_mediastreamfilter_seeking(check_mediastreamfilter_get_duration);
6582 check_mediastreamfilter_seeking(check_mediastreamfilter_get_stop_position);
6583 check_mediastreamfilter_seeking(check_mediastreamfilter_is_format_supported);
6586 static void test_mediastreamfilter_get_current_stream_time(void)
6588 IAMMultiMediaStream *mmstream = create_ammultimediastream();
6589 STREAM_TIME filter_start_time;
6590 IMediaStreamFilter *filter;
6591 IMediaFilter *media_filter;
6592 struct testclock clock;
6593 IGraphBuilder *graph;
6594 STREAM_TIME time;
6595 HRESULT hr;
6596 ULONG ref;
6598 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
6599 ok(hr == S_OK, "Got hr %#x.\n", hr);
6600 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
6601 ok(hr == S_OK, "Got hr %#x.\n", hr);
6602 ok(!!filter, "Expected non-null filter.\n");
6603 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, NULL);
6604 ok(hr == S_OK, "Got hr %#x.\n", hr);
6605 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
6606 ok(hr == S_OK, "Got hr %#x.\n", hr);
6607 ok(graph != NULL, "Expected non-NULL graph.\n");
6608 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void **)&media_filter);
6609 ok(hr == S_OK, "Got hr %#x.\n", hr);
6610 testclock_init(&clock);
6612 /* Crashes on native. */
6613 if (0)
6615 hr = IMediaStreamFilter_GetCurrentStreamTime(filter, NULL);
6616 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
6617 hr = IAMMultiMediaStream_GetTime(mmstream, NULL);
6618 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
6621 time = 0xdeadbeefdeadbeef;
6622 hr = IMediaStreamFilter_GetCurrentStreamTime(filter, &time);
6623 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
6624 ok(time == 0, "Got time %s.\n", wine_dbgstr_longlong(time));
6625 time = 0xdeadbeefdeadbeef;
6626 hr = IAMMultiMediaStream_GetTime(mmstream, &time);
6627 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
6628 ok(time == 0, "Got time %s.\n", wine_dbgstr_longlong(time));
6630 hr = IMediaFilter_SetSyncSource(media_filter, &clock.IReferenceClock_iface);
6631 ok(hr == S_OK, "Got hr %#x.\n", hr);
6633 clock.get_time_hr = E_FAIL;
6635 time = 0xdeadbeefdeadbeef;
6636 hr = IMediaStreamFilter_GetCurrentStreamTime(filter, &time);
6637 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
6638 ok(time == 0, "Got time %s.\n", wine_dbgstr_longlong(time));
6639 time = 0xdeadbeefdeadbeef;
6640 hr = IAMMultiMediaStream_GetTime(mmstream, &time);
6641 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
6642 ok(time == 0, "Got time %s.\n", wine_dbgstr_longlong(time));
6644 clock.time = 23456789;
6645 clock.get_time_hr = S_OK;
6647 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
6648 ok(hr == S_OK, "Got hr %#x.\n", hr);
6650 hr = IMediaStreamFilter_GetCurrentStreamTime(filter, &filter_start_time);
6651 ok(hr == S_OK, "Got hr %#x.\n", hr);
6653 clock.time = 34567890;
6655 time = 0xdeadbeefdeadbeef;
6656 hr = IMediaStreamFilter_GetCurrentStreamTime(filter, &time);
6657 ok(hr == S_OK, "Got hr %#x.\n", hr);
6658 ok(time == 11111101 + filter_start_time, "Got time %s.\n", wine_dbgstr_longlong(time));
6659 time = 0xdeadbeefdeadbeef;
6660 hr = IAMMultiMediaStream_GetTime(mmstream, &time);
6661 ok(hr == S_OK, "Got hr %#x.\n", hr);
6662 ok(time == 11111101 + filter_start_time, "Got time %s.\n", wine_dbgstr_longlong(time));
6664 ref = IAMMultiMediaStream_Release(mmstream);
6665 ok(!ref, "Got outstanding refcount %d.\n", ref);
6666 IMediaFilter_Release(media_filter);
6667 ref = IGraphBuilder_Release(graph);
6668 ok(!ref, "Got outstanding refcount %d.\n", ref);
6669 ref = IMediaStreamFilter_Release(filter);
6670 ok(!ref, "Got outstanding refcount %d.\n", ref);
6673 static void test_mediastreamfilter_reference_time_to_stream_time(void)
6675 IMediaStreamFilter *filter;
6676 struct testclock clock;
6677 REFERENCE_TIME time;
6678 HRESULT hr;
6679 ULONG ref;
6681 hr = CoCreateInstance(&CLSID_MediaStreamFilter, NULL, CLSCTX_INPROC_SERVER,
6682 &IID_IMediaStreamFilter, (void **)&filter);
6683 ok(hr == S_OK, "Got hr %#x.\n", hr);
6684 testclock_init(&clock);
6686 hr = IMediaStreamFilter_ReferenceTimeToStreamTime(filter, NULL);
6687 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
6689 time = 0xdeadbeefdeadbeef;
6690 hr = IMediaStreamFilter_ReferenceTimeToStreamTime(filter, &time);
6691 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
6692 ok(time == 0xdeadbeefdeadbeef, "Got time %s.\n", wine_dbgstr_longlong(time));
6694 hr = IMediaStreamFilter_SetSyncSource(filter, &clock.IReferenceClock_iface);
6695 ok(hr == S_OK, "Got hr %#x.\n", hr);
6697 clock.get_time_hr = E_FAIL;
6699 /* Crashes on native. */
6700 if (0)
6702 hr = IMediaStreamFilter_ReferenceTimeToStreamTime(filter, NULL);
6703 ok(hr == S_FALSE, "Got hr %#x.\n", hr);
6706 time = 0xdeadbeefdeadbeef;
6707 hr = IMediaStreamFilter_ReferenceTimeToStreamTime(filter, &time);
6708 ok(hr == S_OK, "Got hr %#x.\n", hr);
6709 ok(time == 0xdeadbeefdeadbeef, "Got time %s.\n", wine_dbgstr_longlong(time));
6711 hr = IMediaStreamFilter_Run(filter, 23456789);
6712 ok(hr == S_OK, "Got hr %#x.\n", hr);
6714 time = 0xdeadbeefdeadbeef;
6715 hr = IMediaStreamFilter_ReferenceTimeToStreamTime(filter, &time);
6716 ok(hr == S_OK, "Got hr %#x.\n", hr);
6717 ok(time == 0xdeadbeefdd47d2da, "Got time %s.\n", wine_dbgstr_longlong(time));
6719 clock.time = 34567890;
6720 clock.get_time_hr = S_OK;
6722 time = 0xdeadbeefdeadbeef;
6723 hr = IMediaStreamFilter_ReferenceTimeToStreamTime(filter, &time);
6724 ok(hr == S_OK, "Got hr %#x.\n", hr);
6725 ok(time == 0xdeadbeefdd47d2da, "Got time %s.\n", wine_dbgstr_longlong(time));
6727 ref = IMediaStreamFilter_Release(filter);
6728 ok(!ref, "Got outstanding refcount %d.\n", ref);
6731 struct mediastreamfilter_wait_until_params
6733 IMediaStreamFilter *filter;
6734 REFERENCE_TIME time;
6735 HRESULT expected_hr;
6738 static DWORD CALLBACK mediastreamfilter_wait_until(void *p)
6740 struct mediastreamfilter_wait_until_params *params = (struct mediastreamfilter_wait_until_params *)p;
6741 HRESULT hr;
6743 hr = IMediaStreamFilter_WaitUntil(params->filter, params->time);
6744 ok(hr == params->expected_hr, "Got hr %#x.\n", hr);
6746 return 0;
6749 static void test_mediastreamfilter_wait_until(void)
6751 struct mediastreamfilter_wait_until_params params1;
6752 struct mediastreamfilter_wait_until_params params2;
6753 struct advise_time_cookie cookie1 = { 0 };
6754 struct advise_time_cookie cookie2 = { 0 };
6755 IMediaStreamFilter *filter;
6756 struct testclock clock;
6757 HANDLE thread1;
6758 HANDLE thread2;
6759 HRESULT hr;
6760 ULONG ref;
6762 hr = CoCreateInstance(&CLSID_MediaStreamFilter, NULL, CLSCTX_INPROC_SERVER,
6763 &IID_IMediaStreamFilter, (void **)&filter);
6764 ok(hr == S_OK, "Got hr %#x.\n", hr);
6765 testclock_init(&clock);
6766 cookie1.advise_time_called_event = CreateEventW(NULL, FALSE, FALSE, NULL);
6767 cookie2.advise_time_called_event = CreateEventW(NULL, FALSE, FALSE, NULL);
6769 hr = IMediaStreamFilter_Run(filter, 12345678);
6770 ok(hr == S_OK, "Got hr %#x.\n", hr);
6772 hr = IMediaStreamFilter_WaitUntil(filter, 23456789);
6773 ok(hr == E_FAIL, "Got hr %#x.\n", hr);
6775 hr = IMediaStreamFilter_Stop(filter);
6776 ok(hr == S_OK, "Got hr %#x.\n", hr);
6778 hr = IMediaStreamFilter_SetSyncSource(filter, &clock.IReferenceClock_iface);
6779 ok(hr == S_OK, "Got hr %#x.\n", hr);
6781 clock.advise_time_cookie = &cookie1;
6783 params1.filter = filter;
6784 params1.time = 23456789;
6785 params1.expected_hr = S_OK;
6786 thread1 = CreateThread(NULL, 0, mediastreamfilter_wait_until, &params1, 0, NULL);
6787 ok(!WaitForSingleObject(cookie1.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
6788 ok(WaitForSingleObject(thread1, 100) == WAIT_TIMEOUT, "WaitUntil returned prematurely.\n");
6790 ok(cookie1.base == 23456789, "Got base %s.\n", wine_dbgstr_longlong(cookie1.base));
6791 ok(cookie1.offset == 12345678, "Got offset %s.\n", wine_dbgstr_longlong(cookie1.offset));
6792 ok(!!cookie1.event, "Expected non-NULL event.\n");
6794 SetEvent(cookie1.event);
6796 ok(!WaitForSingleObject(thread1, 2000), "Wait timed out.\n");
6797 CloseHandle(thread1);
6799 ok(!cookie1.unadvise_called, "Unexpected Unadvise call.\n");
6801 hr = IMediaStreamFilter_Run(filter, 12345678);
6802 ok(hr == S_OK, "Got hr %#x.\n", hr);
6804 clock.time = 30000000;
6806 clock.advise_time_cookie = &cookie1;
6808 params1.filter = filter;
6809 params1.time = 23456789;
6810 params1.expected_hr = S_OK;
6811 thread1 = CreateThread(NULL, 0, mediastreamfilter_wait_until, &params1, 0, NULL);
6812 ok(!WaitForSingleObject(cookie1.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
6813 ok(WaitForSingleObject(thread1, 100) == WAIT_TIMEOUT, "WaitUntil returned prematurely.\n");
6815 ok(cookie1.base == 23456789, "Got base %s.\n", wine_dbgstr_longlong(cookie1.base));
6816 ok(cookie1.offset == 12345678, "Got offset %s.\n", wine_dbgstr_longlong(cookie1.offset));
6817 ok(!!cookie1.event, "Expected non-NULL event.\n");
6819 clock.advise_time_cookie = &cookie2;
6821 params2.filter = filter;
6822 params2.time = 11111111;
6823 params2.expected_hr = S_OK;
6824 thread2 = CreateThread(NULL, 0, mediastreamfilter_wait_until, &params2, 0, NULL);
6825 ok(!WaitForSingleObject(cookie2.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
6826 ok(WaitForSingleObject(thread2, 100) == WAIT_TIMEOUT, "WaitUntil returned prematurely.\n");
6828 ok(cookie2.base == 11111111, "Got base %s.\n", wine_dbgstr_longlong(cookie2.base));
6829 ok(cookie2.offset == 12345678, "Got offset %s.\n", wine_dbgstr_longlong(cookie2.offset));
6830 ok(!!cookie2.event, "Expected non-NULL event.\n");
6832 SetEvent(cookie1.event);
6834 ok(!WaitForSingleObject(thread1, 2000), "Wait timed out.\n");
6835 CloseHandle(thread1);
6837 ok(WaitForSingleObject(thread2, 100) == WAIT_TIMEOUT, "WaitUntil returned prematurely.\n");
6839 SetEvent(cookie2.event);
6841 ok(!WaitForSingleObject(thread2, 2000), "Wait timed out.\n");
6842 CloseHandle(thread2);
6844 clock.advise_time_cookie = &cookie1;
6846 params1.filter = filter;
6847 params1.time = 23456789;
6848 params1.expected_hr = S_FALSE;
6849 thread1 = CreateThread(NULL, 0, mediastreamfilter_wait_until, &params1, 0, NULL);
6850 ok(!WaitForSingleObject(cookie1.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
6851 ok(WaitForSingleObject(thread1, 100) == WAIT_TIMEOUT, "WaitUntil returned prematurely.\n");
6853 clock.advise_time_cookie = &cookie2;
6855 params2.filter = filter;
6856 params2.time = 23456789;
6857 params2.expected_hr = S_FALSE;
6858 thread2 = CreateThread(NULL, 0, mediastreamfilter_wait_until, &params2, 0, NULL);
6859 ok(!WaitForSingleObject(cookie2.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
6860 ok(WaitForSingleObject(thread2, 100) == WAIT_TIMEOUT, "WaitUntil returned prematurely.\n");
6862 hr = IMediaStreamFilter_Flush(filter, FALSE);
6863 ok(hr == S_OK, "Got hr %#x.\n", hr);
6865 ok(cookie1.unadvise_called, "Expected Unadvise to be called.\n");
6866 ok(cookie2.unadvise_called, "Expected Unadvise to be called.\n");
6868 ok(!WaitForSingleObject(thread1, 2000), "Wait timed out.\n");
6869 CloseHandle(thread1);
6870 ok(!WaitForSingleObject(thread2, 2000), "Wait timed out.\n");
6871 CloseHandle(thread2);
6873 clock.advise_time_cookie = &cookie1;
6875 params1.filter = filter;
6876 params1.time = 23456789;
6877 params1.expected_hr = S_FALSE;
6878 thread1 = CreateThread(NULL, 0, mediastreamfilter_wait_until, &params1, 0, NULL);
6879 ok(!WaitForSingleObject(cookie1.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
6880 ok(WaitForSingleObject(thread1, 100) == WAIT_TIMEOUT, "WaitUntil returned prematurely.\n");
6882 clock.advise_time_cookie = &cookie2;
6884 params2.filter = filter;
6885 params2.time = 23456789;
6886 params2.expected_hr = S_FALSE;
6887 thread2 = CreateThread(NULL, 0, mediastreamfilter_wait_until, &params2, 0, NULL);
6888 ok(!WaitForSingleObject(cookie2.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
6889 ok(WaitForSingleObject(thread2, 100) == WAIT_TIMEOUT, "WaitUntil returned prematurely.\n");
6891 hr = IMediaStreamFilter_Stop(filter);
6892 ok(hr == S_OK, "Got hr %#x.\n", hr);
6894 ok(cookie1.unadvise_called, "Expected Unadvise to be called.\n");
6895 ok(cookie2.unadvise_called, "Expected Unadvise to be called.\n");
6897 ok(!WaitForSingleObject(thread1, 2000), "Wait timed out.\n");
6898 CloseHandle(thread1);
6899 ok(!WaitForSingleObject(thread2, 2000), "Wait timed out.\n");
6900 CloseHandle(thread2);
6902 CloseHandle(cookie1.advise_time_called_event);
6903 CloseHandle(cookie2.advise_time_called_event);
6905 ref = IMediaStreamFilter_Release(filter);
6906 ok(!ref, "Got outstanding refcount %d.\n", ref);
6909 static void test_mediastreamfilter_end_of_stream(void)
6911 IAMMultiMediaStream *mmstream = create_ammultimediastream();
6912 struct testfilter source1, source2;
6913 IMediaStream *stream1, *stream2;
6914 IMediaControl *media_control;
6915 IMediaStreamFilter *filter;
6916 struct graph graph;
6917 IPin *pin1, *pin2;
6918 HRESULT hr;
6919 ULONG ref;
6921 graph_init(&graph);
6922 hr = IFilterGraph2_QueryInterface(&graph.IFilterGraph2_iface, &IID_IMediaControl, (void **)&media_control);
6923 ok(hr == S_OK, "Got hr %#x.\n", hr);
6925 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, (IGraphBuilder *)&graph.IFilterGraph2_iface);
6926 ok(hr == S_OK, "Got hr %#x.\n", hr);
6927 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream1);
6928 ok(hr == S_OK, "Got hr %#x.\n", hr);
6929 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream2);
6930 ok(hr == S_OK, "Got hr %#x.\n", hr);
6931 hr = IMediaStream_QueryInterface(stream1, &IID_IPin, (void **)&pin1);
6932 ok(hr == S_OK, "Got hr %#x.\n", hr);
6933 hr = IMediaStream_QueryInterface(stream2, &IID_IPin, (void **)&pin2);
6934 ok(hr == S_OK, "Got hr %#x.\n", hr);
6935 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
6936 ok(hr == S_OK, "Got hr %#x.\n", hr);
6937 ok(filter != NULL, "Expected non-null filter\n");
6938 testfilter_init(&source1);
6939 testfilter_init(&source2);
6940 hr = IFilterGraph2_AddFilter(&graph.IFilterGraph2_iface, &source1.filter.IBaseFilter_iface, NULL);
6941 ok(hr == S_OK, "Got hr %#x.\n", hr);
6942 hr = IFilterGraph2_AddFilter(&graph.IFilterGraph2_iface, &source2.filter.IBaseFilter_iface, NULL);
6943 ok(hr == S_OK, "Got hr %#x.\n", hr);
6945 hr = IPin_Connect(&source1.source.pin.IPin_iface, pin1, &audio_mt);
6946 ok(hr == S_OK, "Got hr %#x.\n", hr);
6947 hr = IPin_Connect(&source2.source.pin.IPin_iface, pin2, &rgb32_mt);
6948 ok(hr == S_OK, "Got hr %#x.\n", hr);
6950 /* Initially, EC_COMPLETE notifications are disabled. */
6951 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
6952 ok(hr == S_OK, "Got hr %#x.\n", hr);
6954 graph.got_notify = 0;
6956 hr = IMediaStreamFilter_EndOfStream(filter);
6957 ok(hr == S_OK, "Got hr %#x.\n", hr);
6958 hr = IMediaStreamFilter_EndOfStream(filter);
6959 ok(hr == S_OK, "Got hr %#x.\n", hr);
6961 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
6963 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
6964 ok(hr == S_OK, "Got hr %#x.\n", hr);
6966 /* Unsuccsessful call to SupportSeeking does not enable EC_COMPLETE notifications. */
6967 hr = IMediaStreamFilter_SupportSeeking(filter, TRUE);
6968 ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr);
6970 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
6971 ok(hr == S_OK, "Got hr %#x.\n", hr);
6973 graph.got_notify = 0;
6975 hr = IMediaStreamFilter_EndOfStream(filter);
6976 ok(hr == S_OK, "Got hr %#x.\n", hr);
6977 hr = IMediaStreamFilter_EndOfStream(filter);
6978 ok(hr == S_OK, "Got hr %#x.\n", hr);
6980 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
6982 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
6983 ok(hr == S_OK, "Got hr %#x.\n", hr);
6985 /* Successful call to SupportSeeking enables EC_COMPLETE notifications. */
6986 source1.IMediaSeeking_iface.lpVtbl = &testsource_seeking_vtbl;
6988 hr = IMediaStreamFilter_SupportSeeking(filter, TRUE);
6989 ok(hr == S_OK, "Got hr %#x.\n", hr);
6991 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
6992 ok(hr == S_OK, "Got hr %#x.\n", hr);
6994 graph.got_notify = 0;
6996 hr = IMediaStreamFilter_EndOfStream(filter);
6997 ok(hr == S_OK, "Got hr %#x.\n", hr);
6999 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7001 hr = IMediaStreamFilter_EndOfStream(filter);
7002 ok(hr == S_OK, "Got hr %#x.\n", hr);
7004 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7006 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
7007 ok(hr == S_OK, "Got hr %#x.\n", hr);
7009 /* EC_COMPLETE is sent on paused->running state transition
7010 * if EndOfStream has been called for all streams. */
7011 graph.got_notify = 0;
7013 hr = IMediaStreamFilter_EndOfStream(filter);
7014 ok(hr == S_OK, "Got hr %#x.\n", hr);
7015 hr = IMediaStreamFilter_EndOfStream(filter);
7016 ok(hr == S_OK, "Got hr %#x.\n", hr);
7018 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7020 hr = IMediaControl_Pause(media_control);
7021 ok(hr == S_OK, "Got hr %#x.\n", hr);
7023 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7025 hr = IMediaControl_Run(media_control);
7026 ok(hr == S_OK, "Got hr %#x.\n", hr);
7028 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7030 hr = IMediaControl_Run(media_control);
7031 ok(hr == S_OK, "Got hr %#x.\n", hr);
7033 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7035 hr = IMediaControl_Stop(media_control);
7036 ok(hr == S_OK, "Got hr %#x.\n", hr);
7038 /* EC_COMPLETE is sent on paused->running state transition
7039 * if EndOfStream has been called for all streams. */
7040 graph.got_notify = 0;
7042 hr = IMediaStreamFilter_EndOfStream(filter);
7043 ok(hr == S_OK, "Got hr %#x.\n", hr);
7044 hr = IMediaStreamFilter_EndOfStream(filter);
7045 ok(hr == S_OK, "Got hr %#x.\n", hr);
7047 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7049 hr = IMediaControl_Pause(media_control);
7050 ok(hr == S_OK, "Got hr %#x.\n", hr);
7052 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7054 hr = IMediaControl_Run(media_control);
7055 ok(hr == S_OK, "Got hr %#x.\n", hr);
7057 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7059 hr = IMediaControl_Stop(media_control);
7060 ok(hr == S_OK, "Got hr %#x.\n", hr);
7062 /* EndOfStream count is reset on paused->stopped state transition. */
7063 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
7064 ok(hr == S_OK, "Got hr %#x.\n", hr);
7066 graph.got_notify = 0;
7068 hr = IMediaStreamFilter_EndOfStream(filter);
7069 ok(hr == S_OK, "Got hr %#x.\n", hr);
7071 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
7072 ok(hr == S_OK, "Got hr %#x.\n", hr);
7073 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
7074 ok(hr == S_OK, "Got hr %#x.\n", hr);
7076 hr = IMediaStreamFilter_EndOfStream(filter);
7077 ok(hr == S_OK, "Got hr %#x.\n", hr);
7079 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7081 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
7082 ok(hr == S_OK, "Got hr %#x.\n", hr);
7084 /* EOS count is not reset on running->paused state transition. */
7085 hr = IMediaControl_Run(media_control);
7086 ok(hr == S_OK, "Got hr %#x.\n", hr);
7088 graph.got_notify = 0;
7090 hr = IMediaStreamFilter_EndOfStream(filter);
7091 ok(hr == S_OK, "Got hr %#x.\n", hr);
7093 hr = IMediaControl_Pause(media_control);
7094 ok(hr == S_OK, "Got hr %#x.\n", hr);
7095 hr = IMediaControl_Run(media_control);
7096 ok(hr == S_OK, "Got hr %#x.\n", hr);
7098 hr = IMediaStreamFilter_EndOfStream(filter);
7099 ok(hr == S_OK, "Got hr %#x.\n", hr);
7101 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7103 hr = IMediaControl_Stop(media_control);
7104 ok(hr == S_OK, "Got hr %#x.\n", hr);
7106 /* EndOfStream count is not reset when Stop() is called on an already stopped filter. */
7107 hr = IMediaStreamFilter_EndOfStream(filter);
7108 ok(hr == S_OK, "Got hr %#x.\n", hr);
7110 hr = IMediaStreamFilter_Stop(filter);
7111 ok(hr == S_OK, "Got hr %#x.\n", hr);
7113 hr = IMediaStreamFilter_EndOfStream(filter);
7114 ok(hr == S_OK, "Got hr %#x.\n", hr);
7116 graph.got_notify = 0;
7118 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
7119 ok(hr == S_OK, "Got hr %#x.\n", hr);
7121 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7123 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
7124 ok(hr == S_OK, "Got hr %#x.\n", hr);
7126 /* Flush with cancel_eos=TRUE decrements EOS count. */
7127 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
7128 ok(hr == S_OK, "Got hr %#x.\n", hr);
7130 graph.got_notify = 0;
7132 hr = IMediaStreamFilter_EndOfStream(filter);
7133 ok(hr == S_OK, "Got hr %#x.\n", hr);
7135 hr = IMediaStreamFilter_Flush(filter, TRUE);
7137 hr = IMediaStreamFilter_EndOfStream(filter);
7138 ok(hr == S_OK, "Got hr %#x.\n", hr);
7140 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7142 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
7143 ok(hr == S_OK, "Got hr %#x.\n", hr);
7145 /* Flush followed by EndOfStream causes another EC_COMPLETE to be sent. */
7146 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
7147 ok(hr == S_OK, "Got hr %#x.\n", hr);
7149 graph.got_notify = 0;
7151 hr = IMediaStreamFilter_EndOfStream(filter);
7152 ok(hr == S_OK, "Got hr %#x.\n", hr);
7153 hr = IMediaStreamFilter_EndOfStream(filter);
7154 ok(hr == S_OK, "Got hr %#x.\n", hr);
7156 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7158 hr = IMediaStreamFilter_Flush(filter, TRUE);
7159 ok(hr == S_OK, "Got hr %#x.\n", hr);
7161 hr = IMediaStreamFilter_EndOfStream(filter);
7162 ok(hr == S_OK, "Got hr %#x.\n", hr);
7164 ok(graph.got_notify == 2, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7166 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
7167 ok(hr == S_OK, "Got hr %#x.\n", hr);
7169 /* Flush decrements EOS count event when it is 0. */
7170 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
7171 ok(hr == S_OK, "Got hr %#x.\n", hr);
7173 graph.got_notify = 0;
7175 hr = IMediaStreamFilter_Flush(filter, TRUE);
7176 ok(hr == S_OK, "Got hr %#x.\n", hr);
7178 hr = IMediaStreamFilter_EndOfStream(filter);
7179 ok(hr == S_OK, "Got hr %#x.\n", hr);
7180 hr = IMediaStreamFilter_EndOfStream(filter);
7181 ok(hr == S_OK, "Got hr %#x.\n", hr);
7183 ok(graph.got_notify == 0, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7185 hr = IMediaStreamFilter_EndOfStream(filter);
7186 ok(hr == S_OK, "Got hr %#x.\n", hr);
7188 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7190 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
7191 ok(hr == S_OK, "Got hr %#x.\n", hr);
7193 /* Flush with cancel_eos=FALSE does not decrement EOS count. */
7194 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
7195 ok(hr == S_OK, "Got hr %#x.\n", hr);
7197 graph.got_notify = 0;
7199 hr = IMediaStreamFilter_EndOfStream(filter);
7200 ok(hr == S_OK, "Got hr %#x.\n", hr);
7202 hr = IMediaStreamFilter_Flush(filter, FALSE);
7204 hr = IMediaStreamFilter_EndOfStream(filter);
7205 ok(hr == S_OK, "Got hr %#x.\n", hr);
7207 ok(graph.got_notify == 1, "Got %d calls to IMediaEventSink::Notify().\n", graph.got_notify);
7209 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
7210 ok(hr == S_OK, "Got hr %#x.\n", hr);
7212 ref = IAMMultiMediaStream_Release(mmstream);
7213 ok(!ref, "Got outstanding refcount %d.\n", ref);
7214 IMediaControl_Release(media_control);
7215 graph_destroy(&graph);
7216 ref = IMediaStreamFilter_Release(filter);
7217 ok(!ref, "Got outstanding refcount %d.\n", ref);
7218 IPin_Release(pin1);
7219 ref = IMediaStream_Release(stream1);
7220 ok(!ref, "Got outstanding refcount %d.\n", ref);
7221 IPin_Release(pin2);
7222 ref = IMediaStream_Release(stream2);
7223 ok(!ref, "Got outstanding refcount %d.\n", ref);
7226 static void test_ddrawstream_getsetdirectdraw(void)
7228 IAMMultiMediaStream *mmstream = create_ammultimediastream();
7229 IDirectDraw *ddraw, *ddraw2, *ddraw3, *ddraw4;
7230 IDirectDrawMediaStream *ddraw_stream;
7231 IDirectDrawStreamSample *sample;
7232 IDirectDraw7 *ddraw7;
7233 IMediaStream *stream;
7234 HRESULT hr;
7235 ULONG ref;
7237 hr = DirectDrawCreate(NULL, &ddraw, NULL);
7238 ok(hr == S_OK, "Got hr %#x.\n", hr);
7239 hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirectDraw7, (void **)&ddraw7);
7240 ok(hr == DD_OK, "Got hr %#x.\n", hr);
7241 hr = IDirectDraw7_SetCooperativeLevel(ddraw7, GetDesktopWindow(), DDSCL_NORMAL);
7242 ok(hr == DD_OK, "Got hr %#x.\n", hr);
7243 EXPECT_REF(ddraw, 1);
7244 EXPECT_REF(ddraw7, 1);
7246 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
7247 ok(hr == S_OK, "Got hr %#x.\n", hr);
7249 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)ddraw7, &MSPID_PrimaryVideo, 0, &stream);
7250 ok(hr == S_OK, "Got hr %#x.\n", hr);
7251 EXPECT_REF(ddraw, 2);
7253 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
7254 ok(hr == S_OK, "Got hr %#x.\n", hr);
7256 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, NULL);
7257 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
7259 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw2);
7260 ok(hr == S_OK, "Got hr %#x.\n", hr);
7261 ok(ddraw2 == ddraw, "Expected ddraw %p, got %p.\n", ddraw, ddraw2);
7262 EXPECT_REF(ddraw, 3);
7264 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw3);
7265 ok(hr == S_OK, "Got hr %#x.\n", hr);
7266 ok(ddraw3 == ddraw2, "Expected ddraw %p, got %p.\n", ddraw2, ddraw3);
7267 EXPECT_REF(ddraw, 4);
7268 IDirectDraw_Release(ddraw3);
7269 EXPECT_REF(ddraw, 3);
7271 /* The current ddraw is released when SetDirectDraw() is called. */
7272 hr = IDirectDrawMediaStream_SetDirectDraw(ddraw_stream, NULL);
7273 ok(hr == S_OK, "Got hr %#x.\n", hr);
7274 EXPECT_REF(ddraw, 2);
7276 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw3);
7277 ok(hr == S_OK, "Got hr %#x.\n", hr);
7278 ok(ddraw3 == NULL, "Expected NULL, got %p.\n", ddraw3);
7280 hr = IDirectDrawMediaStream_SetDirectDraw(ddraw_stream, ddraw2);
7281 ok(hr == S_OK, "Got hr %#x.\n", hr);
7282 EXPECT_REF(ddraw, 3);
7284 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw3);
7285 ok(hr == S_OK, "Got hr %#x.\n", hr);
7286 ok(ddraw3 == ddraw2, "Expected ddraw %p, got %p.\n", ddraw2, ddraw3);
7287 EXPECT_REF(ddraw, 4);
7288 IDirectDraw_Release(ddraw3);
7289 EXPECT_REF(ddraw, 3);
7291 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &sample);
7292 ok(hr == S_OK, "Got hr %#x.\n", hr);
7294 /* SetDirectDraw() doesn't take an extra reference to the ddraw object
7295 * if there are samples extant. */
7296 hr = IDirectDrawMediaStream_SetDirectDraw(ddraw_stream, ddraw2);
7297 ok(hr == S_OK, "Got hr %#x.\n", hr);
7298 EXPECT_REF(ddraw, 3);
7300 hr = DirectDrawCreate(NULL, &ddraw3, NULL);
7301 ok(hr == S_OK, "Got hr %#x.\n", hr);
7302 hr = IDirectDraw_SetCooperativeLevel(ddraw3, GetDesktopWindow(), DDSCL_NORMAL);
7303 ok(hr == DD_OK, "Got hr %#x.\n", hr);
7304 EXPECT_REF(ddraw3, 1);
7306 hr = IDirectDrawMediaStream_SetDirectDraw(ddraw_stream, ddraw3);
7307 ok(hr == MS_E_SAMPLEALLOC, "Got hr %#x.\n", hr);
7309 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw4);
7310 ok(hr == S_OK, "Got hr %#x.\n", hr);
7311 ok(ddraw4 == ddraw2, "Expected ddraw %p, got %p.\n", ddraw2, ddraw4);
7312 EXPECT_REF(ddraw, 4);
7313 IDirectDraw_Release(ddraw4);
7314 EXPECT_REF(ddraw, 3);
7316 ref = IDirectDrawStreamSample_Release(sample);
7317 ok(!ref, "Got outstanding refcount %d.\n", ref);
7319 hr = IDirectDrawMediaStream_SetDirectDraw(ddraw_stream, ddraw3);
7320 ok(hr == S_OK, "Got hr %#x.\n", hr);
7321 EXPECT_REF(ddraw, 2);
7322 EXPECT_REF(ddraw3, 2);
7324 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw4);
7325 ok(hr == S_OK, "Got hr %#x.\n", hr);
7326 ok(ddraw4 == ddraw3, "Expected ddraw %p, got %p.\n", ddraw3, ddraw4);
7327 EXPECT_REF(ddraw3, 3);
7328 IDirectDraw_Release(ddraw4);
7329 EXPECT_REF(ddraw3, 2);
7331 hr = IDirectDrawMediaStream_SetDirectDraw(ddraw_stream, NULL);
7332 ok(hr == S_OK, "Got hr %#x.\n", hr);
7333 EXPECT_REF(ddraw3, 1);
7335 ref = IDirectDraw_Release(ddraw3);
7336 ok(!ref, "Got outstanding refcount %d.\n", ref);
7338 EXPECT_REF(stream, 3);
7339 IDirectDrawMediaStream_Release(ddraw_stream);
7340 EXPECT_REF(stream, 2);
7341 ref = IAMMultiMediaStream_Release(mmstream);
7342 ok(!ref, "Got outstanding refcount %d.\n", ref);
7343 EXPECT_REF(stream, 1);
7344 ref = IMediaStream_Release(stream);
7345 ok(!ref, "Got outstanding refcount %d.\n", ref);
7346 ref = IDirectDraw7_Release(ddraw7);
7347 ok(!ref, "Got outstanding refcount %d.\n", ref);
7348 IDirectDraw_Release(ddraw2);
7349 EXPECT_REF(ddraw, 1);
7350 ref = IDirectDraw_Release(ddraw);
7351 ok(!ref, "Got outstanding refcount %d.\n", ref);
7354 static void test_audiostreamsample_get_media_stream(void)
7356 IAMMultiMediaStream *mmstream = create_ammultimediastream();
7357 IAudioStreamSample *audio_sample;
7358 IAudioMediaStream *audio_stream;
7359 IMediaStream *stream, *stream2;
7360 IAudioData *audio_data;
7361 HRESULT hr;
7362 ULONG ref;
7364 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
7365 ok(hr == S_OK, "Got hr %#x.\n", hr);
7367 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
7368 ok(hr == S_OK, "Got hr %#x.\n", hr);
7370 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
7371 ok(hr == S_OK, "Got hr %#x.\n", hr);
7373 hr = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER, &IID_IAudioData, (void **)&audio_data);
7374 ok(hr == S_OK, "Got hr %#x.\n", hr);
7376 hr = IAudioMediaStream_CreateSample(audio_stream, audio_data, 0, &audio_sample);
7377 ok(hr == S_OK, "Got hr %#x.\n", hr);
7379 /* Crashes on native. */
7380 if (0)
7382 hr = IAudioStreamSample_GetMediaStream(audio_sample, NULL);
7383 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
7386 EXPECT_REF(stream, 4);
7387 hr = IAudioStreamSample_GetMediaStream(audio_sample, &stream2);
7388 ok(hr == S_OK, "Got hr %#x.\n", hr);
7389 ok(stream2 == stream, "Expected stream %p, got %p.\n", stream, stream2);
7390 EXPECT_REF(stream, 5);
7392 IMediaStream_Release(stream2);
7394 IAudioMediaStream_Release(audio_stream);
7395 ref = IAudioStreamSample_Release(audio_sample);
7396 ok(!ref, "Got outstanding refcount %d.\n", ref);
7397 ref = IAudioData_Release(audio_data);
7398 ok(!ref, "Got outstanding refcount %d.\n", ref);
7399 ref = IAMMultiMediaStream_Release(mmstream);
7400 ok(!ref, "Got outstanding refcount %d.\n", ref);
7401 ref = IMediaStream_Release(stream);
7402 ok(!ref, "Got outstanding refcount %d.\n", ref);
7405 static void test_audiostreamsample_get_audio_data(void)
7407 IAMMultiMediaStream *mmstream = create_ammultimediastream();
7408 IAudioData *audio_data, *audio_data2;
7409 IAudioStreamSample *audio_sample;
7410 IAudioMediaStream *audio_stream;
7411 IMediaStream *stream;
7412 HRESULT hr;
7413 ULONG ref;
7415 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
7416 ok(hr == S_OK, "Got hr %#x.\n", hr);
7418 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryAudio, 0, &stream);
7419 ok(hr == S_OK, "Got hr %#x.\n", hr);
7421 hr = IMediaStream_QueryInterface(stream, &IID_IAudioMediaStream, (void **)&audio_stream);
7422 ok(hr == S_OK, "Got hr %#x.\n", hr);
7424 hr = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER, &IID_IAudioData, (void **)&audio_data);
7425 ok(hr == S_OK, "Got hr %#x.\n", hr);
7427 hr = IAudioMediaStream_CreateSample(audio_stream, audio_data, 0, &audio_sample);
7428 ok(hr == S_OK, "Got hr %#x.\n", hr);
7430 hr = IAudioStreamSample_GetAudioData(audio_sample, NULL);
7431 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
7433 EXPECT_REF(audio_data, 2);
7434 hr = IAudioStreamSample_GetAudioData(audio_sample, &audio_data2);
7435 ok(hr == S_OK, "Got hr %#x.\n", hr);
7436 ok(audio_data2 == audio_data, "Expected audio data %p, got %p.\n", audio_data, audio_data2);
7437 EXPECT_REF(audio_data, 3);
7439 IAudioData_Release(audio_data2);
7441 IAudioMediaStream_Release(audio_stream);
7442 ref = IAudioStreamSample_Release(audio_sample);
7443 ok(!ref, "Got outstanding refcount %d.\n", ref);
7444 ref = IAudioData_Release(audio_data);
7445 ok(!ref, "Got outstanding refcount %d.\n", ref);
7446 ref = IAMMultiMediaStream_Release(mmstream);
7447 ok(!ref, "Got outstanding refcount %d.\n", ref);
7448 ref = IMediaStream_Release(stream);
7449 ok(!ref, "Got outstanding refcount %d.\n", ref);
7452 #define get_ddrawstream_create_sample_desc(a,b,c,d) get_ddrawstream_create_sample_desc_(__LINE__,a,b,c,d)
7453 static void get_ddrawstream_create_sample_desc_(int line, const DDSURFACEDESC *format1,
7454 const DDSURFACEDESC *format2, const AM_MEDIA_TYPE *mt, DDSURFACEDESC *desc)
7456 IAMMultiMediaStream *mmstream = create_ammultimediastream();
7457 IDirectDrawMediaStream *ddraw_stream;
7458 IDirectDrawStreamSample *sample;
7459 IDirectDrawSurface *surface;
7460 struct testfilter source;
7461 IGraphBuilder *graph;
7462 IMediaStream *stream;
7463 HRESULT hr;
7464 ULONG ref;
7465 IPin *pin;
7467 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
7468 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
7469 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
7470 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
7471 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
7472 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
7473 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
7474 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
7475 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
7476 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
7478 testfilter_init(&source);
7480 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
7481 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
7483 if (format1)
7485 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, format1, NULL);
7486 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
7488 if (format2)
7490 hr = IDirectDrawMediaStream_SetFormat(ddraw_stream, format2, NULL);
7491 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
7493 if (mt)
7495 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, mt);
7496 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
7498 hr = IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
7499 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
7500 hr = IGraphBuilder_Disconnect(graph, pin);
7501 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
7504 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &sample);
7505 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
7507 hr = IDirectDrawStreamSample_GetSurface(sample, &surface, NULL);
7508 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
7509 ok_(__FILE__, line)(!!surface, "Expected non-NULL sufrace.\n");
7511 desc->dwSize = sizeof(*desc);
7512 hr = IDirectDrawSurface_GetSurfaceDesc(surface, desc);
7513 ok_(__FILE__, line)(hr == S_OK, "Got hr %#x.\n", hr);
7515 ref = IDirectDrawStreamSample_Release(sample);
7516 ok_(__FILE__, line)(!ref, "Got outstanding refcount %d.\n", ref);
7517 ref = IDirectDrawSurface_Release(surface);
7518 ok_(__FILE__, line)(!ref, "Got outstanding refcount %d.\n", ref);
7519 ref = IAMMultiMediaStream_Release(mmstream);
7520 ok_(__FILE__, line)(!ref, "Got outstanding refcount %d.\n", ref);
7521 ref = IGraphBuilder_Release(graph);
7522 ok_(__FILE__, line)(!ref, "Got outstanding refcount %d.\n", ref);
7523 IPin_Release(pin);
7524 IDirectDrawMediaStream_Release(ddraw_stream);
7525 ref = IMediaStream_Release(stream);
7526 ok_(__FILE__, line)(!ref, "Got outstanding refcount %d.\n", ref);
7529 static void test_ddrawstream_create_sample(void)
7531 IAMMultiMediaStream *mmstream = create_ammultimediastream();
7532 DDSURFACEDESC desc2 = { sizeof(desc2) };
7533 IDirectDrawSurface *surface, *surface2;
7534 DDSURFACEDESC desc = { sizeof(desc) };
7535 IDirectDrawMediaStream *ddraw_stream;
7536 IDirectDrawStreamSample *sample;
7537 DDSURFACEDESC format1;
7538 DDSURFACEDESC format2;
7539 IMediaStream *stream;
7540 IDirectDraw *ddraw;
7541 HRESULT hr;
7542 RECT rect;
7543 ULONG ref;
7545 hr = DirectDrawCreate(NULL, &ddraw, NULL);
7546 ok(hr == S_OK, "Got hr %#x.\n", hr);
7548 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
7549 ok(hr == S_OK, "Got hr %#x.\n", hr);
7551 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
7552 ok(hr == S_OK, "Got hr %#x.\n", hr);
7554 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)ddraw, &MSPID_PrimaryVideo, 0, &stream);
7555 ok(hr == S_OK, "Got hr %#x.\n", hr);
7557 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
7558 ok(hr == S_OK, "Got hr %#x.\n", hr);
7560 /* Crashes on native. */
7561 if (0)
7563 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, NULL);
7564 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
7567 SetRectEmpty(&rect);
7568 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, &rect, 0, &sample);
7569 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
7571 EXPECT_REF(mmstream, 1);
7572 EXPECT_REF(stream, 3);
7573 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &sample);
7574 ok(hr == S_OK, "Got hr %#x.\n", hr);
7575 EXPECT_REF(mmstream, 2);
7576 EXPECT_REF(stream, 4);
7578 hr = IDirectDrawStreamSample_GetSurface(sample, NULL, NULL);
7579 ok(hr == S_OK, "Got hr %#x.\n", hr);
7581 hr = IDirectDrawStreamSample_GetSurface(sample, NULL, &rect);
7582 ok(hr == S_OK, "Got hr %#x.\n", hr);
7584 hr = IDirectDrawStreamSample_GetSurface(sample, &surface, NULL);
7585 ok(hr == S_OK, "Got hr %#x.\n", hr);
7586 ok(surface != NULL, "Expected non-NULL surface.\n");
7587 IDirectDrawSurface_Release(surface);
7589 surface = NULL;
7590 hr = IDirectDrawStreamSample_GetSurface(sample, &surface, &rect);
7591 ok(hr == S_OK, "Got hr %#x.\n", hr);
7592 ok(surface != NULL, "Expected non-NULL surface.\n");
7594 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc);
7595 ok(hr == S_OK, "Got hr %#x.\n", hr);
7596 ok(desc.dwWidth == 100, "Expected width 100, got %d.\n", desc.dwWidth);
7597 ok(desc.dwHeight == 100, "Expected height 100, got %d.\n", desc.dwHeight);
7598 ok(desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Expected format flags DDPF_RGB, got %#x.\n", desc.ddpfPixelFormat.dwFlags);
7599 ok(desc.ddpfPixelFormat.u1.dwRGBBitCount, "Expected non-zero RGB bit count.\n");
7600 IDirectDrawSurface_Release(surface);
7601 IDirectDrawStreamSample_Release(sample);
7602 EXPECT_REF(stream, 3);
7604 memset(&desc, 0, sizeof(desc));
7605 desc.dwSize = sizeof(desc);
7606 desc.dwFlags = DDSD_CAPS;
7607 desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
7608 hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
7609 ok(hr == S_OK, "Got hr %#x.\n", hr);
7611 EXPECT_REF(surface, 1);
7612 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, NULL, 0, &sample);
7613 ok(hr == S_OK, "Got hr %#x.\n", hr);
7614 EXPECT_REF(surface, 2);
7616 surface2 = NULL;
7617 SetRectEmpty(&rect);
7618 hr = IDirectDrawStreamSample_GetSurface(sample, &surface2, &rect);
7619 ok(hr == S_OK, "Got hr %#x.\n", hr);
7620 ok(surface2 == surface, "Expected surface %p, got %p.\n", surface, surface2);
7621 ok(rect.right > 0 && rect.bottom > 0, "Got rect %d, %d.\n", rect.right, rect.bottom);
7622 EXPECT_REF(surface, 3);
7623 IDirectDrawSurface_Release(surface2);
7624 EXPECT_REF(surface, 2);
7625 IDirectDrawStreamSample_Release(sample);
7626 EXPECT_REF(surface, 1);
7628 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, &rect, 0, &sample);
7629 ok(hr == S_OK, "Got hr %#x.\n", hr);
7631 ref = IDirectDrawStreamSample_Release(sample);
7632 ok(!ref, "Got outstanding refcount %d.\n", ref);
7633 ref = IDirectDrawSurface_Release(surface);
7634 ok(!ref, "Got outstanding refcount %d.\n", ref);
7636 memset(&desc, 0, sizeof(desc));
7637 desc.dwSize = sizeof(desc);
7638 desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
7639 desc.dwWidth = 444;
7640 desc.dwHeight = 400;
7641 desc.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
7642 desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
7643 desc.ddpfPixelFormat.u1.dwRGBBitCount = 32;
7644 desc.ddpfPixelFormat.u2.dwRBitMask = 0xff0000;
7645 desc.ddpfPixelFormat.u3.dwGBitMask = 0x00ff00;
7646 desc.ddpfPixelFormat.u4.dwBBitMask = 0x0000ff;
7647 desc.ddpfPixelFormat.u5.dwRGBAlphaBitMask = 0xff000000;
7648 desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7649 hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
7650 ok(hr == S_OK, "Got hr %#x.\n", hr);
7652 SetRect(&rect, 111, 100, 333, 300);
7654 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, &rect, 0, &sample);
7655 ok(hr == S_OK, "Got hr %#x.\n", hr);
7656 ref = IDirectDrawStreamSample_Release(sample);
7657 ok(!ref, "Got outstanding refcount %d.\n", ref);
7659 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &sample);
7660 ok(hr == S_OK, "Got hr %#x.\n", hr);
7661 surface2 = NULL;
7662 hr = IDirectDrawStreamSample_GetSurface(sample, &surface2, &rect);
7663 ok(hr == S_OK, "Got hr %#x.\n", hr);
7665 hr = IDirectDrawSurface_GetSurfaceDesc(surface, &desc);
7666 ok(hr == S_OK, "Got hr %#x.\n", hr);
7667 hr = IDirectDrawSurface_GetSurfaceDesc(surface2, &desc2);
7668 ok(hr == S_OK, "Got hr %#x.\n", hr);
7669 ok(desc2.dwWidth == 222, "Got width %u.\n", desc2.dwWidth);
7670 ok(desc2.dwHeight == 200, "Got height %u.\n", desc2.dwHeight);
7671 ok(memcmp(&desc2.ddpfPixelFormat, &desc.ddpfPixelFormat, sizeof(DDPIXELFORMAT)) == 0,
7672 "Pixel format didn't match.\n");
7674 ref = IDirectDrawStreamSample_Release(sample);
7675 ok(!ref, "Got outstanding refcount %d.\n", ref);
7676 ref = IDirectDrawSurface_Release(surface);
7677 ok(!ref, "Got outstanding refcount %d.\n", ref);
7678 ref = IDirectDrawSurface_Release(surface2);
7679 ok(!ref, "Got outstanding refcount %d.\n", ref);
7681 memset(&desc, 0, sizeof(desc));
7682 desc.dwSize = sizeof(desc);
7683 desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
7684 desc.dwWidth = 444;
7685 desc.dwHeight = 400;
7686 desc.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
7687 desc.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED4;
7688 desc.ddpfPixelFormat.u1.dwRGBBitCount = 4;
7689 desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7690 hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
7691 ok(hr == S_OK, "Got hr %#x.\n", hr);
7693 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, NULL, 0, &sample);
7694 ok(hr == DDERR_INVALIDSURFACETYPE, "Got hr %#x.\n", hr);
7696 IDirectDrawMediaStream_Release(ddraw_stream);
7697 ref = IDirectDrawSurface_Release(surface);
7698 ok(!ref, "Got outstanding refcount %d.\n", ref);
7699 ref = IAMMultiMediaStream_Release(mmstream);
7700 ok(!ref, "Got outstanding refcount %d.\n", ref);
7701 ref = IMediaStream_Release(stream);
7702 ok(!ref, "Got outstanding refcount %d.\n", ref);
7703 ref = IDirectDraw_Release(ddraw);
7704 ok(!ref, "Got outstanding refcount %d.\n", ref);
7706 format1 = rgb8_format;
7707 format1.dwFlags = 0;
7708 format1.dwWidth = 333;
7709 format1.dwHeight = 444;
7710 get_ddrawstream_create_sample_desc(&format1, NULL, NULL, &desc);
7711 ok(desc.dwWidth == 100, "Got width %u.\n", desc.dwWidth);
7712 ok(desc.dwHeight == 100, "Got height %u.\n", desc.dwHeight);
7713 ok(desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Got flags %#x.\n", desc.ddpfPixelFormat.dwFlags);
7714 ok(desc.ddpfPixelFormat.u1.dwRGBBitCount == 32, "Got rgb bit count %u.\n", desc.ddpfPixelFormat.u1.dwRGBBitCount);
7715 ok(desc.ddpfPixelFormat.u2.dwRBitMask == 0xff0000, "Got r bit mask %#x.\n", desc.ddpfPixelFormat.u2.dwRBitMask);
7716 ok(desc.ddpfPixelFormat.u3.dwGBitMask == 0x00ff00, "Got g bit mask %#x.\n", desc.ddpfPixelFormat.u3.dwGBitMask);
7717 ok(desc.ddpfPixelFormat.u4.dwBBitMask == 0x0000ff, "Got b bit mask %#x.\n", desc.ddpfPixelFormat.u4.dwBBitMask);
7719 format1 = rgb8_format;
7720 format1.dwFlags |= DDSD_WIDTH;
7721 format1.dwWidth = 333;
7722 format1.dwHeight = 444;
7723 format2 = rgb8_format;
7724 format2.dwFlags = 0;
7725 get_ddrawstream_create_sample_desc(&format1, &format2, NULL, &desc);
7726 ok(desc.dwWidth == 333, "Got width %u.\n", desc.dwWidth);
7727 ok(desc.dwHeight == 444, "Got height %u.\n", desc.dwHeight);
7729 format1 = rgb8_format;
7730 format1.dwFlags |= DDSD_HEIGHT;
7731 format1.dwWidth = 333;
7732 format1.dwHeight = 444;
7733 format2 = rgb8_format;
7734 format2.dwFlags = 0;
7735 get_ddrawstream_create_sample_desc(&format1, &format2, NULL, &desc);
7736 ok(desc.dwWidth == 333, "Got width %u.\n", desc.dwWidth);
7737 ok(desc.dwHeight == 444, "Got height %u.\n", desc.dwHeight);
7739 get_ddrawstream_create_sample_desc(NULL, NULL, &rgb8_mt, &desc);
7740 ok(desc.dwWidth == 333, "Got width %u.\n", desc.dwWidth);
7741 ok(desc.dwHeight == 444, "Got height %u.\n", desc.dwHeight);
7742 ok(desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Got flags %#x.\n", desc.ddpfPixelFormat.dwFlags);
7743 ok(desc.ddpfPixelFormat.u1.dwRGBBitCount == 32, "Got rgb bit count %u.\n", desc.ddpfPixelFormat.u1.dwRGBBitCount);
7744 ok(desc.ddpfPixelFormat.u2.dwRBitMask == 0xff0000, "Got r bit mask %#x.\n", desc.ddpfPixelFormat.u2.dwRBitMask);
7745 ok(desc.ddpfPixelFormat.u3.dwGBitMask == 0x00ff00, "Got g bit mask %#x.\n", desc.ddpfPixelFormat.u3.dwGBitMask);
7746 ok(desc.ddpfPixelFormat.u4.dwBBitMask == 0x0000ff, "Got b bit mask %#x.\n", desc.ddpfPixelFormat.u4.dwBBitMask);
7748 get_ddrawstream_create_sample_desc(&rgb565_format, NULL, NULL, &desc);
7749 ok(desc.dwWidth == 100, "Got width %u.\n", desc.dwWidth);
7750 ok(desc.dwHeight == 100, "Got height %u.\n", desc.dwHeight);
7751 ok(desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Got flags %#x.\n", desc.ddpfPixelFormat.dwFlags);
7752 ok(desc.ddpfPixelFormat.u1.dwRGBBitCount == 16, "Got rgb bit count %u.\n", desc.ddpfPixelFormat.u1.dwRGBBitCount);
7753 ok(desc.ddpfPixelFormat.u2.dwRBitMask == 0xf800, "Got r bit mask %#x.\n", desc.ddpfPixelFormat.u2.dwRBitMask);
7754 ok(desc.ddpfPixelFormat.u3.dwGBitMask == 0x07e0, "Got g bit mask %#x.\n", desc.ddpfPixelFormat.u3.dwGBitMask);
7755 ok(desc.ddpfPixelFormat.u4.dwBBitMask == 0x001f, "Got b bit mask %#x.\n", desc.ddpfPixelFormat.u4.dwBBitMask);
7757 get_ddrawstream_create_sample_desc(&argb32_format, NULL, NULL, &desc);
7758 ok(desc.dwWidth == 100, "Got width %u.\n", desc.dwWidth);
7759 ok(desc.dwHeight == 100, "Got height %u.\n", desc.dwHeight);
7760 ok(desc.ddpfPixelFormat.dwFlags == (DDPF_RGB | DDPF_ALPHAPIXELS), "Got flags %#x.\n", desc.ddpfPixelFormat.dwFlags);
7761 ok(desc.ddpfPixelFormat.u1.dwRGBBitCount == 32, "Got rgb bit count %u.\n", desc.ddpfPixelFormat.u1.dwRGBBitCount);
7762 ok(desc.ddpfPixelFormat.u2.dwRBitMask == 0xff0000, "Got r bit mask %#x.\n", desc.ddpfPixelFormat.u2.dwRBitMask);
7763 ok(desc.ddpfPixelFormat.u3.dwGBitMask == 0x00ff00, "Got g bit mask %#x.\n", desc.ddpfPixelFormat.u3.dwGBitMask);
7764 ok(desc.ddpfPixelFormat.u4.dwBBitMask == 0x0000ff, "Got b bit mask %#x.\n", desc.ddpfPixelFormat.u4.dwBBitMask);
7765 ok(desc.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0xff000000,
7766 "Got alpha bit mask %#x.\n", desc.ddpfPixelFormat.u4.dwBBitMask);
7768 format1 = rgb32_format;
7769 format1.dwFlags |= DDSD_CAPS;
7770 format1.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
7771 get_ddrawstream_create_sample_desc(&format1, NULL, NULL, &desc);
7772 ok(desc.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN, "Expected set DDSCAPS_OFFSCREENPLAIN.\n");
7773 ok(desc.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY, "Expected set DDSCAPS_SYSTEMMEMORY.\n");
7774 ok(!(desc.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY), "Expected unset DDSCAPS_VIDEOMEMORY.\n");
7775 ok(desc.dwWidth == 100, "Got width %u.\n", desc.dwWidth);
7776 ok(desc.dwHeight == 100, "Got height %u.\n", desc.dwHeight);
7777 ok(desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Got flags %#x.\n", desc.ddpfPixelFormat.dwFlags);
7778 ok(desc.ddpfPixelFormat.u1.dwRGBBitCount == 32, "Got rgb bit count %u.\n", desc.ddpfPixelFormat.u1.dwRGBBitCount);
7779 ok(desc.ddpfPixelFormat.u2.dwRBitMask == 0xff0000, "Got r bit mask %#x.\n", desc.ddpfPixelFormat.u2.dwRBitMask);
7780 ok(desc.ddpfPixelFormat.u3.dwGBitMask == 0x00ff00, "Got g bit mask %#x.\n", desc.ddpfPixelFormat.u3.dwGBitMask);
7781 ok(desc.ddpfPixelFormat.u4.dwBBitMask == 0x0000ff, "Got b bit mask %#x.\n", desc.ddpfPixelFormat.u4.dwBBitMask);
7783 format1 = rgb32_format;
7784 format1.dwFlags |= DDSD_CKSRCBLT;
7785 format1.ddckCKSrcBlt.dwColorSpaceLowValue = 0xff00ff;
7786 format1.ddckCKSrcBlt.dwColorSpaceHighValue = 0xff00ff;
7787 get_ddrawstream_create_sample_desc(&format1, NULL, NULL, &desc);
7788 ok(!(desc.dwFlags & DDSD_CKSRCBLT), "Expected unset DDSD_CKSRCBLT.\n");
7789 ok(desc.dwWidth == 100, "Got width %u.\n", desc.dwWidth);
7790 ok(desc.dwHeight == 100, "Got height %u.\n", desc.dwHeight);
7791 ok(desc.ddpfPixelFormat.dwFlags == DDPF_RGB, "Got flags %#x.\n", desc.ddpfPixelFormat.dwFlags);
7792 ok(desc.ddpfPixelFormat.u1.dwRGBBitCount == 32, "Got rgb bit count %u.\n", desc.ddpfPixelFormat.u1.dwRGBBitCount);
7793 ok(desc.ddpfPixelFormat.u2.dwRBitMask == 0xff0000, "Got r bit mask %#x.\n", desc.ddpfPixelFormat.u2.dwRBitMask);
7794 ok(desc.ddpfPixelFormat.u3.dwGBitMask == 0x00ff00, "Got g bit mask %#x.\n", desc.ddpfPixelFormat.u3.dwGBitMask);
7795 ok(desc.ddpfPixelFormat.u4.dwBBitMask == 0x0000ff, "Got b bit mask %#x.\n", desc.ddpfPixelFormat.u4.dwBBitMask);
7796 ok(desc.ddckCKSrcBlt.dwColorSpaceLowValue == 0, "Got color key low value %#x.\n",
7797 desc.ddckCKSrcBlt.dwColorSpaceLowValue);
7798 ok(desc.ddckCKSrcBlt.dwColorSpaceHighValue == 0, "Got color key high value %#x.\n",
7799 desc.ddckCKSrcBlt.dwColorSpaceHighValue);
7802 static void test_ddrawstreamsample_get_media_stream(void)
7804 IAMMultiMediaStream *mmstream = create_ammultimediastream();
7805 IDirectDrawMediaStream *ddraw_stream;
7806 IDirectDrawStreamSample *sample;
7807 IMediaStream *stream, *stream2;
7808 IDirectDraw *ddraw;
7809 HRESULT hr;
7810 ULONG ref;
7812 hr = DirectDrawCreate(NULL, &ddraw, NULL);
7813 ok(hr == S_OK, "Got hr %#x.\n", hr);
7815 hr = IDirectDraw_SetCooperativeLevel(ddraw, NULL, DDSCL_NORMAL);
7816 ok(hr == S_OK, "Got hr %#x.\n", hr);
7818 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
7819 ok(hr == S_OK, "Got hr %#x.\n", hr);
7821 hr = IAMMultiMediaStream_AddMediaStream(mmstream, (IUnknown *)ddraw, &MSPID_PrimaryVideo, 0, &stream);
7822 ok(hr == S_OK, "Got hr %#x.\n", hr);
7824 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
7825 ok(hr == S_OK, "Got hr %#x.\n", hr);
7827 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &sample);
7828 ok(hr == S_OK, "Got hr %#x.\n", hr);
7830 /* Crashes on native. */
7831 if (0)
7833 hr = IDirectDrawStreamSample_GetMediaStream(sample, NULL);
7834 ok(hr == E_POINTER, "Got hr %#x.\n", hr);
7837 EXPECT_REF(stream, 4);
7838 hr = IDirectDrawStreamSample_GetMediaStream(sample, &stream2);
7839 ok(hr == S_OK, "Got hr %#x.\n", hr);
7840 ok(stream2 == stream, "Expected stream %p, got %p.\n", stream, stream2);
7841 EXPECT_REF(stream, 5);
7842 IMediaStream_Release(stream2);
7843 EXPECT_REF(stream, 4);
7845 IDirectDrawMediaStream_Release(ddraw_stream);
7846 ref = IDirectDrawStreamSample_Release(sample);
7847 ok(!ref, "Got outstanding refcount %d.\n", ref);
7848 ref = IAMMultiMediaStream_Release(mmstream);
7849 ok(!ref, "Got outstanding refcount %d.\n", ref);
7850 ref = IMediaStream_Release(stream);
7851 ok(!ref, "Got outstanding refcount %d.\n", ref);
7852 ref = IDirectDraw_Release(ddraw);
7853 ok(!ref, "Got outstanding refcount %d.\n", ref);
7856 static void test_ddrawstreamsample_update(void)
7858 static const BYTE initial_data[] =
7860 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
7862 static const BYTE test_data[] =
7864 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
7865 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
7867 IAMMultiMediaStream *mmstream = create_ammultimediastream();
7868 IDirectDrawStreamSample *stream_sample;
7869 struct advise_time_cookie cookie = {0};
7870 IDirectDrawMediaStream *ddraw_stream;
7871 IMediaControl *media_control;
7872 IDirectDrawSurface *surface;
7873 IMemInputPin *mem_input_pin;
7874 IMediaSample *media_sample;
7875 IMediaFilter *media_filter;
7876 REFERENCE_TIME start_time;
7877 REFERENCE_TIME end_time;
7878 struct testfilter source;
7879 struct testclock clock;
7880 IGraphBuilder *graph;
7881 IMediaStream *stream;
7882 VIDEOINFO video_info;
7883 DDSURFACEDESC desc;
7884 IDirectDraw *ddraw;
7885 AM_MEDIA_TYPE mt;
7886 HANDLE thread;
7887 HANDLE event;
7888 HRESULT hr;
7889 ULONG ref;
7890 IPin *pin;
7891 RECT rect;
7892 int i;
7894 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
7895 ok(hr == S_OK, "Got hr %#x.\n", hr);
7896 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
7897 ok(hr == S_OK, "Got hr %#x.\n", hr);
7898 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
7899 ok(hr == S_OK, "Got hr %#x.\n", hr);
7900 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
7901 ok(hr == S_OK, "Got hr %#x.\n", hr);
7902 hr = IMediaStream_QueryInterface(stream, &IID_IMemInputPin, (void **)&mem_input_pin);
7903 ok(hr == S_OK, "Got hr %#x.\n", hr);
7904 hr = IDirectDrawMediaStream_GetDirectDraw(ddraw_stream, &ddraw);
7905 ok(hr == S_OK, "Got hr %#x.\n", hr);
7906 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
7907 ok(hr == S_OK, "Got hr %#x.\n", hr);
7908 ok(graph != NULL, "Expected non-NULL graph.\n");
7909 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void **)&media_control);
7910 ok(hr == S_OK, "Got hr %#x.\n", hr);
7911 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void **)&media_filter);
7912 ok(hr == S_OK, "Got hr %#x.\n", hr);
7913 testfilter_init(&source);
7914 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
7915 ok(hr == S_OK, "Got hr %#x.\n", hr);
7916 testclock_init(&clock);
7917 event = CreateEventW(NULL, FALSE, FALSE, NULL);
7918 ok(event != NULL, "Expected non-NULL event.");
7919 cookie.advise_time_called_event = CreateEventW(NULL, FALSE, FALSE, NULL);
7920 ok(cookie.advise_time_called_event != NULL, "Expected non-NULL event.");
7922 hr = IMediaFilter_SetSyncSource(media_filter, NULL);
7923 ok(hr == S_OK, "Got hr %#x.\n", hr);
7925 desc = rgb24_format;
7926 desc.dwFlags |= DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
7927 desc.dwWidth = 4;
7928 desc.dwHeight = 5;
7929 desc.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN;
7930 hr = IDirectDraw_CreateSurface(ddraw, &desc, &surface, NULL);
7931 ok(hr == S_OK, "Got hr %#x.\n", hr);
7932 /* Make the rect width equal to the surface width, as the native
7933 * implementation incorrectly handles rects that are not full-width
7934 * when the ddraw stream's custom allocator is not used. */
7935 SetRect(&rect, 0, 1, 4, 3);
7936 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, surface, &rect, 0, &stream_sample);
7937 ok(hr == S_OK, "Got hr %#x.\n", hr);
7939 hr = IDirectDrawStreamSample_Update(stream_sample, 0, event, apc_func, 0);
7940 ok(hr == E_INVALIDARG, "Got hr %#x.\n", hr);
7942 hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
7943 ok(hr == MS_E_NOTRUNNING, "Got hr %#x.\n", hr);
7945 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
7946 ok(hr == S_OK, "Got hr %#x.\n", hr);
7948 hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
7949 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
7951 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
7952 ok(hr == S_OK, "Got hr %#x.\n", hr);
7953 video_info = rgb24_video_info;
7954 video_info.bmiHeader.biWidth = 4;
7955 video_info.bmiHeader.biHeight = -2;
7956 mt = rgb24_mt;
7957 mt.pbFormat = (BYTE *)&video_info;
7958 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
7959 ok(hr == S_OK, "Got hr %#x.\n", hr);
7961 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
7962 ok(hr == S_OK, "Got hr %#x.\n", hr);
7964 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
7965 ok(hr == S_OK, "Got hr %#x.\n", hr);
7966 for (i = 0; i < 5; ++i)
7967 memcpy((BYTE *)desc.lpSurface + i * desc.u1.lPitch, initial_data, 12);
7968 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
7969 ok(hr == S_OK, "Got hr %#x.\n", hr);
7971 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
7973 ammediastream_mem_input_pin = mem_input_pin;
7974 ammediastream_media_sample = media_sample;
7975 ammediastream_sleep_time = 0;
7976 ammediastream_expected_hr = S_OK;
7977 thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
7979 Sleep(100);
7980 hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
7981 ok(hr == S_OK, "Got hr %#x.\n", hr);
7982 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
7983 ok(hr == S_OK, "Got hr %#x.\n", hr);
7984 ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
7985 ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.u1.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n");
7986 ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.u1.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n");
7987 ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
7988 ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
7989 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
7990 ok(hr == S_OK, "Got hr %#x.\n", hr);
7992 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
7993 CloseHandle(thread);
7995 ref = IMediaSample_Release(media_sample);
7996 ok(!ref, "Got outstanding refcount %d.\n", ref);
7998 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
7999 ok(hr == S_OK, "Got hr %#x.\n", hr);
8000 IGraphBuilder_Disconnect(graph, pin);
8001 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
8002 video_info = rgb24_video_info;
8003 video_info.bmiHeader.biWidth = 4;
8004 video_info.bmiHeader.biHeight = 2;
8005 mt = rgb24_mt;
8006 mt.pbFormat = (BYTE *)&video_info;
8007 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
8008 ok(hr == S_OK, "Got hr %#x.\n", hr);
8009 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8010 ok(hr == S_OK, "Got hr %#x.\n", hr);
8012 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8013 ok(hr == S_OK, "Got hr %#x.\n", hr);
8014 for (i = 0; i < 5; ++i)
8015 memcpy((BYTE *)desc.lpSurface + i * desc.u1.lPitch, initial_data, 12);
8016 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8017 ok(hr == S_OK, "Got hr %#x.\n", hr);
8019 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8021 ammediastream_mem_input_pin = mem_input_pin;
8022 ammediastream_media_sample = media_sample;
8023 ammediastream_sleep_time = 0;
8024 ammediastream_expected_hr = S_OK;
8025 thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
8027 Sleep(100);
8028 hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
8029 ok(hr == S_OK, "Got hr %#x.\n", hr);
8030 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8031 ok(hr == S_OK, "Got hr %#x.\n", hr);
8032 ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8033 ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.u1.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n");
8034 ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.u1.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n");
8035 ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8036 ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8037 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8038 ok(hr == S_OK, "Got hr %#x.\n", hr);
8040 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8041 CloseHandle(thread);
8043 ref = IMediaSample_Release(media_sample);
8044 ok(!ref, "Got outstanding refcount %d.\n", ref);
8046 hr = IPin_EndOfStream(pin);
8047 ok(hr == S_OK, "Got hr %#x.\n", hr);
8049 hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
8050 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
8052 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8053 ok(hr == S_OK, "Got hr %#x.\n", hr);
8054 hr = IMediaControl_Pause(media_control);
8055 ok(hr == S_OK, "Got hr %#x.\n", hr);
8057 hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
8058 ok(hr == MS_E_NOTRUNNING, "Got hr %#x.\n", hr);
8060 hr = IMediaControl_Stop(media_control);
8061 ok(hr == S_OK, "Got hr %#x.\n", hr);
8062 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8063 ok(hr == S_OK, "Got hr %#x.\n", hr);
8065 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8066 ok(hr == S_OK, "Got hr %#x.\n", hr);
8067 for (i = 0; i < 5; ++i)
8068 memcpy((BYTE *)desc.lpSurface + i * desc.u1.lPitch, initial_data, 12);
8069 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8070 ok(hr == S_OK, "Got hr %#x.\n", hr);
8072 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8074 ammediastream_mem_input_pin = mem_input_pin;
8075 ammediastream_media_sample = media_sample;
8076 ammediastream_sleep_time = 100;
8077 ammediastream_expected_hr = S_OK;
8078 thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
8080 hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
8081 ok(hr == S_OK, "Got hr %#x.\n", hr);
8082 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8083 ok(hr == S_OK, "Got hr %#x.\n", hr);
8084 ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8085 ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.u1.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n");
8086 ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.u1.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n");
8087 ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8088 ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8089 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8090 ok(hr == S_OK, "Got hr %#x.\n", hr);
8092 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8093 CloseHandle(thread);
8095 ref = IMediaSample_Release(media_sample);
8096 ok(!ref, "Got outstanding refcount %d.\n", ref);
8098 ammediastream_pin = pin;
8099 ammediastream_sleep_time = 100;
8100 ammediastream_expected_hr = S_OK;
8101 thread = CreateThread(NULL, 0, ammediastream_end_of_stream, NULL, 0, NULL);
8103 hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
8104 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
8106 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8107 CloseHandle(thread);
8109 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8110 ok(hr == S_OK, "Got hr %#x.\n", hr);
8111 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8112 ok(hr == S_OK, "Got hr %#x.\n", hr);
8114 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8115 ok(hr == S_OK, "Got hr %#x.\n", hr);
8116 for (i = 0; i < 5; ++i)
8117 memcpy((BYTE *)desc.lpSurface + i * desc.u1.lPitch, initial_data, 12);
8118 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8119 ok(hr == S_OK, "Got hr %#x.\n", hr);
8121 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8123 ammediastream_mem_input_pin = mem_input_pin;
8124 ammediastream_media_sample = media_sample;
8125 ammediastream_sleep_time = 100;
8126 ammediastream_expected_hr = S_OK;
8127 thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
8129 hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_CONTINUOUS, NULL, NULL, 0);
8130 ok(hr == S_OK, "Got hr %#x.\n", hr);
8131 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8132 ok(hr == S_OK, "Got hr %#x.\n", hr);
8133 ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8134 ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.u1.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n");
8135 ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.u1.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n");
8136 ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8137 ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8138 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8139 ok(hr == S_OK, "Got hr %#x.\n", hr);
8141 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8142 CloseHandle(thread);
8144 ref = IMediaSample_Release(media_sample);
8145 ok(!ref, "Got outstanding refcount %d.\n", ref);
8147 hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC | SSUPDATE_CONTINUOUS, NULL, NULL, 0);
8148 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8150 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8151 ok(hr == S_OK, "Got hr %#x.\n", hr);
8152 for (i = 0; i < 5; ++i)
8153 memcpy((BYTE *)desc.lpSurface + i * desc.u1.lPitch, initial_data, 12);
8154 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8155 ok(hr == S_OK, "Got hr %#x.\n", hr);
8157 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8158 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
8159 ok(hr == S_OK, "Got hr %#x.\n", hr);
8160 ref = IMediaSample_Release(media_sample);
8161 ok(!ref, "Got outstanding refcount %d.\n", ref);
8163 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8164 ok(hr == S_OK, "Got hr %#x.\n", hr);
8165 ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8166 ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.u1.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n");
8167 ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.u1.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n");
8168 ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8169 ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8170 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8171 ok(hr == S_OK, "Got hr %#x.\n", hr);
8173 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8174 ok(hr == S_OK, "Got hr %#x.\n", hr);
8175 for (i = 0; i < 5; ++i)
8176 memcpy((BYTE *)desc.lpSurface + i * desc.u1.lPitch, initial_data, 12);
8177 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8178 ok(hr == S_OK, "Got hr %#x.\n", hr);
8180 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8181 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
8182 ok(hr == S_OK, "Got hr %#x.\n", hr);
8183 ref = IMediaSample_Release(media_sample);
8184 ok(!ref, "Got outstanding refcount %d.\n", ref);
8186 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8187 ok(hr == S_OK, "Got hr %#x.\n", hr);
8188 ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8189 ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.u1.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n");
8190 ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.u1.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n");
8191 ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8192 ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8193 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8194 ok(hr == S_OK, "Got hr %#x.\n", hr);
8196 hr = IPin_EndOfStream(pin);
8197 ok(hr == S_OK, "Got hr %#x.\n", hr);
8199 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8200 ok(hr == S_OK, "Got hr %#x.\n", hr);
8201 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8202 ok(hr == S_OK, "Got hr %#x.\n", hr);
8204 hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
8205 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8206 EXPECT_REF(stream_sample, 1);
8208 hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
8209 ok(hr == MS_E_BUSY, "Got hr %#x.\n", hr);
8211 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8212 ok(hr == S_OK, "Got hr %#x.\n", hr);
8213 hr = IMediaFilter_SetSyncSource(media_filter, &clock.IReferenceClock_iface);
8214 ok(hr == S_OK, "Got hr %#x.\n", hr);
8215 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8216 ok(hr == S_OK, "Got hr %#x.\n", hr);
8218 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8219 ok(hr == S_OK, "Got hr %#x.\n", hr);
8220 for (i = 0; i < 5; ++i)
8221 memcpy((BYTE *)desc.lpSurface + i * desc.u1.lPitch, initial_data, 12);
8222 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8223 ok(hr == S_OK, "Got hr %#x.\n", hr);
8225 hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
8226 ok(hr == MS_E_BUSY, "Got hr %#x.\n", hr);
8228 clock.advise_time_cookie = &cookie;
8230 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8231 start_time = 11111111;
8232 end_time = 11111111;
8233 hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
8234 ok(hr == S_OK, "Got hr %#x.\n", hr);
8236 ammediastream_mem_input_pin = mem_input_pin;
8237 ammediastream_media_sample = media_sample;
8238 ammediastream_sleep_time = 0;
8239 ammediastream_expected_hr = S_OK;
8240 thread = CreateThread(NULL, 0, ammediastream_receive, NULL, 0, NULL);
8241 ok(!WaitForSingleObject(cookie.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
8242 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
8244 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8245 ok(hr == S_OK, "Got hr %#x.\n", hr);
8246 for (i = 0; i < 5; ++i)
8247 ok(memcmp((BYTE *)desc.lpSurface + i * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8248 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8249 ok(hr == S_OK, "Got hr %#x.\n", hr);
8251 SetEvent(cookie.event);
8253 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8254 CloseHandle(thread);
8256 hr = IDirectDrawSurface_Lock(surface, NULL, &desc, 0, NULL);
8257 ok(hr == S_OK, "Got hr %#x.\n", hr);
8258 ok(memcmp((BYTE *)desc.lpSurface + 0 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8259 ok(memcmp((BYTE *)desc.lpSurface + 1 * desc.u1.lPitch, &test_data[12], 12) == 0, "Sample data didn't match.\n");
8260 ok(memcmp((BYTE *)desc.lpSurface + 2 * desc.u1.lPitch, &test_data[0], 12) == 0, "Sample data didn't match.\n");
8261 ok(memcmp((BYTE *)desc.lpSurface + 3 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8262 ok(memcmp((BYTE *)desc.lpSurface + 4 * desc.u1.lPitch, initial_data, 12) == 0, "Sample data didn't match.\n");
8263 hr = IDirectDrawSurface_Unlock(surface, desc.lpSurface);
8264 ok(hr == S_OK, "Got hr %#x.\n", hr);
8266 ref = IMediaSample_Release(media_sample);
8267 ok(!ref, "Got outstanding refcount %d.\n", ref);
8269 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8270 ok(hr == S_OK, "Got hr %#x.\n", hr);
8271 IGraphBuilder_Disconnect(graph, pin);
8272 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
8273 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8274 ok(hr == S_OK, "Got hr %#x.\n", hr);
8276 hr = IDirectDrawStreamSample_Update(stream_sample, 0, NULL, NULL, 0);
8277 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
8279 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8280 ok(hr == S_OK, "Got hr %#x.\n", hr);
8282 CloseHandle(cookie.advise_time_called_event);
8283 CloseHandle(event);
8284 ref = IDirectDrawStreamSample_Release(stream_sample);
8285 ok(!ref, "Got outstanding refcount %d.\n", ref);
8286 ref = IDirectDrawSurface_Release(surface);
8287 ok(!ref, "Got outstanding refcount %d.\n", ref);
8288 ref = IAMMultiMediaStream_Release(mmstream);
8289 ok(!ref, "Got outstanding refcount %d.\n", ref);
8290 IMediaControl_Release(media_control);
8291 IMediaFilter_Release(media_filter);
8292 ref = IGraphBuilder_Release(graph);
8293 ok(!ref, "Got outstanding refcount %d.\n", ref);
8294 IPin_Release(pin);
8295 IMemInputPin_Release(mem_input_pin);
8296 IDirectDrawMediaStream_Release(ddraw_stream);
8297 ref = IMediaStream_Release(stream);
8298 ok(!ref, "Got outstanding refcount %d.\n", ref);
8299 ref = IDirectDraw_Release(ddraw);
8300 ok(!ref, "Got outstanding refcount %d.\n", ref);
8303 static void test_ddrawstreamsample_completion_status(void)
8305 static const BYTE test_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
8306 IAMMultiMediaStream *mmstream = create_ammultimediastream();
8307 struct advise_time_cookie cookie = { 0 };
8308 IDirectDrawStreamSample *stream_sample1;
8309 IDirectDrawStreamSample *stream_sample2;
8310 IDirectDrawMediaStream *ddraw_stream;
8311 STREAM_TIME filter_start_time;
8312 IMediaStreamFilter *filter;
8313 IMediaSample *media_sample;
8314 IMediaFilter *media_filter;
8315 struct testfilter source;
8316 struct testclock clock;
8317 VIDEOINFO video_info;
8318 IGraphBuilder *graph;
8319 IMediaStream *stream;
8320 AM_MEDIA_TYPE mt;
8321 HANDLE thread;
8322 HRESULT hr;
8323 ULONG ref;
8324 IPin *pin;
8326 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
8327 ok(hr == S_OK, "Got hr %#x.\n", hr);
8328 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
8329 ok(hr == S_OK, "Got hr %#x.\n", hr);
8330 ok(!!filter, "Expected non-null filter.\n");
8331 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
8332 ok(hr == S_OK, "Got hr %#x.\n", hr);
8333 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
8334 ok(hr == S_OK, "Got hr %#x.\n", hr);
8335 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
8336 ok(hr == S_OK, "Got hr %#x.\n", hr);
8337 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
8338 ok(hr == S_OK, "Got hr %#x.\n", hr);
8339 ok(graph != NULL, "Expected non-NULL graph.\n");
8340 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void **)&media_filter);
8341 ok(hr == S_OK, "Got hr %#x.\n", hr);
8342 testfilter_init(&source);
8343 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
8344 ok(hr == S_OK, "Got hr %#x.\n", hr);
8345 testclock_init(&clock);
8346 cookie.advise_time_called_event = CreateEventW(NULL, FALSE, FALSE, NULL);
8348 hr = IMediaFilter_SetSyncSource(media_filter, NULL);
8349 ok(hr == S_OK, "Got hr %#x.\n", hr);
8351 video_info = rgb32_video_info;
8352 video_info.bmiHeader.biWidth = 3;
8353 video_info.bmiHeader.biHeight = 1;
8354 mt = rgb32_mt;
8355 mt.pbFormat = (BYTE *)&video_info;
8356 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
8357 ok(hr == S_OK, "Got hr %#x.\n", hr);
8358 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8359 ok(hr == S_OK, "Got hr %#x.\n", hr);
8361 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &stream_sample1);
8362 ok(hr == S_OK, "Got hr %#x.\n", hr);
8363 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &stream_sample2);
8364 ok(hr == S_OK, "Got hr %#x.\n", hr);
8366 /* Initial status is S_OK. */
8367 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8368 ok(hr == S_OK, "Got hr %#x.\n", hr);
8370 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_WAIT, INFINITE);
8371 ok(hr == S_OK, "Got hr %#x.\n", hr);
8373 /* Update changes the status to MS_S_PENDING. */
8374 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
8375 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8377 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8378 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8380 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_WAIT, 100);
8381 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8383 /* Each Receive call changes the status of one queued sample to S_OK in the same order Update was called. */
8384 hr = IDirectDrawStreamSample_Update(stream_sample2, SSUPDATE_ASYNC, NULL, NULL, 0);
8385 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8387 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample2, 0, 0);
8388 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8390 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8391 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
8392 ok(hr == S_OK, "Got hr %#x.\n", hr);
8393 ref = IMediaSample_Release(media_sample);
8394 ok(!ref, "Got outstanding refcount %d.\n", ref);
8396 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8397 ok(hr == S_OK, "Got hr %#x.\n", hr);
8399 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_WAIT, INFINITE);
8400 ok(hr == S_OK, "Got hr %#x.\n", hr);
8402 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample2, 0, 0);
8403 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8405 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8406 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
8407 ok(hr == S_OK, "Got hr %#x.\n", hr);
8408 ref = IMediaSample_Release(media_sample);
8409 ok(!ref, "Got outstanding refcount %d.\n", ref);
8411 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample2, 0, 0);
8412 ok(hr == S_OK, "Got hr %#x.\n", hr);
8414 /* COMPSTAT_NOUPDATEOK removes the sample from the queue and changes the status to MS_S_NOUPDATE. */
8415 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
8416 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8418 hr = IDirectDrawStreamSample_Update(stream_sample2, SSUPDATE_ASYNC, NULL, NULL, 0);
8419 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8421 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_NOUPDATEOK, 0);
8422 ok(hr == MS_S_NOUPDATE, "Got hr %#x.\n", hr);
8424 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_WAIT, INFINITE);
8425 ok(hr == MS_S_NOUPDATE, "Got hr %#x.\n", hr);
8427 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8428 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
8429 ok(hr == S_OK, "Got hr %#x.\n", hr);
8430 ref = IMediaSample_Release(media_sample);
8431 ok(!ref, "Got outstanding refcount %d.\n", ref);
8433 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8434 ok(hr == MS_S_NOUPDATE, "Got hr %#x.\n", hr);
8436 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample2, 0, 0);
8437 ok(hr == S_OK, "Got hr %#x.\n", hr);
8439 /* COMPSTAT_ABORT removes the sample from the queue and changes the status to MS_S_NOUPDATE. */
8440 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
8441 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8443 hr = IDirectDrawStreamSample_Update(stream_sample2, SSUPDATE_ASYNC, NULL, NULL, 0);
8444 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8446 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_ABORT, 0);
8447 ok(hr == MS_S_NOUPDATE, "Got hr %#x.\n", hr);
8449 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_WAIT, INFINITE);
8450 ok(hr == MS_S_NOUPDATE, "Got hr %#x.\n", hr);
8452 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8453 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
8454 ok(hr == S_OK, "Got hr %#x.\n", hr);
8455 ref = IMediaSample_Release(media_sample);
8456 ok(!ref, "Got outstanding refcount %d.\n", ref);
8458 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8459 ok(hr == MS_S_NOUPDATE, "Got hr %#x.\n", hr);
8461 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample2, 0, 0);
8462 ok(hr == S_OK, "Got hr %#x.\n", hr);
8464 /* COMPSTAT_WAIT has no effect when combined with COMPSTAT_NOUPDATEOK. */
8465 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
8466 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8468 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_NOUPDATEOK | COMPSTAT_WAIT, INFINITE);
8469 ok(hr == MS_S_NOUPDATE, "Got hr %#x.\n", hr);
8471 /* COMPSTAT_WAIT has no effect when combined with COMPSTAT_ABORT. */
8472 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
8473 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8475 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_ABORT | COMPSTAT_WAIT, INFINITE);
8476 ok(hr == MS_S_NOUPDATE, "Got hr %#x.\n", hr);
8478 /* EndOfStream changes the status of the queued samples to MS_S_ENDOFSTREAM. */
8479 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
8480 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8482 hr = IPin_EndOfStream(pin);
8483 ok(hr == S_OK, "Got hr %#x.\n", hr);
8485 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8486 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
8488 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_WAIT, INFINITE);
8489 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
8491 /* Update after EndOfStream changes the status to MS_S_ENDOFSTREAM. */
8492 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
8493 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
8495 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8496 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
8498 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_WAIT, INFINITE);
8499 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
8501 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8502 ok(hr == S_OK, "Got hr %#x.\n", hr);
8503 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8504 ok(hr == S_OK, "Got hr %#x.\n", hr);
8506 /* Continuous update can be canceled by COMPSTAT_NOUPDATEOK. */
8507 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC | SSUPDATE_CONTINUOUS, NULL, NULL, 0);
8508 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8510 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_NOUPDATEOK, 0);
8511 ok(hr == MS_S_NOUPDATE, "Got hr %#x.\n", hr);
8513 /* Continuous update can be canceled by COMPSTAT_ABORT. */
8514 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC | SSUPDATE_CONTINUOUS, NULL, NULL, 0);
8515 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8517 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_ABORT, 0);
8518 ok(hr == MS_S_NOUPDATE, "Got hr %#x.\n", hr);
8520 /* If a sample is in countinuous update mode, when Receive is called it's status remains MS_S_PENDING
8521 * and the sample is moved to the end of the queue. */
8522 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC | SSUPDATE_CONTINUOUS, NULL, NULL, 0);
8523 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8525 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC | SSUPDATE_CONTINUOUS, NULL, NULL, 0);
8526 ok(hr == MS_E_BUSY, "Got hr %#x.\n", hr);
8528 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
8529 ok(hr == MS_E_BUSY, "Got hr %#x.\n", hr);
8531 hr = IDirectDrawStreamSample_Update(stream_sample2, SSUPDATE_ASYNC, NULL, NULL, 0);
8532 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8534 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8535 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8537 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8538 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
8539 ok(hr == S_OK, "Got hr %#x.\n", hr);
8540 ref = IMediaSample_Release(media_sample);
8541 ok(!ref, "Got outstanding refcount %d.\n", ref);
8543 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8544 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8546 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample2, 0, 0);
8547 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8549 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8550 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
8551 ok(hr == S_OK, "Got hr %#x.\n", hr);
8552 ref = IMediaSample_Release(media_sample);
8553 ok(!ref, "Got outstanding refcount %d.\n", ref);
8555 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8556 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8558 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample2, 0, 0);
8559 ok(hr == S_OK, "Got hr %#x.\n", hr);
8561 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_NOUPDATEOK, 0);
8562 ok(hr == S_OK, "Got hr %#x.\n", hr);
8564 /* In continuous update mode, flushing does not affect the status. */
8565 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC | SSUPDATE_CONTINUOUS, NULL, NULL, 0);
8566 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8568 hr = IPin_BeginFlush(pin);
8569 ok(hr == S_OK, "Got hr %#x.\n", hr);
8571 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8572 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8574 hr = IPin_EndFlush(pin);
8575 ok(hr == S_OK, "Got hr %#x.\n", hr);
8577 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8578 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8580 /* In continuous update mode, stopping and running the stream does not affect the status. */
8581 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8582 ok(hr == S_OK, "Got hr %#x.\n", hr);
8584 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8585 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8587 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8588 ok(hr == S_OK, "Got hr %#x.\n", hr);
8590 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8591 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8593 /* In continuous update mode, EndOfStream changes the status to MS_S_ENDOFSTREAM. */
8594 hr = IPin_EndOfStream(pin);
8595 ok(hr == S_OK, "Got hr %#x.\n", hr);
8597 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8598 ok(hr == MS_S_ENDOFSTREAM, "Got hr %#x.\n", hr);
8600 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8601 ok(hr == S_OK, "Got hr %#x.\n", hr);
8602 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8603 ok(hr == S_OK, "Got hr %#x.\n", hr);
8605 /* COMPSTAT_WAIT resets the sample to the non-continuous update mode. */
8606 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC | SSUPDATE_CONTINUOUS, NULL, NULL, 0);
8607 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8609 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_WAIT, 0);
8610 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8612 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8613 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
8614 ok(hr == S_OK, "Got hr %#x.\n", hr);
8615 ref = IMediaSample_Release(media_sample);
8616 ok(!ref, "Got outstanding refcount %d.\n", ref);
8618 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8619 ok(hr == S_OK, "Got hr %#x.\n", hr);
8621 /* In continuous update mode, CompletionStatus with COMPSTAT_WAIT returns when Receive is called. */
8622 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC | SSUPDATE_CONTINUOUS, NULL, NULL, 0);
8623 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8625 streamsample_sample = (IStreamSample *)stream_sample1;
8626 streamsample_flags = COMPSTAT_WAIT;
8627 streamsample_timeout = INFINITE;
8628 streamsample_expected_hr = S_OK;
8629 thread = CreateThread(NULL, 0, streamsample_completion_status, NULL, 0, NULL);
8630 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "CompletionStatus returned prematurely.\n");
8632 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8633 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
8634 ok(hr == S_OK, "Got hr %#x.\n", hr);
8635 ref = IMediaSample_Release(media_sample);
8636 ok(!ref, "Got outstanding refcount %d.\n", ref);
8638 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8639 CloseHandle(thread);
8641 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8642 ok(hr == S_OK, "Got hr %#x.\n", hr);
8644 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8645 ok(hr == S_OK, "Got hr %#x.\n", hr);
8646 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8647 ok(hr == S_OK, "Got hr %#x.\n", hr);
8649 /* CompletionStatus with COMPSTAT_WAIT returns when Receive is called. */
8650 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
8651 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8653 streamsample_sample = (IStreamSample *)stream_sample1;
8654 streamsample_flags = COMPSTAT_WAIT;
8655 streamsample_timeout = INFINITE;
8656 streamsample_expected_hr = S_OK;
8657 thread = CreateThread(NULL, 0, streamsample_completion_status, NULL, 0, NULL);
8658 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "CompletionStatus returned prematurely.\n");
8660 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
8661 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
8662 ok(hr == S_OK, "Got hr %#x.\n", hr);
8663 ref = IMediaSample_Release(media_sample);
8664 ok(!ref, "Got outstanding refcount %d.\n", ref);
8666 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8667 CloseHandle(thread);
8669 /* CompletionStatus with COMPSTAT_WAIT returns when EndOfStream is called. */
8670 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
8671 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8673 streamsample_sample = (IStreamSample *)stream_sample1;
8674 streamsample_flags = COMPSTAT_WAIT;
8675 streamsample_timeout = INFINITE;
8676 streamsample_expected_hr = MS_S_ENDOFSTREAM;
8677 thread = CreateThread(NULL, 0, streamsample_completion_status, NULL, 0, NULL);
8678 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "CompletionStatus returned prematurely.\n");
8680 hr = IPin_EndOfStream(pin);
8681 ok(hr == S_OK, "Got hr %#x.\n", hr);
8683 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8684 CloseHandle(thread);
8686 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8687 ok(hr == S_OK, "Got hr %#x.\n", hr);
8688 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8689 ok(hr == S_OK, "Got hr %#x.\n", hr);
8691 /* Stopping and running the stream does not affect the status and does not remove the sample from the queue. */
8692 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
8693 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8695 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8696 ok(hr == S_OK, "Got hr %#x.\n", hr);
8698 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8699 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8701 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8702 ok(hr == S_OK, "Got hr %#x.\n", hr);
8704 media_sample = ammediastream_allocate_sample(&source, test_data, 6);
8705 hr = IMemInputPin_Receive(source.source.pMemInputPin, media_sample);
8706 ok(hr == S_OK, "Got hr %#x.\n", hr);
8707 ref = IMediaSample_Release(media_sample);
8708 ok(!ref, "Got outstanding refcount %d.\n", ref);
8710 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8711 ok(hr == S_OK, "Got hr %#x.\n", hr);
8713 /* When the stream is stopped Update does not change the status. */
8714 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8715 ok(hr == S_OK, "Got hr %#x.\n", hr);
8717 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
8718 ok(hr == MS_E_NOTRUNNING, "Got hr %#x.\n", hr);
8720 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8721 ok(hr == S_OK, "Got hr %#x.\n", hr);
8723 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_WAIT, INFINITE);
8724 ok(hr == S_OK, "Got hr %#x.\n", hr);
8726 /* When the wait time is less than 1ms the sample is updated immediately. */
8727 hr = IMediaFilter_SetSyncSource(media_filter, &clock.IReferenceClock_iface);
8728 ok(hr == S_OK, "Got hr %#x.\n", hr);
8730 clock.time = 12345678;
8732 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8733 ok(hr == S_OK, "Got hr %#x.\n", hr);
8735 hr = IMediaStreamFilter_GetCurrentStreamTime(filter, &filter_start_time);
8736 ok(hr == S_OK, "Got hr %#x.\n", hr);
8738 clock.time = 12345678 - filter_start_time + 11111111;
8740 clock.advise_time_cookie = &cookie;
8742 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
8743 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8745 thread = ammediastream_async_receive_time(&source,
8746 11111111 + 9999, 11111111 + 9999, test_data, sizeof(test_data));
8747 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8748 CloseHandle(thread);
8750 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, INFINITE);
8751 ok(hr == S_OK, "Got hr %#x.\n", hr);
8753 /* When the wait time is 1ms or greater AdviseTime is called
8754 * with base equal to the sample start time and offset equal to the filter start time. */
8755 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
8756 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8758 thread = ammediastream_async_receive_time(&source,
8759 11111111 + 10000, 11111111 + 10000, test_data, sizeof(test_data));
8760 ok(!WaitForSingleObject(cookie.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
8761 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
8763 ok(cookie.base == 11111111 + 10000, "Got base %s.\n", wine_dbgstr_longlong(cookie.base));
8764 ok(cookie.offset == 12345678 - filter_start_time, "Got offset %s.\n", wine_dbgstr_longlong(cookie.offset));
8766 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8767 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8769 clock.time = 12345678 - filter_start_time + 11111111 + 10000;
8770 SetEvent(cookie.event);
8772 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8773 CloseHandle(thread);
8775 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8776 ok(hr == S_OK, "Got hr %#x.\n", hr);
8778 /* NewSegment does not affect the values passed to AdviseTime. */
8779 hr = IPin_NewSegment(pin, 22222222, 33333333, 1.0);
8780 ok(hr == S_OK, "Got hr %#x.\n", hr);
8782 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
8783 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8785 thread = ammediastream_async_receive_time(&source,
8786 11111111 + 20000, 11111111 + 20000, test_data, sizeof(test_data));
8787 ok(!WaitForSingleObject(cookie.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
8788 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
8790 ok(cookie.base == 11111111 + 20000, "Got base %s.\n", wine_dbgstr_longlong(cookie.base));
8791 ok(cookie.offset == 12345678 - filter_start_time, "Got offset %s.\n", wine_dbgstr_longlong(cookie.offset));
8793 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_NOUPDATEOK, 0);
8794 ok(hr == MS_S_NOUPDATE, "Got hr %#x.\n", hr);
8796 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
8798 clock.time = 12345678 - filter_start_time + 11111111 + 20000;
8799 SetEvent(cookie.event);
8801 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
8803 /* COMPSTAT_NOUPDATEOK does not cause Receive to return.
8804 * Receive waits for the next sample to be queued and updates it. */
8805 hr = IDirectDrawStreamSample_Update(stream_sample1, 0, NULL, NULL, 0);
8806 ok(hr == S_OK, "Got hr %#x.\n", hr);
8808 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8809 CloseHandle(thread);
8811 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
8812 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8814 thread = ammediastream_async_receive_time(&source,
8815 11111111 + 30000, 11111111 + 30000, test_data, sizeof(test_data));
8816 ok(!WaitForSingleObject(cookie.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
8817 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
8819 ok(cookie.base == 11111111 + 30000, "Got base %s.\n", wine_dbgstr_longlong(cookie.base));
8820 ok(cookie.offset == 12345678 - filter_start_time, "Got offset %s.\n", wine_dbgstr_longlong(cookie.offset));
8822 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_NOUPDATEOK | COMPSTAT_WAIT, INFINITE);
8823 ok(hr == MS_S_NOUPDATE, "Got hr %#x.\n", hr);
8825 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
8827 clock.time = 12345678 - filter_start_time + 11111111 + 30000;
8828 SetEvent(cookie.event);
8830 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
8832 hr = IDirectDrawStreamSample_Update(stream_sample1, 0, NULL, NULL, 0);
8833 ok(hr == S_OK, "Got hr %#x.\n", hr);
8835 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8836 CloseHandle(thread);
8838 /* COMPSTAT_ABORT does not cause Receive to return.
8839 * Receive waits for the next sample to be queued and updates it. */
8840 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
8841 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8843 thread = ammediastream_async_receive_time(&source,
8844 11111111 + 40000, 11111111 + 40000, test_data, sizeof(test_data));
8845 ok(!WaitForSingleObject(cookie.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
8846 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
8848 ok(cookie.base == 11111111 + 40000, "Got base %s.\n", wine_dbgstr_longlong(cookie.base));
8849 ok(cookie.offset == 12345678 - filter_start_time, "Got offset %s.\n", wine_dbgstr_longlong(cookie.offset));
8851 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, COMPSTAT_ABORT, 0);
8852 ok(hr == MS_S_NOUPDATE, "Got hr %#x.\n", hr);
8854 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
8856 clock.time = 12345678 - filter_start_time + 11111111 + 40000;
8857 SetEvent(cookie.event);
8859 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
8861 hr = IDirectDrawStreamSample_Update(stream_sample1, 0, NULL, NULL, 0);
8862 ok(hr == S_OK, "Got hr %#x.\n", hr);
8864 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8865 CloseHandle(thread);
8867 /* Stopping the stream causes Receive to return and leaves the sample with MS_S_PENDING status. */
8868 hr = IDirectDrawStreamSample_Update(stream_sample1, SSUPDATE_ASYNC, NULL, NULL, 0);
8869 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8871 thread = ammediastream_async_receive_time(&source,
8872 11111111 + 50000, 11111111 + 50000, test_data, sizeof(test_data));
8873 ok(!WaitForSingleObject(cookie.advise_time_called_event, 2000), "Expected AdviseTime to be called.\n");
8874 ok(WaitForSingleObject(thread, 100) == WAIT_TIMEOUT, "Receive returned prematurely.\n");
8876 ok(cookie.base == 11111111 + 50000, "Got base %s.\n", wine_dbgstr_longlong(cookie.base));
8877 ok(cookie.offset == 12345678 - filter_start_time, "Got offset %s.\n", wine_dbgstr_longlong(cookie.offset));
8879 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
8880 ok(hr == S_OK, "Got hr %#x.\n", hr);
8882 ok(!WaitForSingleObject(thread, 2000), "Wait timed out.\n");
8883 CloseHandle(thread);
8885 hr = IDirectDrawStreamSample_CompletionStatus(stream_sample1, 0, 0);
8886 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
8888 IGraphBuilder_Disconnect(graph, pin);
8889 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
8891 CloseHandle(cookie.advise_time_called_event);
8892 ref = IDirectDrawStreamSample_Release(stream_sample1);
8893 ok(!ref, "Got outstanding refcount %d.\n", ref);
8894 ref = IDirectDrawStreamSample_Release(stream_sample2);
8895 ok(!ref, "Got outstanding refcount %d.\n", ref);
8896 ref = IAMMultiMediaStream_Release(mmstream);
8897 ok(!ref, "Got outstanding refcount %d.\n", ref);
8898 IMediaFilter_Release(media_filter);
8899 ref = IGraphBuilder_Release(graph);
8900 ok(!ref, "Got outstanding refcount %d.\n", ref);
8901 ref = IMediaStreamFilter_Release(filter);
8902 ok(!ref, "Got outstanding refcount %d.\n", ref);
8903 IPin_Release(pin);
8904 IDirectDrawMediaStream_Release(ddraw_stream);
8905 ref = IMediaStream_Release(stream);
8906 ok(!ref, "Got outstanding refcount %d.\n", ref);
8909 static void test_ddrawstreamsample_get_sample_times(void)
8911 static const BYTE test_data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
8912 IAMMultiMediaStream *mmstream = create_ammultimediastream();
8913 IDirectDrawStreamSample *stream_sample;
8914 IMediaFilter *graph_media_filter;
8915 IDirectDrawMediaStream *ddraw_stream;
8916 STREAM_TIME filter_start_time;
8917 IMemInputPin *mem_input_pin;
8918 IMediaStreamFilter *filter;
8919 IMediaSample *media_sample;
8920 struct testfilter source;
8921 STREAM_TIME current_time;
8922 struct testclock clock;
8923 STREAM_TIME start_time;
8924 STREAM_TIME end_time;
8925 IGraphBuilder *graph;
8926 IMediaStream *stream;
8927 VIDEOINFO video_info;
8928 AM_MEDIA_TYPE mt;
8929 HRESULT hr;
8930 ULONG ref;
8931 IPin *pin;
8933 hr = IAMMultiMediaStream_Initialize(mmstream, STREAMTYPE_READ, 0, NULL);
8934 ok(hr == S_OK, "Got hr %#x.\n", hr);
8935 hr = IAMMultiMediaStream_GetFilter(mmstream, &filter);
8936 ok(hr == S_OK, "Got hr %#x.\n", hr);
8937 ok(!!filter, "Expected non-null filter.\n");
8938 hr = IAMMultiMediaStream_AddMediaStream(mmstream, NULL, &MSPID_PrimaryVideo, 0, &stream);
8939 ok(hr == S_OK, "Got hr %#x.\n", hr);
8940 hr = IMediaStream_QueryInterface(stream, &IID_IDirectDrawMediaStream, (void **)&ddraw_stream);
8941 ok(hr == S_OK, "Got hr %#x.\n", hr);
8942 hr = IMediaStream_QueryInterface(stream, &IID_IPin, (void **)&pin);
8943 ok(hr == S_OK, "Got hr %#x.\n", hr);
8944 hr = IMediaStream_QueryInterface(stream, &IID_IMemInputPin, (void **)&mem_input_pin);
8945 ok(hr == S_OK, "Got hr %#x.\n", hr);
8946 hr = IAMMultiMediaStream_GetFilterGraph(mmstream, &graph);
8947 ok(hr == S_OK, "Got hr %#x.\n", hr);
8948 ok(graph != NULL, "Expected non-NULL graph.\n");
8949 hr = IGraphBuilder_QueryInterface(graph, &IID_IMediaFilter, (void **)&graph_media_filter);
8950 ok(hr == S_OK, "Got hr %#x.\n", hr);
8951 testfilter_init(&source);
8952 hr = IGraphBuilder_AddFilter(graph, &source.filter.IBaseFilter_iface, NULL);
8953 ok(hr == S_OK, "Got hr %#x.\n", hr);
8954 testclock_init(&clock);
8956 video_info = rgb32_video_info;
8957 video_info.bmiHeader.biWidth = 3;
8958 video_info.bmiHeader.biHeight = 1;
8959 mt = rgb32_mt;
8960 mt.pbFormat = (BYTE *)&video_info;
8961 hr = IGraphBuilder_ConnectDirect(graph, &source.source.pin.IPin_iface, pin, &mt);
8962 ok(hr == S_OK, "Got hr %#x.\n", hr);
8964 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &stream_sample);
8965 ok(hr == S_OK, "Got hr %#x.\n", hr);
8967 clock.time = 12345678;
8969 current_time = 0xdeadbeefdeadbeef;
8970 hr = IDirectDrawStreamSample_GetSampleTimes(stream_sample, NULL, NULL, &current_time);
8971 ok(hr == S_OK, "Got hr %#x.\n", hr);
8972 ok(current_time == 0, "Got current time %s.\n", wine_dbgstr_longlong(current_time));
8974 IMediaFilter_SetSyncSource(graph_media_filter, &clock.IReferenceClock_iface);
8975 ok(hr == S_OK, "Got hr %#x.\n", hr);
8977 current_time = 0xdeadbeefdeadbeef;
8978 hr = IDirectDrawStreamSample_GetSampleTimes(stream_sample, NULL, NULL, &current_time);
8979 ok(hr == S_OK, "Got hr %#x.\n", hr);
8980 ok(current_time == 0, "Got current time %s.\n", wine_dbgstr_longlong(current_time));
8982 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_RUN);
8983 ok(hr == S_OK, "Got hr %#x.\n", hr);
8985 hr = IMediaStreamFilter_GetCurrentStreamTime(filter, &filter_start_time);
8986 ok(hr == S_OK, "Got hr %#x.\n", hr);
8988 clock.get_time_hr = E_FAIL;
8990 current_time = 0xdeadbeefdeadbeef;
8991 hr = IDirectDrawStreamSample_GetSampleTimes(stream_sample, NULL, NULL, &current_time);
8992 ok(hr == S_OK, "Got hr %#x.\n", hr);
8993 ok(current_time == 0xdeadbeefddf15da1 + filter_start_time, "Expected current time %s, got %s.\n",
8994 wine_dbgstr_longlong(0xdeadbeefddf15da1 + filter_start_time), wine_dbgstr_longlong(current_time));
8996 clock.get_time_hr = S_OK;
8998 current_time = 0xdeadbeefdeadbeef;
8999 hr = IDirectDrawStreamSample_GetSampleTimes(stream_sample, NULL, NULL, &current_time);
9000 ok(hr == S_OK, "Got hr %#x.\n", hr);
9001 ok(current_time == filter_start_time, "Expected current time %s, got %s.\n",
9002 wine_dbgstr_longlong(filter_start_time), wine_dbgstr_longlong(current_time));
9004 clock.time = 23456789;
9006 current_time = 0xdeadbeefdeadbeef;
9007 hr = IDirectDrawStreamSample_GetSampleTimes(stream_sample, NULL, NULL, &current_time);
9008 ok(hr == S_OK, "Got hr %#x.\n", hr);
9009 ok(current_time == filter_start_time + 11111111, "Expected current time %s, got %s.\n",
9010 wine_dbgstr_longlong(filter_start_time + 11111111), wine_dbgstr_longlong(current_time));
9012 start_time = 0xdeadbeefdeadbeef;
9013 end_time = 0xdeadbeefdeadbeef;
9014 hr = IDirectDrawStreamSample_GetSampleTimes(stream_sample, &start_time, &end_time, NULL);
9015 ok(hr == S_OK, "Got hr %#x.\n", hr);
9016 ok(start_time == 0, "Got start time %s.\n", wine_dbgstr_longlong(start_time));
9017 ok(end_time == 0, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
9019 hr = IDirectDrawStreamSample_Update(stream_sample, SSUPDATE_ASYNC, NULL, NULL, 0);
9020 ok(hr == MS_S_PENDING, "Got hr %#x.\n", hr);
9022 media_sample = ammediastream_allocate_sample(&source, test_data, sizeof(test_data));
9023 start_time = 12345678;
9024 end_time = 23456789;
9025 hr = IMediaSample_SetTime(media_sample, &start_time, &end_time);
9026 ok(hr == S_OK, "Got hr %#x.\n", hr);
9027 hr = IMemInputPin_Receive(mem_input_pin, media_sample);
9028 ok(hr == S_OK, "Got hr %#x.\n", hr);
9029 IMediaSample_Release(media_sample);
9031 start_time = 0xdeadbeefdeadbeef;
9032 end_time = 0xdeadbeefdeadbeef;
9033 hr = IDirectDrawStreamSample_GetSampleTimes(stream_sample, &start_time, &end_time, NULL);
9034 ok(hr == S_OK, "Got hr %#x.\n", hr);
9035 ok(start_time == 12345678, "Got start time %s.\n", wine_dbgstr_longlong(start_time));
9036 ok(end_time == 23456789, "Got end time %s.\n", wine_dbgstr_longlong(end_time));
9038 hr = IAMMultiMediaStream_SetState(mmstream, STREAMSTATE_STOP);
9039 ok(hr == S_OK, "Got hr %#x.\n", hr);
9040 IGraphBuilder_Disconnect(graph, pin);
9041 IGraphBuilder_Disconnect(graph, &source.source.pin.IPin_iface);
9043 ref = IDirectDrawStreamSample_Release(stream_sample);
9044 ok(!ref, "Got outstanding refcount %d.\n", ref);
9045 ref = IAMMultiMediaStream_Release(mmstream);
9046 ok(!ref, "Got outstanding refcount %d.\n", ref);
9047 IMediaFilter_Release(graph_media_filter);
9048 ref = IGraphBuilder_Release(graph);
9049 ok(!ref, "Got outstanding refcount %d.\n", ref);
9050 ref = IMediaStreamFilter_Release(filter);
9051 ok(!ref, "Got outstanding refcount %d.\n", ref);
9052 IPin_Release(pin);
9053 IMemInputPin_Release(mem_input_pin);
9054 IDirectDrawMediaStream_Release(ddraw_stream);
9055 ref = IMediaStream_Release(stream);
9056 ok(!ref, "Got outstanding refcount %d.\n", ref);
9059 START_TEST(amstream)
9061 const WCHAR *test_avi_path;
9063 CoInitializeEx(NULL, COINIT_MULTITHREADED);
9065 test_interfaces();
9066 test_add_stream();
9067 test_media_streams();
9068 test_enum_pins();
9069 test_find_pin();
9070 test_pin_info();
9071 test_initialize();
9072 test_set_state();
9073 test_enum_media_types();
9074 test_media_types();
9076 test_avi_path = load_resource(L"test.avi");
9078 test_openfile(test_avi_path);
9079 test_mmstream_get_duration(test_avi_path);
9081 unload_resource(test_avi_path);
9083 test_audiodata_query_interface();
9084 test_audiodata_get_info();
9085 test_audiodata_set_buffer();
9086 test_audiodata_set_actual();
9087 test_audiodata_get_format();
9088 test_audiodata_set_format();
9090 test_audiostream_get_format();
9091 test_audiostream_set_format();
9092 test_audiostream_receive_connection();
9093 test_audiostream_receive();
9094 test_audiostream_initialize();
9095 test_audiostream_begin_flush_end_flush();
9096 test_audiostream_new_segment();
9098 test_audiostreamsample_update();
9099 test_audiostreamsample_completion_status();
9100 test_audiostreamsample_get_sample_times();
9101 test_audiostreamsample_get_media_stream();
9102 test_audiostreamsample_get_audio_data();
9104 test_ddrawstream_initialize();
9105 test_ddrawstream_getsetdirectdraw();
9106 test_ddrawstream_receive_connection();
9107 test_ddrawstream_create_sample();
9108 test_ddrawstream_get_format();
9109 test_ddrawstream_set_format();
9110 test_ddrawstream_receive();
9111 test_ddrawstream_begin_flush_end_flush();
9112 test_ddrawstream_new_segment();
9113 test_ddrawstream_get_time_per_frame();
9115 test_ddrawstreamsample_get_media_stream();
9116 test_ddrawstreamsample_update();
9117 test_ddrawstreamsample_completion_status();
9118 test_ddrawstreamsample_get_sample_times();
9120 test_ammediastream_join_am_multi_media_stream();
9121 test_ammediastream_join_filter();
9122 test_ammediastream_join_filter_graph();
9123 test_ammediastream_set_state();
9124 test_ammediastream_end_of_stream();
9126 test_mediastreamfilter_get_state();
9127 test_mediastreamfilter_stop_pause_run();
9128 test_mediastreamfilter_support_seeking();
9129 test_mediastreamfilter_seeking();
9130 test_mediastreamfilter_get_current_stream_time();
9131 test_mediastreamfilter_reference_time_to_stream_time();
9132 test_mediastreamfilter_wait_until();
9133 test_mediastreamfilter_end_of_stream();
9135 CoUninitialize();