[AMSTREAM_WINETEST][QUARTZ_WINETEST]
[reactos.git] / rostests / winetests / amstream / amstream.c
1 /*
2 * Unit tests for MultiMedia Stream functions
3 *
4 * Copyright (C) 2009, 2012 Christian Costa
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #define WIN32_NO_STATUS
22 #define _INC_WINDOWS
23 #define COM_NO_WINDOWS_H
24
25 #define COBJMACROS
26
27 #include <wine/test.h>
28 #include <wingdi.h>
29 #include <winnls.h>
30 #include <vfwmsgs.h>
31 #include <objbase.h>
32 #include <initguid.h>
33 #include <amstream.h>
34 #include <dxsdk/uuids.h>
35
36 static const WCHAR filenameW[] = {'t','e','s','t','.','a','v','i',0};
37
38 static IAMMultiMediaStream* pams;
39 static IDirectDraw7* pdd7;
40 static IDirectDrawSurface7* pdds7;
41
42 static int create_ammultimediastream(void)
43 {
44 return S_OK == CoCreateInstance(
45 &CLSID_AMMultiMediaStream, NULL, CLSCTX_INPROC_SERVER, &IID_IAMMultiMediaStream, (LPVOID*)&pams);
46 }
47
48 static void release_ammultimediastream(void)
49 {
50 IAMMultiMediaStream_Release(pams);
51 }
52
53 static int create_directdraw(void)
54 {
55 HRESULT hr;
56 IDirectDraw* pdd = NULL;
57 DDSURFACEDESC2 ddsd;
58
59 hr = DirectDrawCreate(NULL, &pdd, NULL);
60 ok(hr==DD_OK, "DirectDrawCreate returned: %x\n", hr);
61 if (hr != DD_OK)
62 goto error;
63
64 hr = IDirectDraw_QueryInterface(pdd, &IID_IDirectDraw7, (LPVOID*)&pdd7);
65 ok(hr==DD_OK, "QueryInterface returned: %x\n", hr);
66 if (hr != DD_OK) goto error;
67
68 hr = IDirectDraw7_SetCooperativeLevel(pdd7, GetDesktopWindow(), DDSCL_NORMAL);
69 ok(hr==DD_OK, "SetCooperativeLevel returned: %x\n", hr);
70
71 ZeroMemory(&ddsd, sizeof(ddsd));
72 ddsd.dwSize = sizeof(ddsd);
73 ddsd.dwFlags = DDSD_CAPS;
74 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
75 hr = IDirectDraw7_CreateSurface(pdd7, &ddsd, &pdds7, NULL);
76 ok(hr==DD_OK, "CreateSurface returned: %x\n", hr);
77
78 return TRUE;
79
80 error:
81 if (pdds7)
82 IDirectDrawSurface7_Release(pdds7);
83 if (pdd7)
84 IDirectDraw7_Release(pdd7);
85 if (pdd)
86 IDirectDraw_Release(pdd);
87
88 return FALSE;
89 }
90
91 static void release_directdraw(void)
92 {
93 IDirectDrawSurface7_Release(pdds7);
94 IDirectDraw7_Release(pdd7);
95 }
96
97 static void test_openfile(void)
98 {
99 HRESULT hr;
100 IGraphBuilder* pgraph;
101
102 if (!create_ammultimediastream())
103 return;
104
105 hr = IAMMultiMediaStream_GetFilterGraph(pams, &pgraph);
106 ok(hr==S_OK, "IAMMultiMediaStream_GetFilterGraph returned: %x\n", hr);
107 ok(pgraph==NULL, "Filtergraph should not be created yet\n");
108
109 if (pgraph)
110 IGraphBuilder_Release(pgraph);
111
112 hr = IAMMultiMediaStream_OpenFile(pams, filenameW, 0);
113 ok(hr==S_OK, "IAMMultiMediaStream_OpenFile returned: %x\n", hr);
114
115 hr = IAMMultiMediaStream_GetFilterGraph(pams, &pgraph);
116 ok(hr==S_OK, "IAMMultiMediaStream_GetFilterGraph returned: %x\n", hr);
117 ok(pgraph!=NULL, "Filtergraph should be created\n");
118
119 if (pgraph)
120 IGraphBuilder_Release(pgraph);
121
122 release_ammultimediastream();
123 }
124
125 static void test_renderfile(void)
126 {
127 HRESULT hr;
128 IMediaStream *pvidstream = NULL;
129 IDirectDrawMediaStream *pddstream = NULL;
130 IDirectDrawStreamSample *pddsample = NULL;
131
132 if (!create_ammultimediastream())
133 return;
134 if (!create_directdraw())
135 {
136 release_ammultimediastream();
137 return;
138 }
139
140 hr = IAMMultiMediaStream_Initialize(pams, STREAMTYPE_READ, 0, NULL);
141 ok(hr==S_OK, "IAMMultiMediaStream_Initialize returned: %x\n", hr);
142
143 hr = IAMMultiMediaStream_AddMediaStream(pams, (IUnknown*)pdd7, &MSPID_PrimaryVideo, 0, NULL);
144 ok(hr==S_OK, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
145
146 hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &MSPID_PrimaryAudio, AMMSF_ADDDEFAULTRENDERER, NULL);
147 ok(hr==S_OK, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
148
149 hr = IAMMultiMediaStream_OpenFile(pams, filenameW, 0);
150 ok(hr==S_OK, "IAMMultiMediaStream_OpenFile returned: %x\n", hr);
151
152 hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryVideo, &pvidstream);
153 ok(hr==S_OK, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
154 if (FAILED(hr)) goto error;
155
156 hr = IMediaStream_QueryInterface(pvidstream, &IID_IDirectDrawMediaStream, (LPVOID*)&pddstream);
157 ok(hr==S_OK, "IMediaStream_QueryInterface returned: %x\n", hr);
158 if (FAILED(hr)) goto error;
159
160 hr = IDirectDrawMediaStream_CreateSample(pddstream, NULL, NULL, 0, &pddsample);
161 ok(hr == S_OK, "IDirectDrawMediaStream_CreateSample returned: %x\n", hr);
162
163 error:
164 if (pddsample)
165 IDirectDrawStreamSample_Release(pddsample);
166 if (pddstream)
167 IDirectDrawMediaStream_Release(pddstream);
168 if (pvidstream)
169 IMediaStream_Release(pvidstream);
170
171 release_directdraw();
172 release_ammultimediastream();
173 }
174
175 static void test_media_streams(void)
176 {
177 HRESULT hr;
178 IMediaStream *video_stream = NULL;
179 IMediaStream *audio_stream = NULL;
180 IMediaStream *dummy_stream;
181 IMediaStreamFilter* media_stream_filter = NULL;
182
183 if (!create_ammultimediastream())
184 return;
185 if (!create_directdraw())
186 {
187 release_ammultimediastream();
188 return;
189 }
190
191 hr = IAMMultiMediaStream_Initialize(pams, STREAMTYPE_READ, 0, NULL);
192 ok(hr == S_OK, "IAMMultiMediaStream_Initialize returned: %x\n", hr);
193
194 /* Retrieve media stream filter */
195 hr = IAMMultiMediaStream_GetFilter(pams, NULL);
196 ok(hr == E_POINTER, "IAMMultiMediaStream_GetFilter returned: %x\n", hr);
197 hr = IAMMultiMediaStream_GetFilter(pams, &media_stream_filter);
198 ok(hr == S_OK, "IAMMultiMediaStream_GetFilter returned: %x\n", hr);
199
200 /* Verify behaviour with invalid purpose id */
201 hr = IAMMultiMediaStream_GetMediaStream(pams, &IID_IUnknown, &dummy_stream);
202 ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
203 hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &IID_IUnknown, 0, NULL);
204 ok(hr == MS_E_PURPOSEID, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
205
206 /* Verify there is no video media stream */
207 hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryVideo, &video_stream);
208 ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
209
210 /* Verify there is no default renderer for video stream */
211 hr = IAMMultiMediaStream_AddMediaStream(pams, (IUnknown*)pdd7, &MSPID_PrimaryVideo, AMMSF_ADDDEFAULTRENDERER, NULL);
212 ok(hr == MS_E_PURPOSEID, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
213 hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryVideo, &video_stream);
214 ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
215 hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &MSPID_PrimaryVideo, AMMSF_ADDDEFAULTRENDERER, NULL);
216 ok(hr == MS_E_PURPOSEID, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
217 hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryVideo, &video_stream);
218 ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
219
220 /* Verify normal case for video stream */
221 hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &MSPID_PrimaryVideo, 0, NULL);
222 ok(hr == S_OK, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
223 hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryVideo, &video_stream);
224 ok(hr == S_OK, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
225
226 /* Verify the video stream has been added to the media stream filter */
227 if (media_stream_filter)
228 {
229 hr = IMediaStreamFilter_GetMediaStream(media_stream_filter, &MSPID_PrimaryVideo, &dummy_stream);
230 ok(hr == S_OK, "IMediaStreamFilter_GetMediaStream returned: %x\n", hr);
231 ok(dummy_stream == video_stream, "Got wrong returned pointer %p, expected %p\n", dummy_stream, video_stream);
232 if (SUCCEEDED(hr))
233 IMediaStream_Release(dummy_stream);
234 }
235
236 /* Check interfaces and samples for video */
237 if (video_stream)
238 {
239 IAMMediaStream* am_media_stream;
240 IAudioMediaStream* audio_media_stream;
241 IDirectDrawMediaStream *ddraw_stream = NULL;
242 IDirectDrawStreamSample *ddraw_sample = NULL;
243
244 hr = IMediaStream_QueryInterface(video_stream, &IID_IAMMediaStream, (LPVOID*)&am_media_stream);
245 ok(hr == S_OK, "IMediaStream_QueryInterface returned: %x\n", hr);
246 ok((void*)am_media_stream == (void*)video_stream, "Not same interface, got %p expected %p\n", am_media_stream, video_stream);
247 if (hr == S_OK)
248 IAMMediaStream_Release(am_media_stream);
249
250 hr = IMediaStream_QueryInterface(video_stream, &IID_IAudioMediaStream, (LPVOID*)&audio_media_stream);
251 ok(hr == E_NOINTERFACE, "IMediaStream_QueryInterface returned: %x\n", hr);
252
253 hr = IMediaStream_QueryInterface(video_stream, &IID_IDirectDrawMediaStream, (LPVOID*)&ddraw_stream);
254 ok(hr == S_OK, "IMediaStream_QueryInterface returned: %x\n", hr);
255
256 if (SUCCEEDED(hr))
257 {
258 DDSURFACEDESC current_format, desired_format;
259 IDirectDrawPalette *palette;
260 DWORD flags;
261
262 hr = IDirectDrawMediaStream_GetFormat(ddraw_stream, &current_format, &palette, &desired_format, &flags);
263 ok(hr == MS_E_NOSTREAM, "IDirectDrawoMediaStream_GetFormat returned: %x\n", hr);
264
265 hr = IDirectDrawMediaStream_CreateSample(ddraw_stream, NULL, NULL, 0, &ddraw_sample);
266 ok(hr == S_OK, "IDirectDrawMediaStream_CreateSample returned: %x\n", hr);
267 }
268
269 if (ddraw_sample)
270 IDirectDrawStreamSample_Release(ddraw_sample);
271 if (ddraw_stream)
272 IDirectDrawMediaStream_Release(ddraw_stream);
273 }
274
275 /* Verify there is no audio media stream */
276 hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryAudio, &audio_stream);
277 ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
278
279 /* Verify no stream is created when using the default renderer for audio stream */
280 hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &MSPID_PrimaryAudio, AMMSF_ADDDEFAULTRENDERER, NULL);
281 ok((hr == S_OK) || (hr == VFW_E_NO_AUDIO_HARDWARE), "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
282 if (hr == S_OK)
283 {
284 IGraphBuilder* filtergraph = NULL;
285 IBaseFilter* filter = NULL;
286 const WCHAR name[] = {'0','0','0','1',0};
287 CLSID clsid;
288
289 hr = IAMMultiMediaStream_GetFilterGraph(pams, &filtergraph);
290 ok(hr == S_OK, "IAMMultiMediaStream_GetFilterGraph returned: %x\n", hr);
291 if (hr == S_OK)
292 {
293 hr = IGraphBuilder_FindFilterByName(filtergraph, name, &filter);
294 ok(hr == S_OK, "IGraphBuilder_FindFilterByName returned: %x\n", hr);
295 }
296 if (hr == S_OK)
297 {
298 hr = IBaseFilter_GetClassID(filter, &clsid);
299 ok(hr == S_OK, "IGraphBuilder_FindFilterByName returned: %x\n", hr);
300 }
301 if (hr == S_OK)
302 ok(IsEqualGUID(&clsid, &CLSID_DSoundRender), "Got wrong CLSID\n");
303 if (filter)
304 IBaseFilter_Release(filter);
305 if (filtergraph)
306 IGraphBuilder_Release(filtergraph);
307 }
308 hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryAudio, &audio_stream);
309 ok(hr == MS_E_NOSTREAM, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
310
311 /* Verify a stream is created when no default renderer is used */
312 hr = IAMMultiMediaStream_AddMediaStream(pams, NULL, &MSPID_PrimaryAudio, 0, NULL);
313 ok(hr == S_OK, "IAMMultiMediaStream_AddMediaStream returned: %x\n", hr);
314 hr = IAMMultiMediaStream_GetMediaStream(pams, &MSPID_PrimaryAudio, &audio_stream);
315 ok(hr == S_OK, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
316
317 /* verify the audio stream has been added to the media stream filter */
318 if (media_stream_filter)
319 {
320 hr = IMediaStreamFilter_GetMediaStream(media_stream_filter, &MSPID_PrimaryAudio, &dummy_stream);
321 ok(hr == S_OK, "IAMMultiMediaStream_GetMediaStream returned: %x\n", hr);
322 ok(dummy_stream == audio_stream, "Got wrong returned pointer %p, expected %p\n", dummy_stream, audio_stream);
323 if (SUCCEEDED(hr))
324 IMediaStream_Release(dummy_stream);
325 }
326
327 /* Check interfaces and samples for audio */
328 if (audio_stream)
329 {
330 IAMMediaStream* am_media_stream;
331 IDirectDrawMediaStream* ddraw_stream = NULL;
332 IAudioMediaStream* audio_media_stream = NULL;
333 IAudioStreamSample *audio_sample = NULL;
334
335 hr = IMediaStream_QueryInterface(audio_stream, &IID_IAMMediaStream, (LPVOID*)&am_media_stream);
336 ok(hr == S_OK, "IMediaStream_QueryInterface returned: %x\n", hr);
337 ok((void*)am_media_stream == (void*)audio_stream, "Not same interface, got %p expected %p\n", am_media_stream, audio_stream);
338 if (hr == S_OK)
339 IAMMediaStream_Release(am_media_stream);
340
341 hr = IMediaStream_QueryInterface(audio_stream, &IID_IDirectDrawMediaStream, (LPVOID*)&ddraw_stream);
342 ok(hr == E_NOINTERFACE, "IMediaStream_QueryInterface returned: %x\n", hr);
343
344 hr = IMediaStream_QueryInterface(audio_stream, &IID_IAudioMediaStream, (LPVOID*)&audio_media_stream);
345 ok(hr == S_OK, "IMediaStream_QueryInterface returned: %x\n", hr);
346
347 if (SUCCEEDED(hr))
348 {
349 IAudioData* audio_data = NULL;
350 WAVEFORMATEX format;
351
352 hr = CoCreateInstance(&CLSID_AMAudioData, NULL, CLSCTX_INPROC_SERVER, &IID_IAudioData, (void **)&audio_data);
353 ok(hr == S_OK, "CoCreateInstance returned: %x\n", hr);
354
355 hr = IAudioMediaStream_GetFormat(audio_media_stream, NULL);
356 ok(hr == E_POINTER, "IAudioMediaStream_GetFormat returned: %x\n", hr);
357 hr = IAudioMediaStream_GetFormat(audio_media_stream, &format);
358 ok(hr == MS_E_NOSTREAM, "IAudioMediaStream_GetFormat returned: %x\n", hr);
359
360 hr = IAudioMediaStream_CreateSample(audio_media_stream, NULL, 0, &audio_sample);
361 ok(hr == E_POINTER, "IAudioMediaStream_CreateSample returned: %x\n", hr);
362 hr = IAudioMediaStream_CreateSample(audio_media_stream, audio_data, 0, &audio_sample);
363 ok(hr == S_OK, "IAudioMediaStream_CreateSample returned: %x\n", hr);
364
365 if (audio_data)
366 IAudioData_Release(audio_data);
367 if (audio_sample)
368 IAudioStreamSample_Release(audio_sample);
369 if (audio_media_stream)
370 IAudioMediaStream_Release(audio_media_stream);
371 }
372 }
373
374 if (media_stream_filter)
375 {
376 IEnumPins *enum_pins;
377
378 hr = IMediaStreamFilter_EnumPins(media_stream_filter, &enum_pins);
379 ok(hr == S_OK, "IBaseFilter_EnumPins returned: %x\n", hr);
380 if (hr == S_OK)
381 {
382 IPin* pins[3] = { NULL, NULL, NULL };
383 ULONG nb_pins;
384 ULONG expected_nb_pins = audio_stream ? 2 : 1;
385 int i;
386
387 hr = IEnumPins_Next(enum_pins, 3, pins, &nb_pins);
388 ok(SUCCEEDED(hr), "IEnumPins_Next returned: %x\n", hr);
389 ok(nb_pins == expected_nb_pins, "Number of pins is %u instead of %u\n", nb_pins, expected_nb_pins);
390 for (i = 0; i < min(nb_pins, expected_nb_pins); i++)
391 {
392 IEnumMediaTypes* enum_media_types;
393 AM_MEDIA_TYPE* media_types[10];
394 ULONG nb_media_types;
395 IPin* pin;
396 PIN_INFO info;
397 WCHAR id[40];
398
399 /* Pin name is "I{guid MSPID_PrimaryVideo or MSPID_PrimaryAudio}" */
400 id[0] = 'I';
401 StringFromGUID2(i ? &MSPID_PrimaryAudio : &MSPID_PrimaryVideo, id + 1, 40);
402
403 hr = IPin_ConnectedTo(pins[i], &pin);
404 ok(hr == VFW_E_NOT_CONNECTED, "IPin_ConnectedTo returned: %x\n", hr);
405 hr = IPin_QueryPinInfo(pins[i], &info);
406 ok(hr == S_OK, "IPin_QueryPinInfo returned: %x\n", hr);
407 IBaseFilter_Release(info.pFilter);
408 ok(info.dir == PINDIR_INPUT, "Pin direction is %u instead of %u\n", info.dir, PINDIR_INPUT);
409 ok(!lstrcmpW(info.achName, id), "Pin name is %s instead of %s\n", wine_dbgstr_w(info.achName), wine_dbgstr_w(id));
410 hr = IPin_EnumMediaTypes(pins[i], &enum_media_types);
411 ok(hr == S_OK, "IPin_EnumMediaTypes returned: %x\n", hr);
412 hr = IEnumMediaTypes_Next(enum_media_types, sizeof(media_types) / sizeof(AM_MEDIA_TYPE), media_types, &nb_media_types);
413 ok(SUCCEEDED(hr), "IEnumMediaTypes_Next returned: %x\n", hr);
414 ok(nb_media_types == 0, "nb_media_types should be 0 instead of %u\n", nb_media_types);
415 IEnumMediaTypes_Release(enum_media_types);
416 IPin_Release(pins[i]);
417 }
418 IEnumPins_Release(enum_pins);
419 }
420 }
421
422 /* Test open file with no filename */
423 hr = IAMMultiMediaStream_OpenFile(pams, NULL, 0);
424 ok(hr == E_POINTER, "IAMMultiMediaStream_OpenFile returned %x instead of %x\n", hr, E_POINTER);
425
426 if (video_stream)
427 IMediaStream_Release(video_stream);
428 if (audio_stream)
429 IMediaStream_Release(audio_stream);
430 if (media_stream_filter)
431 IMediaStreamFilter_Release(media_stream_filter);
432
433 release_directdraw();
434 release_ammultimediastream();
435 }
436
437 START_TEST(amstream)
438 {
439 HANDLE file;
440
441 CoInitializeEx(NULL, COINIT_MULTITHREADED);
442
443 test_media_streams();
444
445 file = CreateFileW(filenameW, 0, 0, NULL, OPEN_EXISTING, 0, NULL);
446 if (file != INVALID_HANDLE_VALUE)
447 {
448 CloseHandle(file);
449
450 test_openfile();
451 test_renderfile();
452 }
453
454 CoUninitialize();
455 }