[PATCH 3/5] winegstreamer: Implement WMA decoder ProcessInput.
Rémi Bernon
rbernon at codeweavers.com
Tue Feb 22 16:48:17 CST 2022
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 at 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,
--
2.34.1
More information about the wine-devel
mailing list