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
25 #include "wmcodecdsp.h"
27 #include "wine/test.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
;
45 IMediaBuffer IMediaBuffer_iface
;
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
))
64 ok(0, "Unexpected IID %s\n", wine_dbgstr_guid(iid
));
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
);
87 static HRESULT WINAPI
Buffer_GetMaxLength(IMediaBuffer
*iface
, DWORD
*len
)
89 struct test_buffer
*This
= impl_from_IMediaBuffer(iface
);
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
;
102 static IMediaBufferVtbl Buffer_vtbl
= {
103 Buffer_QueryInterface
,
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};
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
);
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);
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
);
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 */
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
);
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
;
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
);
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;
331 ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid
));
332 return E_NOINTERFACE
;
335 static ULONG WINAPI
Outer_AddRef(IUnknown
*iface
)
340 static ULONG WINAPI
Outer_Release(IUnknown
*iface
)
345 static IUnknownVtbl Outer_vtbl
= {
346 Outer_QueryInterface
,
351 static IUnknown Outer
= { &Outer_vtbl
};
353 static void test_aggregation(void)
355 IUnknown
*unk
, *unk2
;
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
=
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
=
397 .nSamplesPerSec
= 48000,
398 .nAvgBytesPerSec
= 2 * 48000,
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
;
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
);
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
);
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
=
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
=
489 .nSamplesPerSec
= 48000,
490 .nAvgBytesPerSec
= 48000,
494 DMO_MEDIA_TYPE output_mt
=
496 .formattype
= FORMAT_WaveFormatEx
,
497 .cbFormat
= sizeof(output_format
),
498 .pbFormat
= (BYTE
*)&output_format
,
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
);
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");
649 IMediaObject_Release(dmo
);