forked from Mirrors/wine-wine
mp3dmod: Return timestamp and length from ProcessOutput().
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>oldstable
parent
cae0e0b6e7
commit
e1b4aa542e
|
@ -43,6 +43,7 @@ struct mp3_decoder {
|
||||||
mpg123_handle *mh;
|
mpg123_handle *mh;
|
||||||
DMO_MEDIA_TYPE outtype;
|
DMO_MEDIA_TYPE outtype;
|
||||||
IMediaBuffer *buffer;
|
IMediaBuffer *buffer;
|
||||||
|
REFERENCE_TIME timestamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct mp3_decoder *impl_from_IMediaObject(IMediaObject *iface)
|
static inline struct mp3_decoder *impl_from_IMediaObject(IMediaObject *iface)
|
||||||
|
@ -296,9 +297,16 @@ static DWORD get_framesize(DMO_MEDIA_TYPE *type)
|
||||||
return 1152 * format->nBlockAlign;
|
return 1152 * format->nBlockAlign;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static REFERENCE_TIME get_frametime(DMO_MEDIA_TYPE *type)
|
||||||
|
{
|
||||||
|
WAVEFORMATEX *format = (WAVEFORMATEX *)type->pbFormat;
|
||||||
|
return (REFERENCE_TIME) 10000000 * 1152 / format->nSamplesPerSec;
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI MediaObject_ProcessOutput(IMediaObject *iface, DWORD flags, DWORD count, DMO_OUTPUT_DATA_BUFFER *buffers, DWORD *status)
|
static HRESULT WINAPI MediaObject_ProcessOutput(IMediaObject *iface, DWORD flags, DWORD count, DMO_OUTPUT_DATA_BUFFER *buffers, DWORD *status)
|
||||||
{
|
{
|
||||||
struct mp3_decoder *This = impl_from_IMediaObject(iface);
|
struct mp3_decoder *This = impl_from_IMediaObject(iface);
|
||||||
|
REFERENCE_TIME time = 0, frametime;
|
||||||
DWORD len, maxlen, framesize;
|
DWORD len, maxlen, framesize;
|
||||||
int got_data = 0;
|
int got_data = 0;
|
||||||
size_t written;
|
size_t written;
|
||||||
|
@ -325,6 +333,7 @@ static HRESULT WINAPI MediaObject_ProcessOutput(IMediaObject *iface, DWORD flags
|
||||||
if (FAILED(hr)) return hr;
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
framesize = get_framesize(&This->outtype);
|
framesize = get_framesize(&This->outtype);
|
||||||
|
frametime = get_frametime(&This->outtype);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
@ -353,10 +362,16 @@ static HRESULT WINAPI MediaObject_ProcessOutput(IMediaObject *iface, DWORD flags
|
||||||
len += framesize;
|
len += framesize;
|
||||||
hr = IMediaBuffer_SetLength(buffers[0].pBuffer, len);
|
hr = IMediaBuffer_SetLength(buffers[0].pBuffer, len);
|
||||||
if (FAILED(hr)) return hr;
|
if (FAILED(hr)) return hr;
|
||||||
|
|
||||||
|
time += frametime;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (got_data)
|
if (got_data)
|
||||||
{
|
{
|
||||||
|
buffers[0].dwStatus |= (DMO_OUTPUT_DATA_BUFFERF_TIME | DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH);
|
||||||
|
buffers[0].rtTimelength = time;
|
||||||
|
buffers[0].rtTimestamp = This->timestamp;
|
||||||
|
This->timestamp += time;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
|
|
@ -35,6 +35,11 @@ DEFINE_GUID(WMMEDIASUBTYPE_MP3, 0x00000055, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0x
|
||||||
#define O_TIMELENGTH DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH
|
#define O_TIMELENGTH DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH
|
||||||
#define O_INCOMPLETE DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE
|
#define O_INCOMPLETE DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE
|
||||||
|
|
||||||
|
static REFERENCE_TIME samplelen(DWORD samples, int rate)
|
||||||
|
{
|
||||||
|
return (REFERENCE_TIME) 10000000 * samples / rate;
|
||||||
|
}
|
||||||
|
|
||||||
struct test_buffer {
|
struct test_buffer {
|
||||||
IMediaBuffer IMediaBuffer_iface;
|
IMediaBuffer IMediaBuffer_iface;
|
||||||
BYTE data[5000];
|
BYTE data[5000];
|
||||||
|
@ -149,10 +154,14 @@ static void test_convert(void)
|
||||||
outbuf.maxlen = sizeof(outbuf.data);
|
outbuf.maxlen = sizeof(outbuf.data);
|
||||||
output.pBuffer = &outbuf.IMediaBuffer_iface;
|
output.pBuffer = &outbuf.IMediaBuffer_iface;
|
||||||
output.dwStatus = 0xdeadbeef;
|
output.dwStatus = 0xdeadbeef;
|
||||||
|
output.rtTimestamp = 0xdeadbeef;
|
||||||
|
output.rtTimelength = 0xdeadbeef;
|
||||||
hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
|
hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
|
||||||
ok(hr == S_FALSE, "got %#x\n", hr);
|
ok(hr == S_FALSE, "got %#x\n", hr);
|
||||||
ok(outbuf.len == 0, "got %u\n", outbuf.len);
|
ok(outbuf.len == 0, "got %u\n", outbuf.len);
|
||||||
ok(output.dwStatus == 0, "got %#x\n", output.dwStatus);
|
ok(output.dwStatus == 0, "got %#x\n", output.dwStatus);
|
||||||
|
ok(output.rtTimestamp == 0xdeadbeef, "got %s\n", wine_dbgstr_longlong(output.rtTimestamp));
|
||||||
|
ok(output.rtTimelength == 0xdeadbeef, "got %s\n", wine_dbgstr_longlong(output.rtTimelength));
|
||||||
|
|
||||||
/* write several frames of mp3 data */
|
/* write several frames of mp3 data */
|
||||||
for (i = 0; i < 5; i++)
|
for (i = 0; i < 5; i++)
|
||||||
|
@ -170,6 +179,8 @@ static void test_convert(void)
|
||||||
ok(hr == S_FALSE, "got %#x\n", hr);
|
ok(hr == S_FALSE, "got %#x\n", hr);
|
||||||
ok(outbuf.len == 0, "got %u\n", outbuf.len);
|
ok(outbuf.len == 0, "got %u\n", outbuf.len);
|
||||||
ok(output.dwStatus == (O_SYNCPOINT | O_INCOMPLETE), "got %#x\n", output.dwStatus);
|
ok(output.dwStatus == (O_SYNCPOINT | O_INCOMPLETE), "got %#x\n", output.dwStatus);
|
||||||
|
ok(output.rtTimestamp == 0xdeadbeef, "got %s\n", wine_dbgstr_longlong(output.rtTimestamp));
|
||||||
|
ok(output.rtTimelength == 0xdeadbeef, "got %s\n", wine_dbgstr_longlong(output.rtTimelength));
|
||||||
|
|
||||||
/* implementations are inconsistent, but should write at least one frame of data */
|
/* implementations are inconsistent, but should write at least one frame of data */
|
||||||
outbuf.len = 0;
|
outbuf.len = 0;
|
||||||
|
@ -178,14 +189,19 @@ static void test_convert(void)
|
||||||
ok(hr == S_OK, "got %#x\n", hr);
|
ok(hr == S_OK, "got %#x\n", hr);
|
||||||
written = outbuf.len;
|
written = outbuf.len;
|
||||||
ok(written > 1152 && written <= 5000, "got %u\n", written);
|
ok(written > 1152 && written <= 5000, "got %u\n", written);
|
||||||
todo_wine
|
|
||||||
ok(output.dwStatus == (O_SYNCPOINT | O_TIME | O_TIMELENGTH | O_INCOMPLETE),
|
ok(output.dwStatus == (O_SYNCPOINT | O_TIME | O_TIMELENGTH | O_INCOMPLETE),
|
||||||
"got %#x\n", output.dwStatus);
|
"got %#x\n", output.dwStatus);
|
||||||
|
ok(output.rtTimestamp == 0, "got %s\n", wine_dbgstr_longlong(output.rtTimestamp));
|
||||||
|
ok(output.rtTimelength == samplelen(written, 48000),
|
||||||
|
"got %s\n", wine_dbgstr_longlong(output.rtTimelength));
|
||||||
|
|
||||||
hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
|
hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
|
||||||
ok(hr == S_FALSE, "got %#x\n", hr);
|
ok(hr == S_FALSE, "got %#x\n", hr);
|
||||||
ok(outbuf.len == written, "expected %u, got %u\n", written, outbuf.len);
|
ok(outbuf.len == written, "expected %u, got %u\n", written, outbuf.len);
|
||||||
ok(output.dwStatus == (O_SYNCPOINT | O_INCOMPLETE), "got %#x\n", output.dwStatus);
|
ok(output.dwStatus == (O_SYNCPOINT | O_INCOMPLETE), "got %#x\n", output.dwStatus);
|
||||||
|
ok(output.rtTimestamp == 0, "got %s\n", wine_dbgstr_longlong(output.rtTimestamp));
|
||||||
|
ok(output.rtTimelength == samplelen(written, 48000),
|
||||||
|
"got %s\n", wine_dbgstr_longlong(output.rtTimelength));
|
||||||
|
|
||||||
hr = IMediaObject_ProcessInput(dmo, 0, &inbuf.IMediaBuffer_iface, 0, 0, 0);
|
hr = IMediaObject_ProcessInput(dmo, 0, &inbuf.IMediaBuffer_iface, 0, 0, 0);
|
||||||
ok(hr == DMO_E_NOTACCEPTING, "got %#x\n", hr);
|
ok(hr == DMO_E_NOTACCEPTING, "got %#x\n", hr);
|
||||||
|
@ -198,8 +214,11 @@ todo_wine
|
||||||
ok(written + outbuf.len == (1152 * 5) ||
|
ok(written + outbuf.len == (1152 * 5) ||
|
||||||
broken(written + outbuf.len == (1152 * 5) - 528), /* Win10 */
|
broken(written + outbuf.len == (1152 * 5) - 528), /* Win10 */
|
||||||
"got %u, total %u\n", outbuf.len, written + outbuf.len);
|
"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);
|
ok(output.dwStatus == (O_SYNCPOINT | O_TIME | O_TIMELENGTH), "got %#x\n", output.dwStatus);
|
||||||
|
ok(output.rtTimestamp == samplelen(written, 48000),
|
||||||
|
"got %s\n", wine_dbgstr_longlong(output.rtTimestamp));
|
||||||
|
ok(output.rtTimelength == samplelen(outbuf.len, 48000),
|
||||||
|
"got %s\n", wine_dbgstr_longlong(output.rtTimelength));
|
||||||
|
|
||||||
hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
|
hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status);
|
||||||
ok(hr == S_FALSE, "got %#x\n", hr);
|
ok(hr == S_FALSE, "got %#x\n", hr);
|
||||||
|
|
Loading…
Reference in New Issue