mp3dmod/tests: Enable compilation with long types.
[wine.git] / dlls / mp3dmod / tests / mp3dmod.c
blob7d213fcd18a014b2b779f957c9f11ac709753077
1 /*
2 * Copyright 2018 Zebediah Figura
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
20 #include "windef.h"
21 #include "wingdi.h"
22 #include "mmreg.h"
23 #include "mmsystem.h"
24 #include "dmo.h"
25 #include "wmcodecdsp.h"
26 #include "uuids.h"
27 #include "wine/test.h"
29 #include "initguid.h"
30 DEFINE_GUID(WMMEDIASUBTYPE_MP3, 0x00000055, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
32 /* shorter aliases for flags */
33 #define O_SYNCPOINT DMO_OUTPUT_DATA_BUFFERF_SYNCPOINT
34 #define O_TIME DMO_OUTPUT_DATA_BUFFERF_TIME
35 #define O_TIMELENGTH DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH
36 #define O_INCOMPLETE DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE
38 static REFERENCE_TIME samplelen(DWORD samples, int rate)
40 return (REFERENCE_TIME) 10000000 * samples / rate;
43 struct test_buffer
45 IMediaBuffer IMediaBuffer_iface;
46 LONG refcount;
47 BYTE data[5000];
48 DWORD len;
49 DWORD maxlen;
52 static inline struct test_buffer *impl_from_IMediaBuffer(IMediaBuffer *iface)
54 return CONTAINING_RECORD(iface, struct test_buffer, IMediaBuffer_iface);
57 static HRESULT WINAPI Buffer_QueryInterface(IMediaBuffer *iface, REFIID iid, void **obj)
59 if (IsEqualIID(iid, &IID_IMediaBuffer) || IsEqualIID(iid, &IID_IUnknown))
61 *obj = iface;
62 return S_OK;
64 ok(0, "Unexpected IID %s\n", wine_dbgstr_guid(iid));
65 return E_NOINTERFACE;
68 static ULONG WINAPI Buffer_AddRef(IMediaBuffer *iface)
70 struct test_buffer *buffer = impl_from_IMediaBuffer(iface);
71 return InterlockedIncrement(&buffer->refcount);
74 static ULONG WINAPI Buffer_Release(IMediaBuffer *iface)
76 struct test_buffer *buffer = impl_from_IMediaBuffer(iface);
77 return InterlockedDecrement(&buffer->refcount);
80 static HRESULT WINAPI Buffer_SetLength(IMediaBuffer *iface, DWORD len)
82 struct test_buffer *This = impl_from_IMediaBuffer(iface);
83 This->len = len;
84 return S_OK;
87 static HRESULT WINAPI Buffer_GetMaxLength(IMediaBuffer *iface, DWORD *len)
89 struct test_buffer *This = impl_from_IMediaBuffer(iface);
90 *len = This->maxlen;
91 return S_OK;
94 static HRESULT WINAPI Buffer_GetBufferAndLength(IMediaBuffer *iface, BYTE **buf, DWORD *len)
96 struct test_buffer *This = impl_from_IMediaBuffer(iface);
97 if (buf) *buf = This->data;
98 if (len) *len = This->len;
99 return S_OK;
102 static IMediaBufferVtbl Buffer_vtbl = {
103 Buffer_QueryInterface,
104 Buffer_AddRef,
105 Buffer_Release,
106 Buffer_SetLength,
107 Buffer_GetMaxLength,
108 Buffer_GetBufferAndLength,
111 static void test_convert(void)
113 static const BYTE mp3hdr[] = {0xff,0xfb,0x14,0xc4};
114 struct test_buffer outbuf = {.IMediaBuffer_iface = {&Buffer_vtbl}, .refcount = 1};
115 struct test_buffer inbuf = {.IMediaBuffer_iface = {&Buffer_vtbl}, .refcount = 1};
116 DMO_MEDIA_TYPE in = {{0}}, out = {{0}};
117 MPEGLAYER3WAVEFORMAT mp3fmt = {{0}};
118 DMO_OUTPUT_DATA_BUFFER output;
119 WAVEFORMATEX wavfmt = {0};
120 IMediaObject *dmo;
121 DWORD written;
122 DWORD status;
123 HRESULT hr;
124 int i;
126 hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, NULL, CLSCTX_INPROC_SERVER,
127 &IID_IMediaObject, (void **)&dmo);
128 ok(hr == S_OK, "got %#lx\n", hr);
130 mp3fmt.wfx.wFormatTag = WAVE_FORMAT_MPEGLAYER3;
131 mp3fmt.wfx.nChannels = 2;
132 mp3fmt.wfx.nSamplesPerSec = 48000;
133 in.majortype = MEDIATYPE_Audio;
134 in.subtype = WMMEDIASUBTYPE_MP3;
135 in.formattype = FORMAT_WaveFormatEx;
136 in.cbFormat = sizeof(mp3fmt);
137 in.pbFormat = (BYTE *)&mp3fmt;
139 hr = IMediaObject_SetInputType(dmo, 0, &in, 0);
140 ok(hr == S_OK, "got %#lx\n", hr);
142 wavfmt.wFormatTag = WAVE_FORMAT_PCM;
143 wavfmt.nChannels = 1;
144 wavfmt.nSamplesPerSec = 48000;
145 wavfmt.nAvgBytesPerSec = 48000 * ((1 * 8) / 8);
146 wavfmt.nBlockAlign = (1 * 8) / 8;
147 wavfmt.wBitsPerSample = 8;
148 out.majortype = MEDIATYPE_Audio;
149 out.subtype = MEDIASUBTYPE_PCM;
150 out.formattype = FORMAT_WaveFormatEx;
151 out.cbFormat = sizeof(wavfmt);
152 out.pbFormat = (BYTE *)&wavfmt;
154 hr = IMediaObject_SetOutputType(dmo, 0, &out, 0);
155 ok(hr == S_OK, "got %#lx\n", hr);
157 outbuf.len = 0;
158 outbuf.maxlen = sizeof(outbuf.data);
159 output.pBuffer = &outbuf.IMediaBuffer_iface;
160 output.dwStatus = 0xdeadbeef;
161 output.rtTimestamp = 0xdeadbeef;
162 output.rtTimelength = 0xdeadbeef;
163 hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
164 ok(hr == S_FALSE, "got %#lx\n", hr);
165 ok(outbuf.len == 0, "got %lu\n", outbuf.len);
166 ok(output.dwStatus == 0, "got %#lx\n", output.dwStatus);
167 ok(output.rtTimestamp == 0xdeadbeef, "got %s\n", wine_dbgstr_longlong(output.rtTimestamp));
168 ok(output.rtTimelength == 0xdeadbeef, "got %s\n", wine_dbgstr_longlong(output.rtTimelength));
170 /* write several frames of mp3 data */
171 for (i = 0; i < 5; i++)
172 memcpy(inbuf.data + 96 * i, mp3hdr, 4);
173 inbuf.len = 96 * 5;
174 hr = IMediaObject_ProcessInput(dmo, 0, &inbuf.IMediaBuffer_iface, 0, 0, 0);
175 ok(hr == S_OK, "got %#lx\n", hr);
176 ok(inbuf.refcount == 2, "Got refcount %ld.\n", inbuf.refcount);
178 hr = IMediaObject_ProcessInput(dmo, 0, &inbuf.IMediaBuffer_iface, 0, 0, 0);
179 ok(hr == DMO_E_NOTACCEPTING, "got %#lx\n", hr);
181 outbuf.len = 0;
182 outbuf.maxlen = 0;
183 hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
184 ok(hr == S_FALSE, "got %#lx\n", hr);
185 ok(outbuf.len == 0, "got %lu\n", outbuf.len);
186 ok(output.dwStatus == (O_SYNCPOINT | O_INCOMPLETE), "got %#lx\n", output.dwStatus);
187 ok(output.rtTimestamp == 0xdeadbeef, "got %s\n", wine_dbgstr_longlong(output.rtTimestamp));
188 ok(output.rtTimelength == 0xdeadbeef, "got %s\n", wine_dbgstr_longlong(output.rtTimelength));
190 /* implementations are inconsistent, but should write at least one frame of data */
191 outbuf.len = 0;
192 outbuf.maxlen = 5000;
193 hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
194 ok(hr == S_OK, "got %#lx\n", hr);
195 written = outbuf.len;
196 ok(written > 1152 && written <= 5000, "got %lu\n", written);
197 ok(output.dwStatus == (O_SYNCPOINT | O_TIME | O_TIMELENGTH | O_INCOMPLETE),
198 "got %#lx\n", output.dwStatus);
199 ok(output.rtTimestamp == 0, "got %s\n", wine_dbgstr_longlong(output.rtTimestamp));
200 ok(output.rtTimelength == samplelen(written, 48000),
201 "got %s\n", wine_dbgstr_longlong(output.rtTimelength));
202 ok(inbuf.refcount == 2, "Got refcount %ld.\n", inbuf.refcount);
203 ok(outbuf.refcount == 1, "Got refcount %ld.\n", inbuf.refcount);
205 hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
206 ok(hr == S_FALSE, "got %#lx\n", hr);
207 ok(outbuf.len == written, "expected %lu, got %lu\n", written, outbuf.len);
208 ok(output.dwStatus == (O_SYNCPOINT | O_INCOMPLETE), "got %#lx\n", output.dwStatus);
209 ok(output.rtTimestamp == 0, "got %s\n", wine_dbgstr_longlong(output.rtTimestamp));
210 ok(output.rtTimelength == samplelen(written, 48000),
211 "got %s\n", wine_dbgstr_longlong(output.rtTimelength));
213 hr = IMediaObject_ProcessInput(dmo, 0, &inbuf.IMediaBuffer_iface, 0, 0, 0);
214 ok(hr == DMO_E_NOTACCEPTING, "got %#lx\n", hr);
215 ok(inbuf.refcount == 2, "Got refcount %ld.\n", inbuf.refcount);
216 ok(outbuf.refcount == 1, "Got refcount %ld.\n", inbuf.refcount);
218 /* write the rest */
219 outbuf.len = 0;
220 outbuf.maxlen = 5000;
221 hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
222 ok(hr == S_OK, "got %#lx\n", hr);
223 ok(written + outbuf.len == (1152 * 5) ||
224 broken(written + outbuf.len == (1152 * 5) - 528), /* Win10 */
225 "got %lu, total %lu\n", outbuf.len, written + outbuf.len);
226 ok(output.dwStatus == (O_SYNCPOINT | O_TIME | O_TIMELENGTH), "got %#lx\n", output.dwStatus);
227 ok(output.rtTimestamp == samplelen(written, 48000),
228 "got %s\n", wine_dbgstr_longlong(output.rtTimestamp));
229 ok(output.rtTimelength == samplelen(outbuf.len, 48000),
230 "got %s\n", wine_dbgstr_longlong(output.rtTimelength));
231 ok(inbuf.refcount == 1, "Got refcount %ld.\n", inbuf.refcount);
232 ok(outbuf.refcount == 1, "Got refcount %ld.\n", inbuf.refcount);
233 written += outbuf.len;
235 hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
236 ok(hr == S_FALSE, "got %#lx\n", hr);
237 ok(output.dwStatus == 0, "got %#lx\n", output.dwStatus);
239 output.pBuffer = NULL;
240 output.dwStatus = 0xdeadbeef;
241 output.rtTimestamp = 0xdeadbeef;
242 output.rtTimelength = 0xdeadbeef;
243 hr = IMediaObject_ProcessOutput(dmo, DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER, 1, &output, &status);
244 ok(hr == S_OK, "Got hr %#lx.\n", hr);
245 ok(!output.pBuffer, "Got buffer %p.\n", output.pBuffer);
246 ok(!output.dwStatus, "Got status %#lx.\n", output.dwStatus);
247 ok(output.rtTimestamp == 0xdeadbeef, "Got timestamp %s.\n", wine_dbgstr_longlong(output.rtTimestamp));
248 ok(output.rtTimelength == 0xdeadbeef, "Got length %s.\n", wine_dbgstr_longlong(output.rtTimelength));
250 hr = IMediaObject_ProcessInput(dmo, 0, &inbuf.IMediaBuffer_iface, 0, 0, 0);
251 ok(hr == S_OK, "got %#lx\n", hr);
253 hr = IMediaObject_ProcessInput(dmo, 0, &inbuf.IMediaBuffer_iface, 0, 0, 0);
254 ok(hr == DMO_E_NOTACCEPTING, "Got hr %#lx.\n", hr);
256 output.pBuffer = NULL;
257 output.dwStatus = 0xdeadbeef;
258 output.rtTimestamp = 0xdeadbeef;
259 output.rtTimelength = 0xdeadbeef;
260 hr = IMediaObject_ProcessOutput(dmo, DMO_PROCESS_OUTPUT_DISCARD_WHEN_NO_BUFFER, 1, &output, &status);
261 ok(hr == S_OK, "Got hr %#lx.\n", hr);
262 ok(!output.pBuffer, "Got buffer %p.\n", output.pBuffer);
263 ok(output.dwStatus == O_INCOMPLETE, "Got status %#lx.\n", output.dwStatus);
264 ok(output.rtTimestamp == 0xdeadbeef, "Got timestamp %s.\n", wine_dbgstr_longlong(output.rtTimestamp));
265 ok(output.rtTimelength == 0xdeadbeef, "Got length %s.\n", wine_dbgstr_longlong(output.rtTimelength));
266 ok(inbuf.refcount == 2, "Got refcount %ld.\n", inbuf.refcount);
268 hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
269 ok(hr == S_OK, "Got hr %#lx.\n", hr);
270 ok(!output.pBuffer, "Got buffer %p.\n", output.pBuffer);
271 ok(output.dwStatus == O_INCOMPLETE, "Got status %#lx.\n", output.dwStatus);
272 ok(output.rtTimestamp == 0xdeadbeef, "Got timestamp %s.\n", wine_dbgstr_longlong(output.rtTimestamp));
273 ok(output.rtTimelength == 0xdeadbeef, "Got length %s.\n", wine_dbgstr_longlong(output.rtTimelength));
274 ok(inbuf.refcount == 2, "Got refcount %ld.\n", inbuf.refcount);
276 output.pBuffer = &outbuf.IMediaBuffer_iface;
277 outbuf.len = 0;
278 outbuf.maxlen = 5000;
279 hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
280 ok(hr == S_OK, "Got hr %#lx.\n", hr);
281 ok(outbuf.len > 1152 && outbuf.len <= 5000, "Got length %lu.\n", outbuf.len);
282 ok(output.dwStatus == (O_SYNCPOINT | O_TIME | O_TIMELENGTH | O_INCOMPLETE),
283 "Got status %#lx.\n", output.dwStatus);
284 ok(output.rtTimestamp == samplelen(written, 48000), "Got timestamp %s.\n",
285 wine_dbgstr_longlong(output.rtTimestamp));
286 ok(output.rtTimelength == samplelen(outbuf.len, 48000),
287 "Got length %s.\n", wine_dbgstr_longlong(output.rtTimelength));
288 ok(inbuf.refcount == 2, "Got refcount %ld.\n", inbuf.refcount);
289 ok(outbuf.refcount == 1, "Got refcount %ld.\n", inbuf.refcount);
291 hr = IMediaObject_Flush(dmo);
292 ok(hr == S_OK, "Got hr %#lx.\n", hr);
293 ok(inbuf.refcount == 1, "Got refcount %ld.\n", inbuf.refcount);
295 outbuf.len = 0;
296 outbuf.maxlen = 5000;
297 hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
298 ok(hr == S_FALSE, "Got hr %#lx.\n", hr);
300 hr = IMediaObject_Flush(dmo);
301 ok(hr == S_OK, "Got hr %#lx.\n", hr);
303 hr = IMediaObject_ProcessInput(dmo, 0, &inbuf.IMediaBuffer_iface, 0, 0, 0);
304 ok(hr == S_OK, "got %#lx\n", hr);
306 hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
307 ok(hr == S_OK, "Got hr %#lx.\n", hr);
308 ok(outbuf.len > 1152 && outbuf.len <= 5000, "Got length %lu.\n", outbuf.len);
309 ok(output.dwStatus == (O_SYNCPOINT | O_TIME | O_TIMELENGTH | O_INCOMPLETE),
310 "Got status %#lx.\n", output.dwStatus);
311 ok(!output.rtTimestamp, "Got timestamp %s.\n", wine_dbgstr_longlong(output.rtTimestamp));
312 ok(output.rtTimelength == samplelen(outbuf.len, 48000),
313 "Got length %s.\n", wine_dbgstr_longlong(output.rtTimelength));
314 ok(inbuf.refcount == 2, "Got refcount %ld.\n", inbuf.refcount);
315 ok(outbuf.refcount == 1, "Got refcount %ld.\n", inbuf.refcount);
317 IMediaObject_Release(dmo);
318 ok(inbuf.refcount == 1, "Got outstanding refcount %ld.\n", inbuf.refcount);
319 ok(outbuf.refcount == 1, "Got outstanding refcount %ld.\n", outbuf.refcount);
322 static const GUID IID_test_outer = {0xdeadbeef,0,0,{0,0,0,0,0,0,0,0x66}};
324 static HRESULT WINAPI Outer_QueryInterface(IUnknown *iface, REFIID iid, void **obj)
326 if (IsEqualGUID(iid, &IID_test_outer))
328 *obj = (IUnknown *)0xdeadbeef;
329 return S_OK;
331 ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid));
332 return E_NOINTERFACE;
335 static ULONG WINAPI Outer_AddRef(IUnknown *iface)
337 return 2;
340 static ULONG WINAPI Outer_Release(IUnknown *iface)
342 return 1;
345 static IUnknownVtbl Outer_vtbl = {
346 Outer_QueryInterface,
347 Outer_AddRef,
348 Outer_Release,
351 static IUnknown Outer = { &Outer_vtbl };
353 static void test_aggregation(void)
355 IUnknown *unk, *unk2;
356 IMediaObject *dmo;
357 HRESULT hr;
359 hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, &Outer, CLSCTX_INPROC_SERVER,
360 &IID_IUnknown, (void **)&unk);
361 ok(hr == S_OK, "got %#lx\n", hr);
363 hr = IUnknown_QueryInterface(unk, &IID_IMediaObject, (void **)&dmo);
364 ok(hr == S_OK, "got %#lx\n", hr);
366 hr = IMediaObject_QueryInterface(dmo, &IID_test_outer, (void **)&unk2);
367 ok(hr == S_OK, "got %#lx\n", hr);
368 ok(unk2 == (IUnknown *)0xdeadbeef, "got unk %p\n", unk2);
370 IUnknown_Release(dmo);
371 IUnknown_Release(unk);
373 hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, &Outer, CLSCTX_INPROC_SERVER,
374 &IID_IMediaObject, (void **)&unk);
375 ok(hr == E_NOINTERFACE, "got %#lx\n", hr);
378 static void test_stream_info(void)
380 MPEGLAYER3WAVEFORMAT input_format =
382 .wfx.nSamplesPerSec = 48000,
384 DMO_MEDIA_TYPE input_mt =
386 .majortype = MEDIATYPE_Audio,
387 .subtype = WMMEDIASUBTYPE_MP3,
388 .formattype = FORMAT_WaveFormatEx,
389 .cbFormat = sizeof(input_format),
390 .pbFormat = (BYTE *)&input_format,
393 WAVEFORMATEX output_format =
395 .nSamplesPerSec = 48000,
397 DMO_MEDIA_TYPE output_mt =
399 .formattype = FORMAT_WaveFormatEx,
400 .cbFormat = sizeof(output_format),
401 .pbFormat = (BYTE *)&output_format,
404 DWORD input_count, output_count, flags, size, lookahead, alignment;
405 WORD channels, depth;
406 IMediaObject *dmo;
407 HRESULT hr;
409 hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, NULL, CLSCTX_INPROC_SERVER,
410 &IID_IMediaObject, (void **)&dmo);
411 ok(hr == S_OK, "Got hr %#lx.\n", hr);
413 hr = IMediaObject_GetStreamCount(dmo, &input_count, &output_count);
414 ok(hr == S_OK, "Got hr %#lx.\n", hr);
415 ok(input_count == 1, "Got input count %lu.\n", input_count);
416 ok(output_count == 1, "Got output count %lu.\n", output_count);
418 flags = 0xdeadbeef;
419 hr = IMediaObject_GetInputStreamInfo(dmo, 0, &flags);
420 ok(hr == S_OK, "Got hr %#lx.\n", hr);
421 ok(!flags, "Got flags %#lx.\n", flags);
423 flags = 0xdeadbeef;
424 hr = IMediaObject_GetOutputStreamInfo(dmo, 0, &flags);
425 ok(hr == S_OK, "Got hr %#lx.\n", hr);
426 ok(!flags, "Got flags %#lx.\n", flags);
428 hr = IMediaObject_GetInputSizeInfo(dmo, 0, &size, &lookahead, &alignment);
429 ok(hr == DMO_E_TYPE_NOT_SET, "Got hr %#lx.\n", hr);
430 hr = IMediaObject_GetOutputSizeInfo(dmo, 0, &size, &alignment);
431 ok(hr == DMO_E_TYPE_NOT_SET, "Got hr %#lx.\n", hr);
433 for (channels = 1; channels <= 2; ++channels)
435 input_format.wfx.nChannels = channels;
436 output_format.nChannels = channels;
438 hr = IMediaObject_SetInputType(dmo, 0, &input_mt, 0);
439 ok(hr == S_OK, "Got hr %#lx.\n", hr);
441 hr = IMediaObject_GetInputSizeInfo(dmo, 0, &size, &lookahead, &alignment);
442 ok(hr == DMO_E_TYPE_NOT_SET, "Got hr %#lx.\n", hr);
443 hr = IMediaObject_GetOutputSizeInfo(dmo, 0, &size, &alignment);
444 ok(hr == DMO_E_TYPE_NOT_SET, "Got hr %#lx.\n", hr);
446 for (depth = 8; depth <= 16; depth += 8)
448 output_format.wBitsPerSample = depth;
449 output_format.nBlockAlign = channels * depth / 8;
450 output_format.nAvgBytesPerSec = 48000 * output_format.nBlockAlign;
452 hr = IMediaObject_SetOutputType(dmo, 0, &output_mt, 0);
453 ok(hr == S_OK, "Got hr %#lx.\n", hr);
455 size = lookahead = alignment = 0xdeadbeef;
456 hr = IMediaObject_GetInputSizeInfo(dmo, 0, &size, &lookahead, &alignment);
457 ok(hr == S_OK, "Got hr %#lx.\n", hr);
458 ok(!size || broken(size == output_format.nBlockAlign) /* Vista */,
459 "Got size %lu for %u channels, depth %u.\n", size, channels, depth);
460 ok(lookahead == 0xdeadbeef, "Got lookahead %lu.\n", lookahead);
461 ok(alignment == 1, "Got alignment %lu.\n", alignment);
463 size = alignment = 0xdeadbeef;
464 hr = IMediaObject_GetOutputSizeInfo(dmo, 0, &size, &alignment);
465 ok(hr == S_OK, "Got hr %#lx.\n", hr);
466 /* Vista returns the expected size; all later versions act as if
467 * channels == 2 for some reason. */
468 ok(size >= channels * 1152 * depth / 8,
469 "Got size %lu for %u channels, depth %u.\n", size, channels, depth);
470 ok(alignment == 1, "Got alignment %lu.\n", alignment);
473 hr = IMediaObject_SetOutputType(dmo, 0, &output_mt, DMO_SET_TYPEF_CLEAR);
474 ok(hr == S_OK, "Got hr %#lx.\n", hr);
477 IMediaObject_Release(dmo);
480 static void test_media_types(void)
482 MPEGLAYER3WAVEFORMAT mp3fmt =
484 .wfx.nChannels = 2,
485 .wfx.nSamplesPerSec = 48000,
487 DMO_MEDIA_TYPE input_mt =
489 .majortype = MEDIATYPE_Audio,
490 .subtype = WMMEDIASUBTYPE_MP3,
491 .formattype = FORMAT_WaveFormatEx,
492 .cbFormat = sizeof(mp3fmt),
493 .pbFormat = (BYTE *)&mp3fmt,
496 WAVEFORMATEX expect_wfx =
498 .wFormatTag = WAVE_FORMAT_PCM,
499 .nSamplesPerSec = 48000,
502 WAVEFORMATEX output_format =
504 .nChannels = 1,
505 .nSamplesPerSec = 48000,
506 .nAvgBytesPerSec = 48000,
507 .nBlockAlign = 1,
508 .wBitsPerSample = 8,
510 DMO_MEDIA_TYPE output_mt =
512 .formattype = FORMAT_WaveFormatEx,
513 .cbFormat = sizeof(output_format),
514 .pbFormat = (BYTE *)&output_format,
517 DMO_MEDIA_TYPE mt;
518 IMediaObject *dmo;
519 HRESULT hr;
520 DWORD i;
522 hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, NULL, CLSCTX_INPROC_SERVER,
523 &IID_IMediaObject, (void **)&dmo);
524 ok(hr == S_OK, "Got hr %#lx.\n", hr);
526 memset(&mt, 0xcc, sizeof(DMO_MEDIA_TYPE));
527 hr = IMediaObject_GetInputType(dmo, 0, 0, &mt);
528 ok(hr == S_OK, "Got hr %#lx.\n", hr);
529 ok(IsEqualGUID(&mt.majortype, &MEDIATYPE_Audio), "Got major type %s.\n", wine_dbgstr_guid(&mt.majortype));
530 ok(IsEqualGUID(&mt.subtype, &WMMEDIASUBTYPE_MP3), "Got subtype %s.\n", wine_dbgstr_guid(&mt.subtype));
531 ok(mt.bFixedSizeSamples == 0xcccccccc, "Got fixed size %d.\n", mt.bFixedSizeSamples);
532 ok(mt.bTemporalCompression == 0xcccccccc, "Got temporal compression %d.\n", mt.bTemporalCompression);
533 ok(mt.lSampleSize == 0xcccccccc, "Got sample size %lu.\n", mt.lSampleSize);
534 ok(IsEqualGUID(&mt.formattype, &GUID_NULL), "Got format type %s.\n",
535 wine_dbgstr_guid(&mt.formattype));
536 ok(!mt.pUnk, "Got pUnk %p.\n", mt.pUnk);
537 ok(!mt.cbFormat, "Got format size %lu.\n", mt.cbFormat);
538 ok(!mt.pbFormat, "Got format block %p.\n", mt.pbFormat);
540 hr = IMediaObject_GetInputType(dmo, 0, 1, &mt);
541 ok(hr == DMO_E_NO_MORE_ITEMS, "Got hr %#lx.\n", hr);
543 memset(&mt, 0xcc, sizeof(DMO_MEDIA_TYPE));
544 hr = IMediaObject_GetOutputType(dmo, 0, 0, &mt);
545 ok(hr == DMO_E_TYPE_NOT_SET, "Got hr %#lx.\n", hr);
547 hr = IMediaObject_SetInputType(dmo, 0, &input_mt, DMO_SET_TYPEF_TEST_ONLY);
548 ok(hr == S_OK, "Got hr %#lx.\n", hr);
550 input_mt.majortype = GUID_NULL;
551 hr = IMediaObject_SetInputType(dmo, 0, &input_mt, DMO_SET_TYPEF_TEST_ONLY);
552 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
553 input_mt.majortype = MEDIATYPE_Stream;
554 hr = IMediaObject_SetInputType(dmo, 0, &input_mt, DMO_SET_TYPEF_TEST_ONLY);
555 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
556 input_mt.majortype = MEDIATYPE_Audio;
558 input_mt.subtype = GUID_NULL;
559 hr = IMediaObject_SetInputType(dmo, 0, &input_mt, DMO_SET_TYPEF_TEST_ONLY);
560 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
561 input_mt.subtype = MEDIASUBTYPE_PCM;
562 hr = IMediaObject_SetInputType(dmo, 0, &input_mt, DMO_SET_TYPEF_TEST_ONLY);
563 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
564 input_mt.subtype = WMMEDIASUBTYPE_MP3;
566 input_mt.formattype = GUID_NULL;
567 hr = IMediaObject_SetInputType(dmo, 0, &input_mt, DMO_SET_TYPEF_TEST_ONLY);
568 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
569 input_mt.formattype = FORMAT_None;
570 hr = IMediaObject_SetInputType(dmo, 0, &input_mt, DMO_SET_TYPEF_TEST_ONLY);
571 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
572 input_mt.formattype = FORMAT_WaveFormatEx;
574 hr = IMediaObject_SetInputType(dmo, 0, &input_mt, 0);
575 ok(hr == S_OK, "Got hr %#lx.\n", hr);
577 for (i = 0; i < 4; ++i)
579 memset(&mt, 0xcc, sizeof(DMO_MEDIA_TYPE));
580 hr = IMediaObject_GetOutputType(dmo, 0, i, &mt);
581 ok(hr == S_OK, "Got hr %#lx.\n", hr);
582 ok(IsEqualGUID(&mt.majortype, &MEDIATYPE_Audio), "Got major type %s.\n", wine_dbgstr_guid(&mt.majortype));
583 ok(IsEqualGUID(&mt.subtype, &MEDIASUBTYPE_PCM), "Got subtype %s.\n", wine_dbgstr_guid(&mt.subtype));
584 ok(mt.bFixedSizeSamples == 0xcccccccc, "Got fixed size %d.\n", mt.bFixedSizeSamples);
585 ok(mt.bTemporalCompression == 0xcccccccc, "Got temporal compression %d.\n", mt.bTemporalCompression);
586 ok(mt.lSampleSize == 0xcccccccc, "Got sample size %lu.\n", mt.lSampleSize);
587 ok(IsEqualGUID(&mt.formattype, &FORMAT_WaveFormatEx), "Got format type %s.\n",
588 wine_dbgstr_guid(&mt.formattype));
589 ok(!mt.pUnk, "Got pUnk %p.\n", mt.pUnk);
590 ok(mt.cbFormat >= sizeof(WAVEFORMATEX), "Got format size %lu.\n", mt.cbFormat);
591 ok(!!mt.pbFormat, "Got format block %p.\n", mt.pbFormat);
593 expect_wfx.nChannels = (i / 2) ? 1 : 2;
594 expect_wfx.wBitsPerSample = (i % 2) ? 8 : 16;
595 expect_wfx.nBlockAlign = expect_wfx.nChannels * expect_wfx.wBitsPerSample / 8;
596 expect_wfx.nAvgBytesPerSec = 48000 * expect_wfx.nBlockAlign;
597 ok(!memcmp(mt.pbFormat, &expect_wfx, sizeof(WAVEFORMATEX)), "Format blocks didn't match.\n");
599 MoFreeMediaType(&mt);
602 hr = IMediaObject_GetOutputType(dmo, 0, 4, &mt);
603 ok(hr == DMO_E_NO_MORE_ITEMS, "Got hr %#lx.\n", hr);
605 mp3fmt.wfx.nChannels = 1;
606 hr = IMediaObject_SetInputType(dmo, 0, &input_mt, 0);
607 ok(hr == S_OK, "Got hr %#lx.\n", hr);
609 for (i = 0; i < 2; ++i)
611 memset(&mt, 0xcc, sizeof(DMO_MEDIA_TYPE));
612 hr = IMediaObject_GetOutputType(dmo, 0, i, &mt);
613 ok(hr == S_OK, "Got hr %#lx.\n", hr);
614 ok(IsEqualGUID(&mt.majortype, &MEDIATYPE_Audio), "Got major type %s.\n", wine_dbgstr_guid(&mt.majortype));
615 ok(IsEqualGUID(&mt.subtype, &MEDIASUBTYPE_PCM), "Got subtype %s.\n", wine_dbgstr_guid(&mt.subtype));
616 ok(mt.bFixedSizeSamples == 0xcccccccc, "Got fixed size %d.\n", mt.bFixedSizeSamples);
617 ok(mt.bTemporalCompression == 0xcccccccc, "Got temporal compression %d.\n", mt.bTemporalCompression);
618 ok(mt.lSampleSize == 0xcccccccc, "Got sample size %lu.\n", mt.lSampleSize);
619 ok(IsEqualGUID(&mt.formattype, &FORMAT_WaveFormatEx), "Got format type %s.\n",
620 wine_dbgstr_guid(&mt.formattype));
621 ok(!mt.pUnk, "Got pUnk %p.\n", mt.pUnk);
622 ok(mt.cbFormat >= sizeof(WAVEFORMATEX), "Got format size %lu.\n", mt.cbFormat);
623 ok(!!mt.pbFormat, "Got format block %p.\n", mt.pbFormat);
625 expect_wfx.nChannels = 1;
626 expect_wfx.wBitsPerSample = (i % 2) ? 8 : 16;
627 expect_wfx.nBlockAlign = expect_wfx.nChannels * expect_wfx.wBitsPerSample / 8;
628 expect_wfx.nAvgBytesPerSec = 48000 * expect_wfx.nBlockAlign;
629 ok(!memcmp(mt.pbFormat, &expect_wfx, sizeof(WAVEFORMATEX)), "Format blocks didn't match.\n");
631 MoFreeMediaType(&mt);
634 hr = IMediaObject_GetOutputType(dmo, 0, 2, &mt);
635 ok(hr == DMO_E_NO_MORE_ITEMS, "Got hr %#lx.\n", hr);
637 hr = IMediaObject_SetOutputType(dmo, 0, &output_mt, DMO_SET_TYPEF_TEST_ONLY);
638 ok(hr == S_OK, "Got hr %#lx.\n", hr);
640 output_mt.formattype = GUID_NULL;
641 hr = IMediaObject_SetOutputType(dmo, 0, &output_mt, DMO_SET_TYPEF_TEST_ONLY);
642 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
643 output_mt.formattype = FORMAT_None;
644 hr = IMediaObject_SetOutputType(dmo, 0, &output_mt, DMO_SET_TYPEF_TEST_ONLY);
645 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "Got hr %#lx.\n", hr);
646 output_mt.formattype = FORMAT_WaveFormatEx;
648 IMediaObject_Release(dmo);
651 START_TEST(mp3dmod)
653 IMediaObject *dmo;
654 HRESULT hr;
656 CoInitializeEx(NULL, COINIT_MULTITHREADED);
658 hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, NULL, CLSCTX_INPROC_SERVER,
659 &IID_IMediaObject, (void **)&dmo);
660 if (hr == REGDB_E_CLASSNOTREG)
662 win_skip("CLSID_CMP3DecMediaObject not available\n");
663 return;
665 IMediaObject_Release(dmo);
667 test_convert();
668 test_aggregation();
669 test_stream_info();
670 test_media_types();
672 CoUninitialize();