makefiles: Don't use standard libs for programs that specify -nodefaultlibs.
[wine/zf.git] / dlls / mp3dmod / tests / mp3dmod.c
blob61002d5966165e2a91d197218e921649c5c4e2d3
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 %#x\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 %#x\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 %#x\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 %#x\n", hr);
165 ok(outbuf.len == 0, "got %u\n", outbuf.len);
166 ok(output.dwStatus == 0, "got %#x\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 %#x\n", hr);
176 ok(inbuf.refcount == 2, "Got refcount %d.\n", inbuf.refcount);
178 hr = IMediaObject_ProcessInput(dmo, 0, &inbuf.IMediaBuffer_iface, 0, 0, 0);
179 ok(hr == DMO_E_NOTACCEPTING, "got %#x\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 %#x\n", hr);
185 ok(outbuf.len == 0, "got %u\n", outbuf.len);
186 ok(output.dwStatus == (O_SYNCPOINT | O_INCOMPLETE), "got %#x\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 %#x\n", hr);
195 written = outbuf.len;
196 ok(written > 1152 && written <= 5000, "got %u\n", written);
197 ok(output.dwStatus == (O_SYNCPOINT | O_TIME | O_TIMELENGTH | O_INCOMPLETE),
198 "got %#x\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 %d.\n", inbuf.refcount);
203 ok(outbuf.refcount == 1, "Got refcount %d.\n", inbuf.refcount);
205 hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
206 ok(hr == S_FALSE, "got %#x\n", hr);
207 ok(outbuf.len == written, "expected %u, got %u\n", written, outbuf.len);
208 ok(output.dwStatus == (O_SYNCPOINT | O_INCOMPLETE), "got %#x\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 %#x\n", hr);
215 ok(inbuf.refcount == 2, "Got refcount %d.\n", inbuf.refcount);
216 ok(outbuf.refcount == 1, "Got refcount %d.\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 %#x\n", hr);
223 ok(written + outbuf.len == (1152 * 5) ||
224 broken(written + outbuf.len == (1152 * 5) - 528), /* Win10 */
225 "got %u, total %u\n", outbuf.len, written + outbuf.len);
226 ok(output.dwStatus == (O_SYNCPOINT | O_TIME | O_TIMELENGTH), "got %#x\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 %d.\n", inbuf.refcount);
232 ok(outbuf.refcount == 1, "Got refcount %d.\n", inbuf.refcount);
233 written += outbuf.len;
235 hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
236 ok(hr == S_FALSE, "got %#x\n", hr);
237 ok(output.dwStatus == 0, "got %#x\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 %#x.\n", hr);
245 ok(!output.pBuffer, "Got buffer %p.\n", output.pBuffer);
246 ok(!output.dwStatus, "Got status %#x.\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 %#x\n", hr);
253 hr = IMediaObject_ProcessInput(dmo, 0, &inbuf.IMediaBuffer_iface, 0, 0, 0);
254 ok(hr == DMO_E_NOTACCEPTING, "Got hr %#x.\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 %#x.\n", hr);
262 ok(!output.pBuffer, "Got buffer %p.\n", output.pBuffer);
263 ok(output.dwStatus == O_INCOMPLETE, "Got status %#x.\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 %d.\n", inbuf.refcount);
268 hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
269 ok(hr == S_OK, "Got hr %#x.\n", hr);
270 ok(!output.pBuffer, "Got buffer %p.\n", output.pBuffer);
271 ok(output.dwStatus == O_INCOMPLETE, "Got status %#x.\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 %d.\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 %#x.\n", hr);
281 ok(outbuf.len > 1152 && outbuf.len <= 5000, "Got length %u.\n", outbuf.len);
282 ok(output.dwStatus == (O_SYNCPOINT | O_TIME | O_TIMELENGTH | O_INCOMPLETE),
283 "Got status %#x.\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 %d.\n", inbuf.refcount);
289 ok(outbuf.refcount == 1, "Got refcount %d.\n", inbuf.refcount);
291 hr = IMediaObject_Flush(dmo);
292 ok(hr == S_OK, "Got hr %#x.\n", hr);
293 ok(inbuf.refcount == 1, "Got refcount %d.\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 %#x.\n", hr);
300 hr = IMediaObject_Flush(dmo);
301 ok(hr == S_OK, "Got hr %#x.\n", hr);
303 hr = IMediaObject_ProcessInput(dmo, 0, &inbuf.IMediaBuffer_iface, 0, 0, 0);
304 ok(hr == S_OK, "got %#x\n", hr);
306 hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
307 ok(hr == S_OK, "Got hr %#x.\n", hr);
308 ok(outbuf.len > 1152 && outbuf.len <= 5000, "Got length %u.\n", outbuf.len);
309 ok(output.dwStatus == (O_SYNCPOINT | O_TIME | O_TIMELENGTH | O_INCOMPLETE),
310 "Got status %#x.\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 %d.\n", inbuf.refcount);
315 ok(outbuf.refcount == 1, "Got refcount %d.\n", inbuf.refcount);
317 IMediaObject_Release(dmo);
318 ok(inbuf.refcount == 1, "Got outstanding refcount %d.\n", inbuf.refcount);
319 ok(outbuf.refcount == 1, "Got outstanding refcount %d.\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 %#x\n", hr);
363 hr = IUnknown_QueryInterface(unk, &IID_IMediaObject, (void **)&dmo);
364 ok(hr == S_OK, "got %#x\n", hr);
366 hr = IMediaObject_QueryInterface(dmo, &IID_test_outer, (void **)&unk2);
367 ok(hr == S_OK, "got %#x\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 %#x\n", hr);
378 static void test_stream_info(void)
380 static const MPEGLAYER3WAVEFORMAT input_format =
382 .wfx.nChannels = 2,
383 .wfx.nSamplesPerSec = 48000,
385 DMO_MEDIA_TYPE input_mt =
387 .majortype = MEDIATYPE_Audio,
388 .subtype = WMMEDIASUBTYPE_MP3,
389 .formattype = FORMAT_WaveFormatEx,
390 .cbFormat = sizeof(input_format),
391 .pbFormat = (BYTE *)&input_format,
394 static const WAVEFORMATEX output_format =
396 .nChannels = 1,
397 .nSamplesPerSec = 48000,
398 .nAvgBytesPerSec = 2 * 48000,
399 .nBlockAlign = 2,
400 .wBitsPerSample = 16,
402 DMO_MEDIA_TYPE output_mt =
404 .formattype = FORMAT_WaveFormatEx,
405 .cbFormat = sizeof(output_format),
406 .pbFormat = (BYTE *)&output_format,
409 DWORD input_count, output_count, flags, size, lookahead, alignment;
410 IMediaObject *dmo;
411 HRESULT hr;
413 hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, NULL, CLSCTX_INPROC_SERVER,
414 &IID_IMediaObject, (void **)&dmo);
415 ok(hr == S_OK, "Got hr %#x.\n", hr);
417 hr = IMediaObject_GetStreamCount(dmo, &input_count, &output_count);
418 ok(hr == S_OK, "Got hr %#x.\n", hr);
419 ok(input_count == 1, "Got input count %u.\n", input_count);
420 ok(output_count == 1, "Got output count %u.\n", output_count);
422 flags = 0xdeadbeef;
423 hr = IMediaObject_GetInputStreamInfo(dmo, 0, &flags);
424 ok(hr == S_OK, "Got hr %#x.\n", hr);
425 ok(!flags, "Got flags %#x.\n", flags);
427 flags = 0xdeadbeef;
428 hr = IMediaObject_GetOutputStreamInfo(dmo, 0, &flags);
429 ok(hr == S_OK, "Got hr %#x.\n", hr);
430 ok(!flags, "Got flags %#x.\n", flags);
432 hr = IMediaObject_GetInputSizeInfo(dmo, 0, &size, &lookahead, &alignment);
433 ok(hr == DMO_E_TYPE_NOT_SET, "Got hr %#x.\n", hr);
434 hr = IMediaObject_GetOutputSizeInfo(dmo, 0, &size, &alignment);
435 ok(hr == DMO_E_TYPE_NOT_SET, "Got hr %#x.\n", hr);
437 hr = IMediaObject_SetInputType(dmo, 0, &input_mt, 0);
438 ok(hr == S_OK, "Got hr %#x.\n", hr);
440 hr = IMediaObject_GetInputSizeInfo(dmo, 0, &size, &lookahead, &alignment);
441 ok(hr == DMO_E_TYPE_NOT_SET, "Got hr %#x.\n", hr);
442 hr = IMediaObject_GetOutputSizeInfo(dmo, 0, &size, &alignment);
443 ok(hr == DMO_E_TYPE_NOT_SET, "Got hr %#x.\n", hr);
445 hr = IMediaObject_SetOutputType(dmo, 0, &output_mt, 0);
446 ok(hr == S_OK, "Got hr %#x.\n", hr);
448 size = lookahead = alignment = 0xdeadbeef;
449 hr = IMediaObject_GetInputSizeInfo(dmo, 0, &size, &lookahead, &alignment);
450 ok(hr == S_OK, "Got hr %#x.\n", hr);
451 ok(!size, "Got size %u.\n", size);
452 ok(lookahead == 0xdeadbeef, "Got lookahead %u.\n", lookahead);
453 ok(alignment == 1, "Got alignment %u.\n", alignment);
455 size = alignment = 0xdeadbeef;
456 hr = IMediaObject_GetOutputSizeInfo(dmo, 0, &size, &alignment);
457 ok(hr == S_OK, "Got hr %#x.\n", hr);
458 ok(size == 1152 * 4, "Got size %u.\n", size);
459 ok(alignment == 1, "Got alignment %u.\n", alignment);
461 IMediaObject_Release(dmo);
464 static void test_media_types(void)
466 MPEGLAYER3WAVEFORMAT mp3fmt =
468 .wfx.nChannels = 2,
469 .wfx.nSamplesPerSec = 48000,
471 DMO_MEDIA_TYPE input_mt =
473 .majortype = MEDIATYPE_Audio,
474 .subtype = WMMEDIASUBTYPE_MP3,
475 .formattype = FORMAT_WaveFormatEx,
476 .cbFormat = sizeof(mp3fmt),
477 .pbFormat = (BYTE *)&mp3fmt,
480 WAVEFORMATEX expect_wfx =
482 .wFormatTag = WAVE_FORMAT_PCM,
483 .nSamplesPerSec = 48000,
486 WAVEFORMATEX output_format =
488 .nChannels = 1,
489 .nSamplesPerSec = 48000,
490 .nAvgBytesPerSec = 48000,
491 .nBlockAlign = 1,
492 .wBitsPerSample = 8,
494 DMO_MEDIA_TYPE output_mt =
496 .formattype = FORMAT_WaveFormatEx,
497 .cbFormat = sizeof(output_format),
498 .pbFormat = (BYTE *)&output_format,
501 DMO_MEDIA_TYPE mt;
502 IMediaObject *dmo;
503 HRESULT hr;
504 DWORD i;
506 hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, NULL, CLSCTX_INPROC_SERVER,
507 &IID_IMediaObject, (void **)&dmo);
508 ok(hr == S_OK, "Got hr %#x.\n", hr);
510 memset(&mt, 0xcc, sizeof(DMO_MEDIA_TYPE));
511 hr = IMediaObject_GetInputType(dmo, 0, 0, &mt);
512 ok(hr == S_OK, "Got hr %#x.\n", hr);
513 ok(IsEqualGUID(&mt.majortype, &MEDIATYPE_Audio), "Got major type %s.\n", wine_dbgstr_guid(&mt.majortype));
514 ok(IsEqualGUID(&mt.subtype, &WMMEDIASUBTYPE_MP3), "Got subtype %s.\n", wine_dbgstr_guid(&mt.subtype));
515 ok(mt.bFixedSizeSamples == 0xcccccccc, "Got fixed size %d.\n", mt.bFixedSizeSamples);
516 ok(mt.bTemporalCompression == 0xcccccccc, "Got temporal compression %d.\n", mt.bTemporalCompression);
517 ok(mt.lSampleSize == 0xcccccccc, "Got sample size %u.\n", mt.lSampleSize);
518 ok(IsEqualGUID(&mt.formattype, &GUID_NULL), "Got format type %s.\n",
519 wine_dbgstr_guid(&mt.formattype));
520 ok(!mt.pUnk, "Got pUnk %p.\n", mt.pUnk);
521 ok(!mt.cbFormat, "Got format size %u.\n", mt.cbFormat);
522 ok(!mt.pbFormat, "Got format block %p.\n", mt.pbFormat);
524 hr = IMediaObject_GetInputType(dmo, 0, 1, &mt);
525 ok(hr == DMO_E_NO_MORE_ITEMS, "Got hr %#x.\n", hr);
527 memset(&mt, 0xcc, sizeof(DMO_MEDIA_TYPE));
528 hr = IMediaObject_GetOutputType(dmo, 0, 0, &mt);
529 ok(hr == DMO_E_TYPE_NOT_SET, "Got hr %#x.\n", hr);
531 hr = IMediaObject_SetInputType(dmo, 0, &input_mt, DMO_SET_TYPEF_TEST_ONLY);
532 ok(hr == S_OK, "Got hr %#x.\n", hr);
534 input_mt.majortype = GUID_NULL;
535 hr = IMediaObject_SetInputType(dmo, 0, &input_mt, DMO_SET_TYPEF_TEST_ONLY);
536 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
537 input_mt.majortype = MEDIATYPE_Stream;
538 hr = IMediaObject_SetInputType(dmo, 0, &input_mt, DMO_SET_TYPEF_TEST_ONLY);
539 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
540 input_mt.majortype = MEDIATYPE_Audio;
542 input_mt.subtype = GUID_NULL;
543 hr = IMediaObject_SetInputType(dmo, 0, &input_mt, DMO_SET_TYPEF_TEST_ONLY);
544 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
545 input_mt.subtype = MEDIASUBTYPE_PCM;
546 hr = IMediaObject_SetInputType(dmo, 0, &input_mt, DMO_SET_TYPEF_TEST_ONLY);
547 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
548 input_mt.subtype = WMMEDIASUBTYPE_MP3;
550 input_mt.formattype = 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 %#x.\n", hr);
553 input_mt.formattype = FORMAT_None;
554 hr = IMediaObject_SetInputType(dmo, 0, &input_mt, DMO_SET_TYPEF_TEST_ONLY);
555 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
556 input_mt.formattype = FORMAT_WaveFormatEx;
558 hr = IMediaObject_SetInputType(dmo, 0, &input_mt, 0);
559 ok(hr == S_OK, "Got hr %#x.\n", hr);
561 for (i = 0; i < 4; ++i)
563 memset(&mt, 0xcc, sizeof(DMO_MEDIA_TYPE));
564 hr = IMediaObject_GetOutputType(dmo, 0, i, &mt);
565 ok(hr == S_OK, "Got hr %#x.\n", hr);
566 ok(IsEqualGUID(&mt.majortype, &MEDIATYPE_Audio), "Got major type %s.\n", wine_dbgstr_guid(&mt.majortype));
567 ok(IsEqualGUID(&mt.subtype, &MEDIASUBTYPE_PCM), "Got subtype %s.\n", wine_dbgstr_guid(&mt.subtype));
568 ok(mt.bFixedSizeSamples == 0xcccccccc, "Got fixed size %d.\n", mt.bFixedSizeSamples);
569 ok(mt.bTemporalCompression == 0xcccccccc, "Got temporal compression %d.\n", mt.bTemporalCompression);
570 ok(mt.lSampleSize == 0xcccccccc, "Got sample size %u.\n", mt.lSampleSize);
571 ok(IsEqualGUID(&mt.formattype, &FORMAT_WaveFormatEx), "Got format type %s.\n",
572 wine_dbgstr_guid(&mt.formattype));
573 ok(!mt.pUnk, "Got pUnk %p.\n", mt.pUnk);
574 ok(mt.cbFormat >= sizeof(WAVEFORMATEX), "Got format size %u.\n", mt.cbFormat);
575 ok(!!mt.pbFormat, "Got format block %p.\n", mt.pbFormat);
577 expect_wfx.nChannels = (i / 2) ? 1 : 2;
578 expect_wfx.wBitsPerSample = (i % 2) ? 8 : 16;
579 expect_wfx.nBlockAlign = expect_wfx.nChannels * expect_wfx.wBitsPerSample / 8;
580 expect_wfx.nAvgBytesPerSec = 48000 * expect_wfx.nBlockAlign;
581 ok(!memcmp(mt.pbFormat, &expect_wfx, sizeof(WAVEFORMATEX)), "Format blocks didn't match.\n");
583 MoFreeMediaType(&mt);
586 hr = IMediaObject_GetOutputType(dmo, 0, 4, &mt);
587 ok(hr == DMO_E_NO_MORE_ITEMS, "Got hr %#x.\n", hr);
589 mp3fmt.wfx.nChannels = 1;
590 hr = IMediaObject_SetInputType(dmo, 0, &input_mt, 0);
591 ok(hr == S_OK, "Got hr %#x.\n", hr);
593 for (i = 0; i < 2; ++i)
595 memset(&mt, 0xcc, sizeof(DMO_MEDIA_TYPE));
596 hr = IMediaObject_GetOutputType(dmo, 0, i, &mt);
597 ok(hr == S_OK, "Got hr %#x.\n", hr);
598 ok(IsEqualGUID(&mt.majortype, &MEDIATYPE_Audio), "Got major type %s.\n", wine_dbgstr_guid(&mt.majortype));
599 ok(IsEqualGUID(&mt.subtype, &MEDIASUBTYPE_PCM), "Got subtype %s.\n", wine_dbgstr_guid(&mt.subtype));
600 ok(mt.bFixedSizeSamples == 0xcccccccc, "Got fixed size %d.\n", mt.bFixedSizeSamples);
601 ok(mt.bTemporalCompression == 0xcccccccc, "Got temporal compression %d.\n", mt.bTemporalCompression);
602 ok(mt.lSampleSize == 0xcccccccc, "Got sample size %u.\n", mt.lSampleSize);
603 ok(IsEqualGUID(&mt.formattype, &FORMAT_WaveFormatEx), "Got format type %s.\n",
604 wine_dbgstr_guid(&mt.formattype));
605 ok(!mt.pUnk, "Got pUnk %p.\n", mt.pUnk);
606 ok(mt.cbFormat >= sizeof(WAVEFORMATEX), "Got format size %u.\n", mt.cbFormat);
607 ok(!!mt.pbFormat, "Got format block %p.\n", mt.pbFormat);
609 expect_wfx.nChannels = 1;
610 expect_wfx.wBitsPerSample = (i % 2) ? 8 : 16;
611 expect_wfx.nBlockAlign = expect_wfx.nChannels * expect_wfx.wBitsPerSample / 8;
612 expect_wfx.nAvgBytesPerSec = 48000 * expect_wfx.nBlockAlign;
613 ok(!memcmp(mt.pbFormat, &expect_wfx, sizeof(WAVEFORMATEX)), "Format blocks didn't match.\n");
615 MoFreeMediaType(&mt);
618 hr = IMediaObject_GetOutputType(dmo, 0, 2, &mt);
619 ok(hr == DMO_E_NO_MORE_ITEMS, "Got hr %#x.\n", hr);
621 hr = IMediaObject_SetOutputType(dmo, 0, &output_mt, DMO_SET_TYPEF_TEST_ONLY);
622 ok(hr == S_OK, "Got hr %#x.\n", hr);
624 output_mt.formattype = GUID_NULL;
625 hr = IMediaObject_SetOutputType(dmo, 0, &output_mt, DMO_SET_TYPEF_TEST_ONLY);
626 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
627 output_mt.formattype = FORMAT_None;
628 hr = IMediaObject_SetOutputType(dmo, 0, &output_mt, DMO_SET_TYPEF_TEST_ONLY);
629 ok(hr == DMO_E_TYPE_NOT_ACCEPTED, "Got hr %#x.\n", hr);
630 output_mt.formattype = FORMAT_WaveFormatEx;
632 IMediaObject_Release(dmo);
635 START_TEST(mp3dmod)
637 IMediaObject *dmo;
638 HRESULT hr;
640 CoInitializeEx(NULL, COINIT_MULTITHREADED);
642 hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, NULL, CLSCTX_INPROC_SERVER,
643 &IID_IMediaObject, (void **)&dmo);
644 if (hr == REGDB_E_CLASSNOTREG)
646 win_skip("CLSID_CMP3DecMediaObject not available\n");
647 return;
649 IMediaObject_Release(dmo);
651 test_convert();
652 test_aggregation();
653 test_stream_info();
654 test_media_types();
656 CoUninitialize();