Checking that WMA decoder ignores any incorrectly sized input sample.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51931 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52391 Signed-off-by: Rémi Bernon rbernon@codeweavers.com Signed-off-by: Zebediah Figura zfigura@codeweavers.com Signed-off-by: Nikolay Sivov nsivov@codeweavers.com ---
v4: * Rebase to fix the H264 decoder conflict in PATCH 2,
* Kept the signoffs.
dlls/mf/tests/mf.c | 23 +++++++++++++--------- dlls/winegstreamer/wma_decoder.c | 33 ++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 9 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 880fbc9fc3f..de72ad5a6e7 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -6035,6 +6035,7 @@ static void test_wma_decoder(void) MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Audio, MFAudioFormat_WMAudioV8}; MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Audio, MFAudioFormat_Float}; MFT_OUTPUT_STREAM_INFO output_info; + MFT_OUTPUT_DATA_BUFFER outputs[2]; MFT_INPUT_STREAM_INFO input_info; MFT_OUTPUT_DATA_BUFFER output; const BYTE *wma_encoded_data; @@ -6212,7 +6213,7 @@ static void test_wma_decoder(void) ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); ret = IMFSample_Release(sample); ok(ret == 0, "Release returned %lu\n", ret); - sample = create_sample(wma_encoded_data + wma_block_size, wma_block_size - wma_block_size / 2); + sample = create_sample(wma_encoded_data, wma_block_size + 1); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); todo_wine ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); @@ -6235,16 +6236,13 @@ static void test_wma_decoder(void) status = 0xdeadbeef; memset(&output, 0, sizeof(output)); hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); - todo_wine ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr); ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID); ok(!output.pSample, "got pSample %p\n", output.pSample); - todo_wine ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE || broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */, "got dwStatus %#lx\n", output.dwStatus); ok(!output.pEvents, "got pEvents %p\n", output.pEvents); - todo_wine ok(status == 0, "got status %#lx\n", status);
sample = create_sample(wma_encoded_data, wma_block_size); @@ -6257,16 +6255,25 @@ static void test_wma_decoder(void) status = 0xdeadbeef; memset(&output, 0, sizeof(output)); hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); - todo_wine ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr); ok(!output.pSample, "got pSample %p\n", output.pSample); - todo_wine ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE || broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE)) /* Win7 */, "got dwStatus %#lx\n", output.dwStatus); - todo_wine ok(status == 0, "got status %#lx\n", status);
+ status = 0xdeadbeef; + memset(&output, 0, sizeof(output)); + output_info.cbSize = sizeof(wma_decoded_data); + sample = create_sample(NULL, output_info.cbSize); + outputs[0].pSample = sample; + sample = create_sample(NULL, output_info.cbSize); + outputs[1].pSample = sample; + hr = IMFTransform_ProcessOutput(transform, 0, 2, outputs, &status); + ok(hr == E_INVALIDARG, "ProcessOutput returned %#lx\n", hr); + IMFSample_Release(outputs[0].pSample); + IMFSample_Release(outputs[1].pSample); + i = 1; status = 0xdeadbeef; output_info.cbSize = sizeof(wma_decoded_data); @@ -6337,7 +6344,6 @@ static void test_wma_decoder(void) ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr); ok(output.pSample == sample, "got pSample %p\n", output.pSample); ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus); - todo_wine ok(status == 0, "got status %#lx\n", status); ret = IMFSample_Release(sample); ok(ret == 0, "Release returned %lu\n", ret); @@ -6353,7 +6359,6 @@ static void test_wma_decoder(void) ok(output.dwStatus == 0 || broken(output.dwStatus == (MFT_OUTPUT_DATA_BUFFER_INCOMPLETE|7)) /* Win7 */, "got dwStatus %#lx\n", output.dwStatus); - todo_wine ok(status == 0, "got status %#lx\n", status); check_sample(sample, NULL, 0, NULL); ret = IMFSample_Release(sample); diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c index 6c198706944..a35da1cdc70 100644 --- a/dlls/winegstreamer/wma_decoder.c +++ b/dlls/winegstreamer/wma_decoder.c @@ -520,14 +520,47 @@ static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_
static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags) { + struct wma_decoder *decoder = impl_from_IMFTransform(iface); + MFT_INPUT_STREAM_INFO info; + HRESULT hr; + FIXME("iface %p, id %lu, sample %p, flags %#lx stub!\n", iface, id, sample, flags); + + if (!decoder->wg_transform) + return MF_E_TRANSFORM_TYPE_NOT_SET; + + if (FAILED(hr = IMFTransform_GetInputStreamInfo(iface, 0, &info))) + return hr; + return E_NOTIMPL; }
static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count, MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status) { + struct wma_decoder *decoder = impl_from_IMFTransform(iface); + MFT_OUTPUT_STREAM_INFO info; + HRESULT hr; + FIXME("iface %p, flags %#lx, count %lu, samples %p, status %p stub!\n", iface, flags, count, samples, status); + + if (count > 1) + return E_INVALIDARG; + + if (!decoder->wg_transform) + return MF_E_TRANSFORM_TYPE_NOT_SET; + + if (FAILED(hr = IMFTransform_GetOutputStreamInfo(iface, 0, &info))) + return hr; + + *status = 0; + samples[0].dwStatus = 0; + if (!samples[0].pSample) + { + samples[0].dwStatus = MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE; + return MF_E_TRANSFORM_NEED_MORE_INPUT; + } + return E_NOTIMPL; }
And use it to implement WMA decoder Process(Input|Output).
The test output is different because ffmpeg WMA decoder outputs data in a different way as native. The data seems valid audio nonetheless, and it shouldn't matter too much.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51931 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52391 Signed-off-by: Rémi Bernon rbernon@codeweavers.com Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/mf/tests/mf.c | 50 ++++--------- dlls/winegstreamer/gst_private.h | 5 ++ dlls/winegstreamer/main.c | 30 ++++++++ dlls/winegstreamer/mfplat.c | 49 ++++++++++++ dlls/winegstreamer/unix_private.h | 2 + dlls/winegstreamer/unixlib.h | 30 ++++++++ dlls/winegstreamer/wg_parser.c | 3 + dlls/winegstreamer/wg_transform.c | 119 +++++++++++++++++++++++++++++- dlls/winegstreamer/wma_decoder.c | 33 ++++++++- 9 files changed, 278 insertions(+), 43 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index de72ad5a6e7..166a357409a 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -6209,22 +6209,18 @@ static void test_wma_decoder(void)
sample = create_sample(wma_encoded_data, wma_block_size / 2); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); - todo_wine ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); ret = IMFSample_Release(sample); ok(ret == 0, "Release returned %lu\n", ret); sample = create_sample(wma_encoded_data, wma_block_size + 1); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); - todo_wine ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); ret = IMFSample_Release(sample); ok(ret == 0, "Release returned %lu\n", ret); sample = create_sample(wma_encoded_data, wma_block_size); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); - todo_wine ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); - todo_wine ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr); ret = IMFSample_Release(sample); todo_wine @@ -6247,7 +6243,6 @@ static void test_wma_decoder(void)
sample = create_sample(wma_encoded_data, wma_block_size); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); - todo_wine ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#lx\n", hr); ret = IMFSample_Release(sample); ok(ret == 0, "Release returned %lu\n", ret); @@ -6274,38 +6269,12 @@ static void test_wma_decoder(void) IMFSample_Release(outputs[0].pSample); IMFSample_Release(outputs[1].pSample);
- i = 1; status = 0xdeadbeef; output_info.cbSize = sizeof(wma_decoded_data); sample = create_sample(NULL, output_info.cbSize); memset(&output, 0, sizeof(output)); output.pSample = sample; hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); - while (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) - { - ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr); - ok(output.pSample == sample, "got pSample %p\n", output.pSample); - ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus); - ok(status == 0, "got status %#lx\n", status); - check_sample(sample, NULL, 0, NULL); - ret = IMFSample_Release(sample); - ok(ret == 0, "Release returned %lu\n", ret); - - sample = create_sample(wma_encoded_data + i * wma_block_size, wma_block_size); - hr = IMFTransform_ProcessInput(transform, 0, sample, 0); - ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); - ret = IMFSample_Release(sample); - ok(ret == 1, "Release returned %lu\n", ret); - i++; - - status = 0xdeadbeef; - sample = create_sample(NULL, output_info.cbSize); - memset(&output, 0, sizeof(output)); - output.pSample = sample; - hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); - } - - todo_wine ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr); ok(output.pSample == sample, "got pSample %p\n", output.pSample);
@@ -6325,8 +6294,20 @@ static void test_wma_decoder(void) } else { - check_sample(sample, wma_decoded_data, sizeof(wma_decoded_data) / 2, NULL); - i += sizeof(wma_decoded_data) / 2; + DWORD length; + + /* FFmpeg doesn't seem to decode WMA buffers in the same way as native */ + + hr = IMFSample_GetTotalLength(sample, &length); + ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr); + todo_wine + ok(length == sizeof(wma_decoded_data) / 2, "got length %lu\n", length); + + if (length == sizeof(wma_decoded_data) / 2) + { + check_sample(sample, wma_decoded_data, sizeof(wma_decoded_data) / 2, NULL); + i += sizeof(wma_decoded_data) / 2; + } } ret = IMFSample_Release(sample); ok(ret == 0, "Release returned %lu\n", ret); @@ -6340,7 +6321,6 @@ static void test_wma_decoder(void) todo_wine ok(i == 0xe000, "ProcessOutput produced %#lx bytes\n", i);
- todo_wine ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr); ok(output.pSample == sample, "got pSample %p\n", output.pSample); ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus); @@ -6353,7 +6333,6 @@ static void test_wma_decoder(void) memset(&output, 0, sizeof(output)); output.pSample = sample; hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); - todo_wine ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr); ok(output.pSample == sample, "got pSample %p\n", output.pSample); ok(output.dwStatus == 0 || @@ -6366,7 +6345,6 @@ static void test_wma_decoder(void)
sample = create_sample(wma_encoded_data, wma_block_size); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); - todo_wine ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
ret = IMFTransform_Release(transform); diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 34b3e0c1047..f5da807a2ab 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -96,6 +96,8 @@ void wg_parser_stream_seek(struct wg_parser_stream *stream, double rate, struct wg_transform *wg_transform_create(const struct wg_format *input_format, const struct wg_format *output_format); void wg_transform_destroy(struct wg_transform *transform); +HRESULT wg_transform_push_data(struct wg_transform *transform, struct wg_sample *sample); +HRESULT wg_transform_read_data(struct wg_transform *transform, struct wg_sample *sample);
unsigned int wg_format_get_max_size(const struct wg_format *format);
@@ -116,6 +118,9 @@ extern HRESULT mfplat_DllRegisterServer(void); IMFMediaType *mf_media_type_from_wg_format(const struct wg_format *format); void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format);
+HRESULT mf_create_wg_sample(IMFSample *sample, struct wg_sample **out); +void mf_destroy_wg_sample(struct wg_sample *wg_sample); + HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj);
HRESULT h264_decoder_create(REFIID riid, void **ret); diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index 327d144499e..8a41df6b223 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -263,6 +263,36 @@ void wg_transform_destroy(struct wg_transform *transform) __wine_unix_call(unix_handle, unix_wg_transform_destroy, transform); }
+HRESULT wg_transform_push_data(struct wg_transform *transform, struct wg_sample *sample) +{ + struct wg_transform_push_data_params params = + { + .transform = transform, + .sample = sample, + }; + NTSTATUS status; + + if ((status = __wine_unix_call(unix_handle, unix_wg_transform_push_data, ¶ms))) + return HRESULT_FROM_NT(status); + + return params.result; +} + +HRESULT wg_transform_read_data(struct wg_transform *transform, struct wg_sample *sample) +{ + struct wg_transform_read_data_params params = + { + .transform = transform, + .sample = sample, + }; + NTSTATUS status; + + if ((status = __wine_unix_call(unix_handle, unix_wg_transform_read_data, ¶ms))) + return HRESULT_FROM_NT(status); + + return params.result; +} + BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved) { if (reason == DLL_PROCESS_ATTACH) diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index 7eb673b61ae..ed460144e8b 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -854,3 +854,52 @@ void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format) else FIXME("Unrecognized major type %s.\n", debugstr_guid(&major_type)); } + +struct mf_sample +{ + IMFSample *sample; + IMFMediaBuffer *media_buffer; + struct wg_sample wg_sample; +}; + +HRESULT mf_create_wg_sample(IMFSample *sample, struct wg_sample **out) +{ + DWORD current_length, max_length; + struct mf_sample *mf_sample; + BYTE *buffer; + HRESULT hr; + + if (!(mf_sample = calloc(1, sizeof(*mf_sample)))) + return E_OUTOFMEMORY; + if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(sample, &mf_sample->media_buffer))) + goto out; + if (FAILED(hr = IMFMediaBuffer_Lock(mf_sample->media_buffer, &buffer, &max_length, ¤t_length))) + goto out; + + IMFSample_AddRef((mf_sample->sample = sample)); + mf_sample->wg_sample.data = buffer; + mf_sample->wg_sample.size = current_length; + mf_sample->wg_sample.max_size = max_length; + + TRACE("Created mf_sample %p for sample %p.\n", mf_sample, sample); + *out = &mf_sample->wg_sample; + return S_OK; + +out: + if (mf_sample->media_buffer) + IMFMediaBuffer_Release(mf_sample->media_buffer); + free(mf_sample); + return hr; +} + +void mf_destroy_wg_sample(struct wg_sample *wg_sample) +{ + struct mf_sample *mf_sample = CONTAINING_RECORD(wg_sample, struct mf_sample, wg_sample); + + IMFMediaBuffer_Unlock(mf_sample->media_buffer); + IMFMediaBuffer_SetCurrentLength(mf_sample->media_buffer, wg_sample->size); + IMFMediaBuffer_Release(mf_sample->media_buffer); + + IMFSample_Release(mf_sample->sample); + free(mf_sample); +} diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h index d3f32484ee6..7bce8263aaf 100644 --- a/dlls/winegstreamer/unix_private.h +++ b/dlls/winegstreamer/unix_private.h @@ -34,5 +34,7 @@ extern GstCaps *wg_format_to_caps(const struct wg_format *format) DECLSPEC_HIDDE
extern NTSTATUS wg_transform_create(void *args) DECLSPEC_HIDDEN; extern NTSTATUS wg_transform_destroy(void *args) DECLSPEC_HIDDEN; +extern NTSTATUS wg_transform_push_data(void *args) DECLSPEC_HIDDEN; +extern NTSTATUS wg_transform_read_data(void *args) DECLSPEC_HIDDEN;
#endif /* __WINE_WINEGSTREAMER_UNIX_PRIVATE_H */ diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index 3dfa30b4889..e1c0ec3f3b7 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -103,6 +103,19 @@ struct wg_format } u; };
+enum wg_sample_flag +{ + WG_SAMPLE_FLAG_INCOMPLETE = 1, +}; + +struct wg_sample +{ + UINT32 flags; + UINT32 max_size; + UINT32 size; + BYTE *data; +}; + struct wg_parser_buffer { /* pts and duration are in 100-nanosecond units. */ @@ -216,6 +229,20 @@ struct wg_transform_create_params const struct wg_format *output_format; };
+struct wg_transform_push_data_params +{ + struct wg_transform *transform; + struct wg_sample *sample; + HRESULT result; +}; + +struct wg_transform_read_data_params +{ + struct wg_transform *transform; + struct wg_sample *sample; + HRESULT result; +}; + enum unix_funcs { unix_wg_parser_create, @@ -244,6 +271,9 @@ enum unix_funcs
unix_wg_transform_create, unix_wg_transform_destroy, + + unix_wg_transform_push_data, + unix_wg_transform_read_data, };
#endif /* __WINE_WINEGSTREAMER_UNIXLIB_H */ diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 46a298f13c1..df563e9336e 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -1589,4 +1589,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
X(wg_transform_create), X(wg_transform_destroy), + + X(wg_transform_push_data), + X(wg_transform_read_data), }; diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index 45f8588b9f1..6e272634653 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -35,7 +35,7 @@ #include "ntstatus.h" #define WIN32_NO_STATUS #include "winternl.h" -#include "dshow.h" +#include "mferror.h"
#include "unix_private.h"
@@ -48,15 +48,24 @@ struct wg_transform GstPad *my_src, *my_sink; GstPad *their_sink, *their_src; GstSegment segment; + GstBuffer *input; + + pthread_mutex_t mutex; + GstBuffer *output; };
static GstFlowReturn transform_sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *buffer) { struct wg_transform *transform = gst_pad_get_element_private(pad);
- GST_INFO("transform %p, buffer %p.", transform, buffer); + GST_LOG("transform %p, buffer %p.", transform, buffer);
- gst_buffer_unref(buffer); + pthread_mutex_lock(&transform->mutex); + if (transform->output) + transform->output = gst_buffer_append(transform->output, buffer); + else + transform->output = buffer; + pthread_mutex_unlock(&transform->mutex);
return GST_FLOW_OK; } @@ -65,12 +74,18 @@ NTSTATUS wg_transform_destroy(void *args) { struct wg_transform *transform = args;
+ if (transform->input) + gst_buffer_unref(transform->input); + if (transform->output) + gst_buffer_unref(transform->output); + gst_element_set_state(transform->container, GST_STATE_NULL); g_object_unref(transform->their_sink); g_object_unref(transform->their_src); g_object_unref(transform->container); g_object_unref(transform->my_sink); g_object_unref(transform->my_src); + pthread_mutex_destroy(&transform->mutex); free(transform);
return STATUS_SUCCESS; @@ -278,6 +293,8 @@ NTSTATUS wg_transform_create(void *args) gst_caps_unref(sink_caps); gst_caps_unref(src_caps);
+ pthread_mutex_init(&transform->mutex, NULL); + GST_INFO("Created winegstreamer transform %p.", transform); params->transform = transform; return STATUS_SUCCESS; @@ -304,3 +321,99 @@ out: GST_ERROR("Failed to create winegstreamer transform."); return status; } + +NTSTATUS wg_transform_push_data(void *args) +{ + struct wg_transform_push_data_params *params = args; + struct wg_transform *transform = params->transform; + struct wg_sample *sample = params->sample; + GstBuffer *buffer; + + if (transform->input) + { + GST_INFO("Refusing %u bytes, a buffer is already queued", sample->size); + params->result = MF_E_NOTACCEPTING; + return STATUS_SUCCESS; + } + + if (!(buffer = gst_buffer_new_and_alloc(sample->size))) + { + GST_ERROR("Failed to allocate input buffer"); + return STATUS_NO_MEMORY; + } + gst_buffer_fill(buffer, 0, sample->data, sample->size); + transform->input = buffer; + + GST_INFO("Copied %u bytes from sample %p to input buffer", sample->size, sample); + params->result = S_OK; + return STATUS_SUCCESS; +} + +static NTSTATUS read_transform_output_data(struct wg_transform *transform, + struct wg_sample *sample) +{ + GstBuffer *buffer = transform->output; + GstMapInfo info; + + if (!gst_buffer_map(buffer, &info, GST_MAP_READ)) + { + GST_ERROR("Failed to map buffer %p", buffer); + return STATUS_UNSUCCESSFUL; + } + + if (sample->max_size >= info.size) + sample->size = info.size; + else + { + sample->flags |= WG_SAMPLE_FLAG_INCOMPLETE; + sample->size = sample->max_size; + } + + memcpy(sample->data, info.data, sample->size); + gst_buffer_unmap(buffer, &info); + gst_buffer_resize(buffer, sample->size, -1); + + if (info.size <= sample->size) + { + gst_buffer_unref(transform->output); + transform->output = NULL; + } + + GST_INFO("Copied %u bytes, sample %p, flags %#x", sample->size, sample, sample->flags); + return STATUS_SUCCESS; +} + +NTSTATUS wg_transform_read_data(void *args) +{ + struct wg_transform_read_data_params *params = args; + struct wg_transform *transform = params->transform; + struct wg_sample *sample = params->sample; + GstFlowReturn ret; + NTSTATUS status; + + if (!transform->input) + GST_DEBUG("Not input buffer queued"); + else if ((ret = gst_pad_push(transform->my_src, transform->input))) + { + GST_ERROR("Failed to push transform input, error %d", ret); + return STATUS_UNSUCCESSFUL; + } + transform->input = NULL; + + sample->size = 0; + pthread_mutex_lock(&transform->mutex); + if (transform->output) + { + params->result = S_OK; + status = read_transform_output_data(transform, sample); + } + else + { + params->result = MF_E_TRANSFORM_NEED_MORE_INPUT; + status = STATUS_SUCCESS; + GST_INFO("Cannot read %u bytes, no output available", sample->max_size); + } + pthread_mutex_unlock(&transform->mutex); + + return status; +} diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c index a35da1cdc70..6ee43e19414 100644 --- a/dlls/winegstreamer/wma_decoder.c +++ b/dlls/winegstreamer/wma_decoder.c @@ -521,10 +521,11 @@ static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_ static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags) { struct wma_decoder *decoder = impl_from_IMFTransform(iface); + struct wg_sample *wg_sample; MFT_INPUT_STREAM_INFO info; HRESULT hr;
- FIXME("iface %p, id %lu, sample %p, flags %#lx stub!\n", iface, id, sample, flags); + TRACE("iface %p, id %lu, sample %p, flags %#lx.\n", iface, id, sample, flags);
if (!decoder->wg_transform) return MF_E_TRANSFORM_TYPE_NOT_SET; @@ -532,7 +533,17 @@ static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFS if (FAILED(hr = IMFTransform_GetInputStreamInfo(iface, 0, &info))) return hr;
- return E_NOTIMPL; + if (FAILED(hr = mf_create_wg_sample(sample, &wg_sample))) + return hr; + + /* WMA transform uses fixed size input samples and ignores samples with invalid sizes */ + if (wg_sample->size % info.cbSize) + hr = S_OK; + else + hr = wg_transform_push_data(decoder->wg_transform, wg_sample); + + mf_destroy_wg_sample(wg_sample); + return hr; }
static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count, @@ -540,9 +551,10 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, { struct wma_decoder *decoder = impl_from_IMFTransform(iface); MFT_OUTPUT_STREAM_INFO info; + struct wg_sample *wg_sample; HRESULT hr;
- FIXME("iface %p, flags %#lx, count %lu, samples %p, status %p stub!\n", iface, flags, count, samples, status); + TRACE("iface %p, flags %#lx, count %lu, samples %p, status %p.\n", iface, flags, count, samples, status);
if (count > 1) return E_INVALIDARG; @@ -561,7 +573,20 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, return MF_E_TRANSFORM_NEED_MORE_INPUT; }
- return E_NOTIMPL; + if (FAILED(hr = mf_create_wg_sample(samples[0].pSample, &wg_sample))) + return hr; + + wg_sample->size = 0; + if (wg_sample->max_size < info.cbSize) + hr = MF_E_BUFFERTOOSMALL; + else if (SUCCEEDED(hr = wg_transform_read_data(decoder->wg_transform, wg_sample))) + { + if (wg_sample->flags & WG_SAMPLE_FLAG_INCOMPLETE) + samples[0].dwStatus |= MFT_OUTPUT_DATA_BUFFER_INCOMPLETE; + } + + mf_destroy_wg_sample(wg_sample); + return hr; }
static const IMFTransformVtbl transform_vtbl =
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51931 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52391 Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winegstreamer/wma_decoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c index 6ee43e19414..57b0f204f9e 100644 --- a/dlls/winegstreamer/wma_decoder.c +++ b/dlls/winegstreamer/wma_decoder.c @@ -515,7 +515,7 @@ static HRESULT WINAPI transform_ProcessEvent(IMFTransform *iface, DWORD id, IMFM static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param) { FIXME("iface %p, message %#x, param %p stub!\n", iface, message, (void *)param); - return E_NOTIMPL; + return S_OK; }
static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)