Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/mp3dmod/mp3dmod.c | 15 +++++++++++++++ dlls/mp3dmod/tests/mp3dmod.c | 26 +++++++++++++++++++++++--- 2 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/dlls/mp3dmod/mp3dmod.c b/dlls/mp3dmod/mp3dmod.c index 0d97909..cdc8fa3 100644 --- a/dlls/mp3dmod/mp3dmod.c +++ b/dlls/mp3dmod/mp3dmod.c @@ -43,6 +43,7 @@ struct mp3_decoder { mpg123_handle *mh; DMO_MEDIA_TYPE outtype; IMediaBuffer *buffer; + REFERENCE_TIME timestamp; };
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; }
+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) { struct mp3_decoder *This = impl_from_IMediaObject(iface); + REFERENCE_TIME time = 0, frametime; DWORD len, maxlen, framesize; int got_data = 0; size_t written; @@ -325,6 +333,7 @@ static HRESULT WINAPI MediaObject_ProcessOutput(IMediaObject *iface, DWORD flags if (FAILED(hr)) return hr;
framesize = get_framesize(&This->outtype); + frametime = get_frametime(&This->outtype);
while (1) { @@ -353,10 +362,16 @@ static HRESULT WINAPI MediaObject_ProcessOutput(IMediaObject *iface, DWORD flags len += framesize; hr = IMediaBuffer_SetLength(buffers[0].pBuffer, len); if (FAILED(hr)) return hr; + + time += frametime; }
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_FALSE; diff --git a/dlls/mp3dmod/tests/mp3dmod.c b/dlls/mp3dmod/tests/mp3dmod.c index efa77de..c0aa32f 100644 --- a/dlls/mp3dmod/tests/mp3dmod.c +++ b/dlls/mp3dmod/tests/mp3dmod.c @@ -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_INCOMPLETE DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE
+static REFERENCE_TIME framelen(int frames, int rate) +{ + return (REFERENCE_TIME) frames * 10000000 * 1152 / rate; +} + struct test_buffer { IMediaBuffer IMediaBuffer_iface; BYTE data[1152 * 2 * 3]; @@ -147,10 +152,14 @@ static void test_convert(void) outbuf.maxlen = sizeof(outbuf.data); output.pBuffer = &outbuf.IMediaBuffer_iface; output.dwStatus = 0xdeadbeef; + output.rtTimestamp = 0xdeadbeef; + output.rtTimelength = 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); + ok(output.rtTimestamp == 0xdeadbeef, "got %s\n", wine_dbgstr_longlong(output.rtTimestamp)); + ok(output.rtTimelength == 0xdeadbeef, "got %s\n", wine_dbgstr_longlong(output.rtTimestamp));
/* write several frames of mp3 data */ for (i = 0; i < 5; i++) @@ -179,11 +188,14 @@ static void test_convert(void)
outbuf.len = 0; outbuf.maxlen = 1152 * 2; + output.rtTimestamp = 0xdeadbeef; + output.rtTimelength = 0xdeadbeef; hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status); ok(hr == S_OK, "got %#x\n", hr); ok(outbuf.len == 1152 * 2, "got %u\n", outbuf.len); -todo_wine ok(output.dwStatus == (O_SYNCPOINT | O_TIME | O_TIMELENGTH | O_INCOMPLETE), "got %#x\n", output.dwStatus); + ok(output.rtTimestamp == 0, "got %s\n", wine_dbgstr_longlong(output.rtTimestamp)); + ok(output.rtTimelength == framelen(1, 48000), "got %s\n", wine_dbgstr_longlong(output.rtTimelength));
hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status); ok(hr == S_FALSE, "got %#x\n", hr); @@ -194,16 +206,20 @@ todo_wine hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status); ok(hr == S_OK, "got %#x\n", hr); ok(outbuf.len == 1152 * 2 * 2, "got %u\n", outbuf.len); -todo_wine ok(output.dwStatus == (O_SYNCPOINT | O_TIME | O_TIMELENGTH | O_INCOMPLETE), "got %#x\n", output.dwStatus); + ok(output.rtTimestamp == framelen(1, 48000), "got %s\n", wine_dbgstr_longlong(output.rtTimestamp)); + ok(output.rtTimelength == framelen(1, 48000), "got %s\n", wine_dbgstr_longlong(output.rtTimelength));
outbuf.len = 0; outbuf.maxlen = 1152 * 2 * 3; + output.rtTimestamp = 0xdeadbeef; + output.rtTimelength = 0xdeadbeef; hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status); ok(hr == S_OK, "got %#x\n", hr); ok(outbuf.len == 1152 * 2 * 3, "got %u\n", outbuf.len); -todo_wine ok(output.dwStatus == (O_SYNCPOINT | O_TIME | O_TIMELENGTH | O_INCOMPLETE), "got %#x\n", output.dwStatus); + ok(output.rtTimestamp == framelen(2, 48000), "got %s\n", wine_dbgstr_longlong(output.rtTimestamp)); + ok(output.rtTimelength == framelen(3, 48000), "got %s\n", wine_dbgstr_longlong(output.rtTimelength));
hr = IMediaObject_ProcessOutput(dmo, 0, 1, &output, &status); ok(hr == S_FALSE, "got %#x\n", hr); @@ -216,10 +232,14 @@ todo_wine /* native requires one more frame's worth of space before it'll finish processing input */ outbuf.len = 0; outbuf.maxlen = 1152 * 2; + output.rtTimestamp = 0xdeadbeef; + output.rtTimelength = 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 == O_SYNCPOINT, "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));
hr = IMediaObject_ProcessInput(dmo, 0, &inbuf.IMediaBuffer_iface, 0, 0, 0); ok(hr == S_OK, "got %#x\n", hr);