From: Alfred Agrell floating@muncher.se
--- dlls/mf/tests/transform.c | 36 +---- dlls/winegstreamer/wma_decoder.c | 243 ++++++++++++++++++++++++++++--- 2 files changed, 228 insertions(+), 51 deletions(-)
diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index 3afbba0bf8e..460b354c9d1 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -1384,7 +1384,9 @@ static void check_dmo_media_type_(int line, DMO_MEDIA_TYPE *media_type, const DM "Got unexpected formattype %s.\n", debugstr_guid(&media_type->formattype)); ok_(__FILE__, line)(media_type->pUnk == NULL, "Got unexpected pUnk %p.\n", media_type->pUnk); - todo_wine_if(expected->cbFormat && expected->cbFormat != sizeof(VIDEOINFOHEADER)) + todo_wine_if(expected->cbFormat + && expected->cbFormat != sizeof(VIDEOINFOHEADER) + && IsEqualGUID(&expected->majortype, &MEDIATYPE_Video)) check_member_(__FILE__, line, *media_type, *expected, "%lu", cbFormat);
if (expected->pbFormat) @@ -3385,8 +3387,6 @@ static void test_wma_decoder_dmo_input_type(void) bad_input_type = (void *)buffer_bad;
/* Test GetInputType. */ - todo_wine - { count = ARRAY_SIZE(expected_input_types); hr = IMediaObject_GetInputType(dmo, 1, 0, NULL); ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetInputType returned %#lx.\n", hr); @@ -3402,7 +3402,6 @@ static void test_wma_decoder_dmo_input_type(void) ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned %#lx.\n", hr); hr = IMediaObject_GetInputType(dmo, 0, count - 1, NULL); ok(hr == S_OK, "GetInputType returned %#lx.\n", hr); - }
i = -1; while (SUCCEEDED(hr = IMediaObject_GetInputType(dmo, 0, ++i, &type))) @@ -3412,17 +3411,13 @@ static void test_wma_decoder_dmo_input_type(void) MoFreeMediaType(&type); winetest_pop_context(); } - todo_wine ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned %#lx.\n", hr); - todo_wine ok(i == count, "%lu types.\n", i);
/* Test SetInputType. */ init_dmo_media_type_audio(good_input_type, &MEDIASUBTYPE_WMAUDIO2, 2, 22050, 32); memset(bad_input_type, 0, sizeof(buffer_bad));
- todo_wine - { hr = IMediaObject_SetInputType(dmo, 1, NULL, 0); ok(hr == DMO_E_INVALIDSTREAMINDEX, "SetInputType returned %#lx.\n", hr); hr = IMediaObject_SetInputType(dmo, 1, bad_input_type, 0); @@ -3478,11 +3473,9 @@ static void test_wma_decoder_dmo_input_type(void) ok(hr == S_OK, "SetInputType returned %#lx.\n", hr); hr = IMediaObject_SetInputType(dmo, 0, good_input_type, 0x4); ok(hr == E_INVALIDARG, "SetInputType returned %#lx.\n", hr); - }
/* Test GetInputCurrentType. */ hr = IMediaObject_SetInputType(dmo, 0, NULL, DMO_SET_TYPEF_CLEAR); - todo_wine ok(hr == S_OK, "SetInputType returned %#lx.\n", hr); hr = IMediaObject_GetInputCurrentType(dmo, 1, NULL); todo_wine @@ -3498,7 +3491,6 @@ static void test_wma_decoder_dmo_input_type(void) ok(hr == DMO_E_TYPE_NOT_SET, "GetInputCurrentType returned %#lx.\n", hr);
hr = IMediaObject_SetInputType(dmo, 0, good_input_type, 0); - todo_wine ok(hr == S_OK, "SetInputType returned %#lx.\n", hr); hr = IMediaObject_GetInputCurrentType(dmo, 1, NULL); todo_wine @@ -3562,24 +3554,19 @@ static void test_wma_decoder_dmo_output_type(void) input_type = (void *)buffer_input; good_output_type = (void *)buffer_good_output; bad_output_type = (void *)buffer_bad_output; - init_dmo_media_type_audio(input_type, input_subtype, channel_count, rate, 32); + init_dmo_media_type_audio(input_type, input_subtype, channel_count, rate, 16); init_dmo_media_type_audio(good_output_type, &MEDIASUBTYPE_PCM, channel_count, rate, bits_per_sample); memset(bad_output_type, 0, sizeof(buffer_bad_output));
/* Test GetOutputType. */ hr = IMediaObject_GetOutputType(dmo, 1, 0, NULL); - todo_wine ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetOutputType returned %#lx.\n", hr); hr = IMediaObject_GetOutputType(dmo, 0, 0, NULL); - todo_wine ok(hr == DMO_E_TYPE_NOT_SET, "GetOutputType returned %#lx.\n", hr);
hr = IMediaObject_SetInputType(dmo, 0, input_type, 0); - todo_wine ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
- todo_wine - { count = 1; hr = IMediaObject_GetOutputType(dmo, 1, 0, NULL); ok(hr == DMO_E_INVALIDSTREAMINDEX, "GetOutputType returned %#lx.\n", hr); @@ -3595,7 +3582,6 @@ static void test_wma_decoder_dmo_output_type(void) ok(hr == DMO_E_NO_MORE_ITEMS, "GetOutputType returned %#lx.\n", hr); hr = IMediaObject_GetOutputType(dmo, 0, count - 1, NULL); ok(hr == S_OK, "GetOutputType returned %#lx.\n", hr); - }
i = -1; while (SUCCEEDED(hr = IMediaObject_GetOutputType(dmo, 0, ++i, &type))) @@ -3605,17 +3591,12 @@ static void test_wma_decoder_dmo_output_type(void) MoFreeMediaType(&type); winetest_pop_context(); } - todo_wine ok(hr == DMO_E_NO_MORE_ITEMS, "GetInputType returned %#lx.\n", hr); - todo_wine ok(i == count, "%lu types.\n", i);
/* Test SetOutputType. */ hr = IMediaObject_SetInputType(dmo, 0, NULL, DMO_SET_TYPEF_CLEAR); - todo_wine ok(hr == S_OK, "SetInputType returned %#lx.\n", hr); - todo_wine - { hr = IMediaObject_SetOutputType(dmo, 1, NULL, 0); ok(hr == DMO_E_INVALIDSTREAMINDEX, "SetOutputType returned %#lx.\n", hr); hr = IMediaObject_SetOutputType(dmo, 1, good_output_type, 0); @@ -3636,14 +3617,10 @@ static void test_wma_decoder_dmo_output_type(void) ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr); hr = IMediaObject_SetOutputType(dmo, 0, good_output_type, 0x4); ok(hr == E_INVALIDARG, "SetOutputType returned %#lx.\n", hr); - }
hr = IMediaObject_SetInputType(dmo, 0, input_type, 0); - todo_wine ok(hr == S_OK, "SetInputType returned %#lx.\n", hr);
- todo_wine - { hr = IMediaObject_SetOutputType(dmo, 1, NULL, 0); ok(hr == DMO_E_INVALIDSTREAMINDEX, "SetOutputType returned %#lx.\n", hr); hr = IMediaObject_SetOutputType(dmo, 1, bad_output_type, 0); @@ -3699,11 +3676,9 @@ static void test_wma_decoder_dmo_output_type(void) ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr); hr = IMediaObject_SetOutputType(dmo, 0, good_output_type, 0x4); ok(hr == E_INVALIDARG, "SetOutputType returned %#lx.\n", hr); - }
/* Test GetOutputCurrentType. */ hr = IMediaObject_SetOutputType(dmo, 0, NULL, DMO_SET_TYPEF_CLEAR); - todo_wine ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr); todo_wine { @@ -3718,7 +3693,6 @@ static void test_wma_decoder_dmo_output_type(void) }
hr = IMediaObject_SetOutputType(dmo, 0, good_output_type, 0); - todo_wine ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr); todo_wine { @@ -3741,7 +3715,6 @@ static void test_wma_decoder_dmo_output_type(void) todo_wine ok(hr == S_OK, "GetInputCurrentType returned %#lx.\n", hr); hr = IMediaObject_SetInputType(dmo, 0, input_type, 0); - todo_wine ok(hr == S_OK, "SetInputType returned %#lx.\n", hr); hr = IMediaObject_GetOutputCurrentType(dmo, 0, &type); todo_wine @@ -3749,7 +3722,6 @@ static void test_wma_decoder_dmo_output_type(void)
init_dmo_media_type_audio(input_type, input_subtype, channel_count, rate * 2, 32); hr = IMediaObject_SetInputType(dmo, 0, input_type, 0); - todo_wine ok(hr == S_OK, "SetInputType returned %#lx.\n", hr); hr = IMediaObject_GetOutputCurrentType(dmo, 0, &type); todo_wine diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c index a9f0f531b8c..62279e4d108 100644 --- a/dlls/winegstreamer/wma_decoder.c +++ b/dlls/winegstreamer/wma_decoder.c @@ -24,6 +24,7 @@ #include "mfobjects.h" #include "mftransform.h" #include "wmcodecdsp.h" +#include "mediaerr.h"
#include "wine/debug.h"
@@ -632,29 +633,185 @@ static HRESULT WINAPI media_object_GetOutputStreamInfo(IMediaObject *iface, DWOR static HRESULT WINAPI media_object_GetInputType(IMediaObject *iface, DWORD index, DWORD type_index, DMO_MEDIA_TYPE *type) { - FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface, index, type_index, type); - return E_NOTIMPL; + TRACE("iface %p, index %lu, type_index %lu, type %p.\n", iface, index, type_index, type); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + if (type_index >= ARRAY_SIZE(wma_decoder_input_types)) + return DMO_E_NO_MORE_ITEMS; + if (!type) + return S_OK; + + memset(type, 0, sizeof(*type)); + type->majortype = MFMediaType_Audio; + type->subtype = *wma_decoder_input_types[type_index]; + type->bFixedSizeSamples = FALSE; + type->bTemporalCompression = TRUE; + type->lSampleSize = 0; + + return S_OK; }
static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD index, DWORD type_index, DMO_MEDIA_TYPE *type) { - FIXME("iface %p, index %lu, type_index %lu, type %p stub!\n", iface, index, type_index, type); - return E_NOTIMPL; + struct wma_decoder *decoder = impl_from_IMediaObject(iface); + WAVEFORMATEX *wfx; + + TRACE("iface %p, index %lu, type_index %lu, type %p\n", iface, index, type_index, type); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + if (type_index >= 1) + return DMO_E_NO_MORE_ITEMS; + if (decoder->input_format.major_type == WG_MAJOR_TYPE_UNKNOWN) + return DMO_E_TYPE_NOT_SET; + if (!type) + return S_OK; + + memset(type, 0, sizeof(*type)); + type->majortype = MFMediaType_Audio; + type->subtype = MEDIASUBTYPE_PCM; + type->formattype = FORMAT_WaveFormatEx; + type->bFixedSizeSamples = FALSE; + type->bTemporalCompression = TRUE; + type->lSampleSize = 0; + + type->cbFormat = sizeof(WAVEFORMATEX); + type->pbFormat = CoTaskMemAlloc(type->cbFormat); + memset(type->pbFormat, 0, type->cbFormat); + + wfx = (WAVEFORMATEX *)type->pbFormat; + if (decoder->input_format.u.audio_wma.depth == 32) + wfx->wFormatTag = WAVE_FORMAT_IEEE_FLOAT; + else + wfx->wFormatTag = WAVE_FORMAT_PCM; + wfx->nChannels = decoder->input_format.u.audio_wma.channels; + wfx->nSamplesPerSec = decoder->input_format.u.audio_wma.rate; + wfx->wBitsPerSample = decoder->input_format.u.audio_wma.depth; + wfx->nAvgBytesPerSec = wfx->nChannels * wfx->nSamplesPerSec * wfx->wBitsPerSample / 8; + wfx->nBlockAlign = wfx->nChannels * wfx->wBitsPerSample / 8; + + return S_OK; }
static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index, const DMO_MEDIA_TYPE *type, DWORD flags) { - FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface, index, type, flags); - return E_NOTIMPL; + struct wma_decoder *decoder = impl_from_IMediaObject(iface); + struct wg_format wg_format; + unsigned int i; + + TRACE("iface %p, index %lu, type %p, flags %#lx.\n", iface, index, type, flags); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + + if (flags & DMO_SET_TYPEF_CLEAR) + { + if (flags != DMO_SET_TYPEF_CLEAR) + return E_INVALIDARG; + memset(&decoder->input_format, 0, sizeof(decoder->input_format)); + if (decoder->wg_transform) + { + wg_transform_destroy(decoder->wg_transform); + decoder->wg_transform = 0; + } + return S_OK; + } + if (!type) + return E_POINTER; + if (flags & ~DMO_SET_TYPEF_TEST_ONLY) + return E_INVALIDARG; + + if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Audio)) + return DMO_E_TYPE_NOT_ACCEPTED; + + for (i = 0; i < ARRAY_SIZE(wma_decoder_input_types); ++i) + if (IsEqualGUID(&type->subtype, wma_decoder_input_types[i])) + break; + if (i == ARRAY_SIZE(wma_decoder_input_types)) + return DMO_E_TYPE_NOT_ACCEPTED; + + if (!amt_to_wg_format((const AM_MEDIA_TYPE *)type, &wg_format)) + return DMO_E_TYPE_NOT_ACCEPTED; + assert(wg_format.major_type == WG_MAJOR_TYPE_AUDIO_WMA); + + if (flags & DMO_SET_TYPEF_TEST_ONLY) + return S_OK; + + decoder->input_format = wg_format; + if (decoder->wg_transform) + { + wg_transform_destroy(decoder->wg_transform); + decoder->wg_transform = 0; + } + + return S_OK; }
static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD index, const DMO_MEDIA_TYPE *type, DWORD flags) { - FIXME("iface %p, index %lu, type %p, flags %#lx stub!\n", iface, index, type, flags); - return E_NOTIMPL; + struct wma_decoder *decoder = impl_from_IMediaObject(iface); + struct wg_transform_attrs attrs = {0}; + struct wg_format wg_format; + unsigned int i; + + TRACE("iface %p, index %lu, type %p, flags %#lx,\n", iface, index, type, flags); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + + if (flags & DMO_SET_TYPEF_CLEAR) + { + if (flags != DMO_SET_TYPEF_CLEAR) + return E_INVALIDARG; + memset(&decoder->output_format, 0, sizeof(decoder->output_format)); + if (decoder->wg_transform) + { + wg_transform_destroy(decoder->wg_transform); + decoder->wg_transform = 0; + } + return S_OK; + } + if (!type) + return E_POINTER; + if (flags & ~DMO_SET_TYPEF_TEST_ONLY) + return E_INVALIDARG; + + if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Audio)) + return DMO_E_TYPE_NOT_ACCEPTED; + + for (i = 0; i < ARRAY_SIZE(wma_decoder_output_types); ++i) + if (IsEqualGUID(&type->subtype, wma_decoder_output_types[i])) + break; + if (i == ARRAY_SIZE(wma_decoder_output_types)) + return DMO_E_TYPE_NOT_ACCEPTED; + + + if (!amt_to_wg_format((const AM_MEDIA_TYPE *)type, &wg_format)) + return DMO_E_TYPE_NOT_ACCEPTED; + assert(wg_format.major_type == WG_MAJOR_TYPE_AUDIO); + + if (decoder->input_format.major_type == WG_MAJOR_TYPE_UNKNOWN) + return DMO_E_TYPE_NOT_SET; + + if (flags & DMO_SET_TYPEF_TEST_ONLY) + return S_OK; + + decoder->output_format = wg_format; + + /* Set up wg_transform. */ + if (decoder->wg_transform) + { + wg_transform_destroy(decoder->wg_transform); + decoder->wg_transform = 0; + } + if (!(decoder->wg_transform = wg_transform_create(&decoder->input_format, &decoder->output_format, &attrs))) + return E_FAIL; + + return S_OK; }
static HRESULT WINAPI media_object_GetInputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type) @@ -679,8 +836,21 @@ static HRESULT WINAPI media_object_GetInputSizeInfo(IMediaObject *iface, DWORD i
static HRESULT WINAPI media_object_GetOutputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, DWORD *alignment) { - FIXME("iface %p, index %lu, size %p, alignment %p stub!\n", iface, index, size, alignment); - return E_NOTIMPL; + struct wma_decoder *decoder = impl_from_IMediaObject(iface); + + TRACE("iface %p, index %lu, size %p, alignment %p.\n", iface, index, size, alignment); + + if (!size || !alignment) + return E_POINTER; + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + if (decoder->output_format.major_type == WG_MAJOR_TYPE_UNKNOWN) + return DMO_E_TYPE_NOT_SET; + + *size = 8192; + *alignment = 1; + + return S_OK; }
static HRESULT WINAPI media_object_GetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME *latency) @@ -697,14 +867,27 @@ static HRESULT WINAPI media_object_SetInputMaxLatency(IMediaObject *iface, DWORD
static HRESULT WINAPI media_object_Flush(IMediaObject *iface) { - FIXME("iface %p stub!\n", iface); - return E_NOTIMPL; + struct wma_decoder *decoder = impl_from_IMediaObject(iface); + HRESULT hr; + + TRACE("iface %p.\n", iface); + + if (FAILED(hr = wg_transform_flush(decoder->wg_transform))) + return hr; + + wg_sample_queue_flush(decoder->wg_sample_queue, TRUE); + + return S_OK; }
static HRESULT WINAPI media_object_Discontinuity(IMediaObject *iface, DWORD index) { - FIXME("iface %p, index %lu stub!\n", iface, index); - return E_NOTIMPL; + TRACE("iface %p, index %lu.\n", iface, index); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + + return S_OK; }
static HRESULT WINAPI media_object_AllocateStreamingResources(IMediaObject *iface) @@ -728,16 +911,38 @@ static HRESULT WINAPI media_object_GetInputStatus(IMediaObject *iface, DWORD ind static HRESULT WINAPI media_object_ProcessInput(IMediaObject *iface, DWORD index, IMediaBuffer *buffer, DWORD flags, REFERENCE_TIME timestamp, REFERENCE_TIME timelength) { - FIXME("iface %p, index %lu, buffer %p, flags %#lx, timestamp %s, timelength %s stub!\n", iface, - index, buffer, flags, wine_dbgstr_longlong(timestamp), wine_dbgstr_longlong(timelength)); - return E_NOTIMPL; + struct wma_decoder *decoder = impl_from_IMediaObject(iface); + + TRACE("iface %p, index %lu, buffer %p, flags %#lx, timestamp %s, timelength %s.\n", iface, + index, buffer, flags, wine_dbgstr_longlong(timestamp), wine_dbgstr_longlong(timelength)); + + if (!decoder->wg_transform) + return DMO_E_TYPE_NOT_SET; + + return wg_transform_push_dmo(decoder->wg_transform, buffer, flags, timestamp, timelength, decoder->wg_sample_queue); }
static HRESULT WINAPI media_object_ProcessOutput(IMediaObject *iface, DWORD flags, DWORD count, DMO_OUTPUT_DATA_BUFFER *buffers, DWORD *status) { - FIXME("iface %p, flags %#lx, count %lu, buffers %p, status %p stub!\n", iface, flags, count, buffers, status); - return E_NOTIMPL; + struct wma_decoder *decoder = impl_from_IMediaObject(iface); + HRESULT hr; + + TRACE("iface %p, flags %#lx, count %lu, buffers %p, status %p.\n", iface, flags, count, buffers, status); + + if (!decoder->wg_transform) + return DMO_E_TYPE_NOT_SET; + + hr = wg_transform_read_dmo(decoder->wg_transform, buffers); + + if (SUCCEEDED(hr)) + { + /* WMA Lossless emits anything from 0 to 12 packets of output for each packet of input */ + buffers[0].dwStatus |= DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE; + wg_sample_queue_flush(decoder->wg_sample_queue, false); + } + + return hr; }
static HRESULT WINAPI media_object_Lock(IMediaObject *iface, LONG lock)