Simply keeping a reference on the input sample for now, wrapped in a new wg_sample struct.
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/mf/tests/mf.c | 6 ---- dlls/winegstreamer/gst_private.h | 3 ++ dlls/winegstreamer/mfplat.c | 59 ++++++++++++++++++++++++++++++++ dlls/winegstreamer/unixlib.h | 8 +++++ dlls/winegstreamer/wma_decoder.c | 37 ++++++++++++++++++-- 5 files changed, 105 insertions(+), 8 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 60d95529f97..be02a0909e8 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -5996,25 +5996,20 @@ 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 %#x\n", hr); ret = IMFSample_Release(sample); ok(ret == 0, "Release returned %u\n", ret); sample = create_sample(wma_encoded_data + wma_block_size, wma_block_size - wma_block_size / 2); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); - todo_wine ok(hr == S_OK, "ProcessInput returned %#x\n", hr); ret = IMFSample_Release(sample); ok(ret == 0, "Release returned %u\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 %#x\n", hr); hr = IMFTransform_ProcessInput(transform, 0, sample, 0); - todo_wine ok(hr == MF_E_NOTACCEPTING, "ProcessInput returned %#x\n", hr); ret = IMFSample_Release(sample); - todo_wine ok(ret == 1, "Release returned %u\n", ret);
/* As output_info.dwFlags doesn't have MFT_OUTPUT_STREAM_CAN_PROVIDE_SAMPLES @@ -6037,7 +6032,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 %#x\n", hr); ret = IMFSample_Release(sample); ok(ret == 0, "Release returned %u\n", ret); diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index a63daaf04b9..7ad3434fd1d 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -119,6 +119,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 audio_converter_create(REFIID riid, void **ret); diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index 9b3fc429d32..2ba1490f20b 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -827,3 +827,62 @@ void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format) else FIXME("Unrecognized major type %s.\n", debugstr_guid(&major_type)); } + +HRESULT mf_create_wg_sample(IMFSample *sample, struct wg_sample **out) +{ + DWORD current_length, max_length, count; + IMFMediaBuffer *media_buffer = NULL; + struct wg_sample *entry; + BYTE *buffer; + HRESULT hr; + + if (FAILED(hr = IMFSample_GetBufferCount(sample, &count)) || count != 1) + { + FIXME("Only samples with 1 buffer are supported!\n"); + return hr ? hr : E_FAIL; + } + + if (!(entry = calloc(1, sizeof(*entry)))) + return E_OUTOFMEMORY; + + if (FAILED(hr = IMFSample_GetBufferByIndex(sample, 0, &media_buffer))) + goto failed; + if (FAILED(hr = IMFMediaBuffer_Lock(media_buffer, &buffer, &max_length, ¤t_length))) + goto failed; + + IMFSample_AddRef((entry->private = sample)); + entry->data = buffer; + entry->size = current_length; + entry->max_size = max_length; + + TRACE("Created sample entry %p.\n", entry); + *out = entry; + return S_OK; + +failed: + if (media_buffer) + IMFMediaBuffer_Release(media_buffer); + free(entry); + return hr; +} + +void mf_destroy_wg_sample(struct wg_sample *sample) +{ + IMFMediaBuffer *media_buffer; + HRESULT hr; + + if (FAILED(hr = IMFSample_GetBufferByIndex(sample->private, 0, &media_buffer))) + WARN("Failed to get first buffer, sample %p\n", sample->private); + else + { + /* release lock and ref taken in mf_create_wg_sample */ + IMFMediaBuffer_Unlock(media_buffer); + IMFMediaBuffer_SetCurrentLength(media_buffer, sample->size); + IMFMediaBuffer_Release(media_buffer); + + IMFMediaBuffer_Release(media_buffer); + } + + IMFSample_Release(sample->private); + free(sample); +} diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index 4adbb694766..59b15df7d08 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -103,6 +103,14 @@ struct wg_format } u; };
+struct wg_sample +{ + UINT32 max_size; + UINT32 size; + BYTE *data; + void *private; +}; + enum wg_parser_event_type { WG_PARSER_EVENT_NONE = 0, diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c index 6c198706944..f84faad669d 100644 --- a/dlls/winegstreamer/wma_decoder.c +++ b/dlls/winegstreamer/wma_decoder.c @@ -55,6 +55,7 @@ struct wma_decoder IMFMediaType *output_type;
struct wg_transform *wg_transform; + struct wg_sample *input_sample; };
static inline struct wma_decoder *impl_from_IUnknown(IUnknown *iface) @@ -134,6 +135,8 @@ static ULONG WINAPI unknown_Release(IUnknown *iface) IMFMediaType_Release(decoder->input_type); if (decoder->output_type) IMFMediaType_Release(decoder->output_type); + if (decoder->input_sample) + mf_destroy_wg_sample(decoder->input_sample); free(decoder); }
@@ -520,8 +523,38 @@ static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_
static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags) { - FIXME("iface %p, id %lu, sample %p, flags %#lx stub!\n", iface, id, sample, flags); - return E_NOTIMPL; + struct wma_decoder *decoder = impl_from_IMFTransform(iface); + IMFMediaBuffer *media_buffer; + struct wg_sample *wg_sample; + MFT_INPUT_STREAM_INFO info; + HRESULT hr; + + TRACE("iface %p, id %lu, sample %p, flags %#lx.\n", iface, id, sample, flags); + + if (FAILED(hr = IMFTransform_GetInputStreamInfo(iface, 0, &info))) + return hr; + + if (!decoder->wg_transform) + return MF_E_TRANSFORM_TYPE_NOT_SET; + + if (decoder->input_sample) + return MF_E_NOTACCEPTING; + + if (FAILED(hr = IMFSample_ConvertToContiguousBuffer(sample, &media_buffer))) + return hr; + IMFMediaBuffer_Release(media_buffer); + + if (FAILED(hr = mf_create_wg_sample(sample, &wg_sample))) + return hr; + + if (!(wg_sample->size = (wg_sample->size / info.cbSize) * info.cbSize)) + { + mf_destroy_wg_sample(wg_sample); + return S_OK; + } + + decoder->input_sample = wg_sample; + return S_OK; }
static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count,