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