mp3dmod/tests: Add some tests for decoding.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
3b8ec3046a
commit
cae0e0b6e7
|
@ -18805,6 +18805,7 @@ wine_fn_config_makefile dlls/monodebg.vxd enable_win16
|
||||||
wine_fn_config_makefile dlls/mountmgr.sys enable_mountmgr_sys
|
wine_fn_config_makefile dlls/mountmgr.sys enable_mountmgr_sys
|
||||||
wine_fn_config_makefile dlls/mouse.drv16 enable_win16
|
wine_fn_config_makefile dlls/mouse.drv16 enable_win16
|
||||||
wine_fn_config_makefile dlls/mp3dmod enable_mp3dmod
|
wine_fn_config_makefile dlls/mp3dmod enable_mp3dmod
|
||||||
|
wine_fn_config_makefile dlls/mp3dmod/tests enable_tests
|
||||||
wine_fn_config_makefile dlls/mpr enable_mpr
|
wine_fn_config_makefile dlls/mpr enable_mpr
|
||||||
wine_fn_config_makefile dlls/mpr/tests enable_tests
|
wine_fn_config_makefile dlls/mpr/tests enable_tests
|
||||||
wine_fn_config_makefile dlls/mprapi enable_mprapi
|
wine_fn_config_makefile dlls/mprapi enable_mprapi
|
||||||
|
|
|
@ -3401,6 +3401,7 @@ WINE_CONFIG_MAKEFILE(dlls/monodebg.vxd,enable_win16)
|
||||||
WINE_CONFIG_MAKEFILE(dlls/mountmgr.sys)
|
WINE_CONFIG_MAKEFILE(dlls/mountmgr.sys)
|
||||||
WINE_CONFIG_MAKEFILE(dlls/mouse.drv16,enable_win16)
|
WINE_CONFIG_MAKEFILE(dlls/mouse.drv16,enable_win16)
|
||||||
WINE_CONFIG_MAKEFILE(dlls/mp3dmod)
|
WINE_CONFIG_MAKEFILE(dlls/mp3dmod)
|
||||||
|
WINE_CONFIG_MAKEFILE(dlls/mp3dmod/tests)
|
||||||
WINE_CONFIG_MAKEFILE(dlls/mpr)
|
WINE_CONFIG_MAKEFILE(dlls/mpr)
|
||||||
WINE_CONFIG_MAKEFILE(dlls/mpr/tests)
|
WINE_CONFIG_MAKEFILE(dlls/mpr/tests)
|
||||||
WINE_CONFIG_MAKEFILE(dlls/mprapi)
|
WINE_CONFIG_MAKEFILE(dlls/mprapi)
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
TESTDLL = mp3dmod.dll
|
||||||
|
IMPORTS = dmoguids ole32 strmiids uuid wmcodecdspuuid
|
||||||
|
|
||||||
|
C_SRCS = \
|
||||||
|
mp3dmod.c
|
|
@ -0,0 +1,233 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2018 Zebediah Figura
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define COBJMACROS
|
||||||
|
#include "windef.h"
|
||||||
|
#include "wingdi.h"
|
||||||
|
#include "mmreg.h"
|
||||||
|
#include "mmsystem.h"
|
||||||
|
#include "mediaerr.h"
|
||||||
|
#include "wmcodecdsp.h"
|
||||||
|
#include "uuids.h"
|
||||||
|
#include "wine/test.h"
|
||||||
|
|
||||||
|
#include "initguid.h"
|
||||||
|
DEFINE_GUID(WMMEDIASUBTYPE_MP3, 0x00000055, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
|
||||||
|
|
||||||
|
/* shorter aliases for flags */
|
||||||
|
#define O_SYNCPOINT DMO_OUTPUT_DATA_BUFFERF_SYNCPOINT
|
||||||
|
#define O_TIME DMO_OUTPUT_DATA_BUFFERF_TIME
|
||||||
|
#define O_TIMELENGTH DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH
|
||||||
|
#define O_INCOMPLETE DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE
|
||||||
|
|
||||||
|
struct test_buffer {
|
||||||
|
IMediaBuffer IMediaBuffer_iface;
|
||||||
|
BYTE data[5000];
|
||||||
|
DWORD len;
|
||||||
|
DWORD maxlen;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct test_buffer *impl_from_IMediaBuffer(IMediaBuffer *iface)
|
||||||
|
{
|
||||||
|
return CONTAINING_RECORD(iface, struct test_buffer, IMediaBuffer_iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI Buffer_QueryInterface(IMediaBuffer *iface, REFIID iid, void **obj)
|
||||||
|
{
|
||||||
|
if (IsEqualIID(iid, &IID_IMediaBuffer) || IsEqualIID(iid, &IID_IUnknown))
|
||||||
|
{
|
||||||
|
*obj = iface;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
ok(0, "Unexpected IID %s\n", wine_dbgstr_guid(iid));
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI Buffer_AddRef(IMediaBuffer *iface)
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI Buffer_Release(IMediaBuffer *iface)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI Buffer_SetLength(IMediaBuffer *iface, DWORD len)
|
||||||
|
{
|
||||||
|
struct test_buffer *This = impl_from_IMediaBuffer(iface);
|
||||||
|
This->len = len;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI Buffer_GetMaxLength(IMediaBuffer *iface, DWORD *len)
|
||||||
|
{
|
||||||
|
struct test_buffer *This = impl_from_IMediaBuffer(iface);
|
||||||
|
*len = This->maxlen;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI Buffer_GetBufferAndLength(IMediaBuffer *iface, BYTE **buf, DWORD *len)
|
||||||
|
{
|
||||||
|
struct test_buffer *This = impl_from_IMediaBuffer(iface);
|
||||||
|
if (buf) *buf = This->data;
|
||||||
|
if (len) *len = This->len;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static IMediaBufferVtbl Buffer_vtbl = {
|
||||||
|
Buffer_QueryInterface,
|
||||||
|
Buffer_AddRef,
|
||||||
|
Buffer_Release,
|
||||||
|
Buffer_SetLength,
|
||||||
|
Buffer_GetMaxLength,
|
||||||
|
Buffer_GetBufferAndLength,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void test_convert(void)
|
||||||
|
{
|
||||||
|
static const BYTE mp3hdr[] = {0xff,0xfb,0x14,0xc4};
|
||||||
|
struct test_buffer outbuf = {{&Buffer_vtbl}};
|
||||||
|
struct test_buffer inbuf = {{&Buffer_vtbl}};
|
||||||
|
DMO_MEDIA_TYPE in = {{0}}, out = {{0}};
|
||||||
|
MPEGLAYER3WAVEFORMAT mp3fmt = {{0}};
|
||||||
|
DMO_OUTPUT_DATA_BUFFER output;
|
||||||
|
WAVEFORMATEX wavfmt = {0};
|
||||||
|
IMediaObject *dmo;
|
||||||
|
DWORD written;
|
||||||
|
DWORD status;
|
||||||
|
HRESULT hr;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, NULL, CLSCTX_INPROC_SERVER,
|
||||||
|
&IID_IMediaObject, (void **)&dmo);
|
||||||
|
ok(hr == S_OK, "got %#x\n", hr);
|
||||||
|
|
||||||
|
mp3fmt.wfx.wFormatTag = WAVE_FORMAT_MPEGLAYER3;
|
||||||
|
mp3fmt.wfx.nChannels = 2;
|
||||||
|
mp3fmt.wfx.nSamplesPerSec = 48000;
|
||||||
|
in.majortype = MEDIATYPE_Audio;
|
||||||
|
in.subtype = WMMEDIASUBTYPE_MP3;
|
||||||
|
in.formattype = FORMAT_WaveFormatEx;
|
||||||
|
in.cbFormat = sizeof(mp3fmt);
|
||||||
|
in.pbFormat = (BYTE *)&mp3fmt;
|
||||||
|
|
||||||
|
hr = IMediaObject_SetInputType(dmo, 0, &in, 0);
|
||||||
|
ok(hr == S_OK, "got %#x\n", hr);
|
||||||
|
|
||||||
|
wavfmt.wFormatTag = WAVE_FORMAT_PCM;
|
||||||
|
wavfmt.nChannels = 1;
|
||||||
|
wavfmt.nSamplesPerSec = 48000;
|
||||||
|
wavfmt.nAvgBytesPerSec = 48000 * ((1 * 8) / 8);
|
||||||
|
wavfmt.nBlockAlign = (1 * 8) / 8;
|
||||||
|
wavfmt.wBitsPerSample = 8;
|
||||||
|
out.majortype = MEDIATYPE_Audio;
|
||||||
|
out.subtype = MEDIASUBTYPE_PCM;
|
||||||
|
out.formattype = FORMAT_WaveFormatEx;
|
||||||
|
out.cbFormat = sizeof(wavfmt);
|
||||||
|
out.pbFormat = (BYTE *)&wavfmt;
|
||||||
|
|
||||||
|
hr = IMediaObject_SetOutputType(dmo, 0, &out, 0);
|
||||||
|
ok(hr == S_OK, "got %#x\n", hr);
|
||||||
|
|
||||||
|
outbuf.len = 0;
|
||||||
|
outbuf.maxlen = sizeof(outbuf.data);
|
||||||
|
output.pBuffer = &outbuf.IMediaBuffer_iface;
|
||||||
|
output.dwStatus = 0xdeadbeef;
|
||||||
|
hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
|
||||||
|
ok(hr == S_FALSE, "got %#x\n", hr);
|
||||||
|
ok(outbuf.len == 0, "got %u\n", outbuf.len);
|
||||||
|
ok(output.dwStatus == 0, "got %#x\n", output.dwStatus);
|
||||||
|
|
||||||
|
/* write several frames of mp3 data */
|
||||||
|
for (i = 0; i < 5; i++)
|
||||||
|
memcpy(inbuf.data + 96 * i, mp3hdr, 4);
|
||||||
|
inbuf.len = 96 * 5;
|
||||||
|
hr = IMediaObject_ProcessInput(dmo, 0, &inbuf.IMediaBuffer_iface, 0, 0, 0);
|
||||||
|
ok(hr == S_OK, "got %#x\n", hr);
|
||||||
|
|
||||||
|
hr = IMediaObject_ProcessInput(dmo, 0, &inbuf.IMediaBuffer_iface, 0, 0, 0);
|
||||||
|
ok(hr == DMO_E_NOTACCEPTING, "got %#x\n", hr);
|
||||||
|
|
||||||
|
outbuf.len = 0;
|
||||||
|
outbuf.maxlen = 0;
|
||||||
|
hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
|
||||||
|
ok(hr == S_FALSE, "got %#x\n", hr);
|
||||||
|
ok(outbuf.len == 0, "got %u\n", outbuf.len);
|
||||||
|
ok(output.dwStatus == (O_SYNCPOINT | O_INCOMPLETE), "got %#x\n", output.dwStatus);
|
||||||
|
|
||||||
|
/* implementations are inconsistent, but should write at least one frame of data */
|
||||||
|
outbuf.len = 0;
|
||||||
|
outbuf.maxlen = 5000;
|
||||||
|
hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
|
||||||
|
ok(hr == S_OK, "got %#x\n", hr);
|
||||||
|
written = outbuf.len;
|
||||||
|
ok(written > 1152 && written <= 5000, "got %u\n", written);
|
||||||
|
todo_wine
|
||||||
|
ok(output.dwStatus == (O_SYNCPOINT | O_TIME | O_TIMELENGTH | O_INCOMPLETE),
|
||||||
|
"got %#x\n", output.dwStatus);
|
||||||
|
|
||||||
|
hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
|
||||||
|
ok(hr == S_FALSE, "got %#x\n", hr);
|
||||||
|
ok(outbuf.len == written, "expected %u, got %u\n", written, outbuf.len);
|
||||||
|
ok(output.dwStatus == (O_SYNCPOINT | O_INCOMPLETE), "got %#x\n", output.dwStatus);
|
||||||
|
|
||||||
|
hr = IMediaObject_ProcessInput(dmo, 0, &inbuf.IMediaBuffer_iface, 0, 0, 0);
|
||||||
|
ok(hr == DMO_E_NOTACCEPTING, "got %#x\n", hr);
|
||||||
|
|
||||||
|
/* write the rest */
|
||||||
|
outbuf.len = 0;
|
||||||
|
outbuf.maxlen = 5000;
|
||||||
|
hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
|
||||||
|
ok(hr == S_OK, "got %#x\n", hr);
|
||||||
|
ok(written + outbuf.len == (1152 * 5) ||
|
||||||
|
broken(written + outbuf.len == (1152 * 5) - 528), /* Win10 */
|
||||||
|
"got %u, total %u\n", outbuf.len, written + outbuf.len);
|
||||||
|
todo_wine
|
||||||
|
ok(output.dwStatus == (O_SYNCPOINT | O_TIME | O_TIMELENGTH), "got %#x\n", output.dwStatus);
|
||||||
|
|
||||||
|
hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
|
||||||
|
ok(hr == S_FALSE, "got %#x\n", hr);
|
||||||
|
ok(output.dwStatus == 0, "got %#x\n", output.dwStatus);
|
||||||
|
|
||||||
|
hr = IMediaObject_ProcessInput(dmo, 0, &inbuf.IMediaBuffer_iface, 0, 0, 0);
|
||||||
|
ok(hr == S_OK, "got %#x\n", hr);
|
||||||
|
|
||||||
|
IMediaObject_Release(dmo);
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(mp3dmod)
|
||||||
|
{
|
||||||
|
IMediaObject *dmo;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||||
|
|
||||||
|
hr = CoCreateInstance(&CLSID_CMP3DecMediaObject, NULL, CLSCTX_INPROC_SERVER,
|
||||||
|
&IID_IMediaObject, (void **)&dmo);
|
||||||
|
if (hr == REGDB_E_CLASSNOTREG)
|
||||||
|
{
|
||||||
|
win_skip("CLSID_CMP3DecMediaObject not available\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
IMediaObject_Release(dmo);
|
||||||
|
|
||||||
|
test_convert();
|
||||||
|
|
||||||
|
CoUninitialize();
|
||||||
|
}
|
Loading…
Reference in New Issue