[PATCH v2 7/8] winegstreamer: Introduce new wg_transform_read_data entry point.
Rémi Bernon
rbernon at codeweavers.com
Wed Feb 23 08:46:38 CST 2022
And use it to implement WMA decoder ProcessOutput.
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 | 9 +++-
dlls/winegstreamer/gst_private.h | 1 +
dlls/winegstreamer/main.c | 15 +++++++
dlls/winegstreamer/mfplat.c | 1 +
dlls/winegstreamer/unix_private.h | 1 +
dlls/winegstreamer/unixlib.h | 16 +++++++
dlls/winegstreamer/wg_parser.c | 2 +
dlls/winegstreamer/wg_transform.c | 74 ++++++++++++++++++++++++++++++-
dlls/winegstreamer/wma_decoder.c | 9 ++--
9 files changed, 123 insertions(+), 5 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index f3c0db7a2c6..e5c0e6051b5 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -6079,9 +6079,17 @@ static void test_wma_decoder(void)
sample = create_sample(wma_encoded_data + i * wma_block_size, wma_block_size);
hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
+ todo_wine
ok(hr == S_OK, "ProcessInput returned %#x\n", hr);
ret = IMFSample_Release(sample);
+ todo_wine
ok(ret == 1, "Release returned %u\n", ret);
+ if (hr != S_OK)
+ {
+ memset(&output, 0, sizeof(output));
+ output.pSample = sample = create_sample(NULL, output_info.cbSize);
+ break;
+ }
i++;
status = 0xdeadbeef;
@@ -6139,7 +6147,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 %#x\n", hr);
ok(output.pSample == sample, "got pSample %p\n", output.pSample);
ok(output.dwStatus == 0 ||
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h
index 7ad3434fd1d..7970980e5ba 100644
--- a/dlls/winegstreamer/gst_private.h
+++ b/dlls/winegstreamer/gst_private.h
@@ -99,6 +99,7 @@ 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_read_data(struct wg_transform *transform, struct wg_sample *sample);
unsigned int wg_format_get_max_size(const struct wg_format *format);
diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c
index f85e9995525..4337bd7e5e1 100644
--- a/dlls/winegstreamer/main.c
+++ b/dlls/winegstreamer/main.c
@@ -273,6 +273,21 @@ void wg_transform_destroy(struct wg_transform *transform)
__wine_unix_call(unix_handle, unix_wg_transform_destroy, transform);
}
+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 c457a4ee79a..4b4d647170a 100644
--- a/dlls/winegstreamer/mfplat.c
+++ b/dlls/winegstreamer/mfplat.c
@@ -850,6 +850,7 @@ HRESULT mf_create_wg_sample(IMFSample *sample, struct wg_sample **out)
goto out_release_buffer;
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;
diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h
index d3f32484ee6..d14d0d309f5 100644
--- a/dlls/winegstreamer/unix_private.h
+++ b/dlls/winegstreamer/unix_private.h
@@ -34,5 +34,6 @@ 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_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 5bcad297fa9..8bc8b5f9ec2 100644
--- a/dlls/winegstreamer/unixlib.h
+++ b/dlls/winegstreamer/unixlib.h
@@ -103,10 +103,17 @@ 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;
};
enum wg_parser_event_type
@@ -242,6 +249,13 @@ struct wg_transform_create_params
const struct wg_format *output_format;
};
+struct wg_transform_read_data_params
+{
+ struct wg_transform *transform;
+ struct wg_sample *sample;
+ HRESULT result;
+};
+
enum unix_funcs
{
unix_wg_parser_create,
@@ -273,6 +287,8 @@ enum unix_funcs
unix_wg_transform_create,
unix_wg_transform_destroy,
+
+ 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 d9bbc60964e..8b7c5278c27 100644
--- a/dlls/winegstreamer/wg_parser.c
+++ b/dlls/winegstreamer/wg_parser.c
@@ -1660,4 +1660,6 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
X(wg_transform_create),
X(wg_transform_destroy),
+
+ X(wg_transform_read_data),
};
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index ed4f95afde3..5200d836db4 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,6 +48,7 @@ struct sample_entry
{
struct list entry;
GstSample *sample;
+ gsize buffer_size;
};
struct wg_transform
@@ -72,6 +73,7 @@ static GstFlowReturn transform_sink_chain_cb(GstPad *pad, GstObject *parent, Gst
else
{
pthread_mutex_lock(&transform->mutex);
+ entry->buffer_size = gst_buffer_get_size(buffer);
entry->sample = gst_sample_new(buffer, NULL, NULL, NULL);
list_add_tail(&transform->samples, &entry->entry);
pthread_mutex_unlock(&transform->mutex);
@@ -340,3 +342,73 @@ out_free_transform:
GST_ERROR("Failed to create winegstreamer transform.");
return status;
}
+
+static void release_sample_entry(struct wg_sample *sample, struct sample_entry *entry)
+{
+ GstBuffer *buffer = gst_sample_get_buffer(entry->sample);
+
+ if (entry->buffer_size > sample->size)
+ {
+ gst_buffer_resize(buffer, sample->size, -1);
+ entry->buffer_size -= sample->size;
+ }
+ else
+ {
+ gst_sample_unref(entry->sample);
+ list_remove(&entry->entry);
+ free(entry);
+ }
+}
+
+static NTSTATUS copy_from_sample_entry(struct wg_sample *sample, struct sample_entry *entry)
+{
+ GstBuffer *buffer = gst_sample_get_buffer(entry->sample);
+ 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_INFO("Copied %u bytes, flags %#x", sample->size, (UINT32)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;
+ struct sample_entry *entry;
+ struct list *head;
+ NTSTATUS status;
+
+ pthread_mutex_lock(&transform->mutex);
+ if ((head = list_head(&transform->samples)))
+ {
+ params->result = S_OK;
+ entry = LIST_ENTRY(head, struct sample_entry, entry);
+ status = copy_from_sample_entry(sample, entry);
+ release_sample_entry(sample, entry);
+ }
+ else
+ {
+ params->result = MF_E_TRANSFORM_NEED_MORE_INPUT;
+ status = STATUS_SUCCESS;
+ }
+ pthread_mutex_unlock(&transform->mutex);
+
+ return status;
+}
diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c
index 354f363bedf..af7db10b335 100644
--- a/dlls/winegstreamer/wma_decoder.c
+++ b/dlls/winegstreamer/wma_decoder.c
@@ -554,7 +554,7 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags,
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;
@@ -579,8 +579,11 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags,
wg_sample->size = 0;
if (wg_sample->max_size < info.cbSize)
hr = MF_E_BUFFERTOOSMALL;
- else
- hr = E_NOTIMPL;
+ 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;
--
2.34.1
More information about the wine-devel
mailing list