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 ---
This series introduces a new wg_sample structure, which is used to pass media buffers from PE to unix and back, as well as their metadata.
Initially the buffers are copied to GStreamer buffer, but the last patch of the series introduces a zero-copy mechanism, which is used for input buffers only for now.
Testing shows that IMFTransform are usually keeping a reference on their input samples, and this makes it easier to keep the IMFSample alive as long as the unix side has a reference on them, reaping them on specific occasion to retrieve released samples and release their PE-side objects.
For output buffers, zero-copy is also possible, using the same structure and mapping mechanism, but is a little trickier as transforms aren't apparently keeping a reference on the output samples they are passed across calls to ProcessOutput.
They can also optionally allocate and provide samples themselves to the caller, instead of depending on their samples, but it's not how native transforms are working, and to keep the behavior and compatibility close we cannot safely rely on it.
The idea, which will be proposed later, and for the H264 transform (as video buffers may be large, it makes most sense there), will be to decouple GStreamer decoding using a queue, and a buffer pool which will wait on ProcessOutput calls to provide output buffers to the pipeline.
dlls/winegstreamer/wg_transform.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-)
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index d316071cf60..7160fd087b6 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -46,6 +46,7 @@ struct wg_transform { GstElement *container; GstPad *my_src, *my_sink; + GstPad *their_sink, *their_src; };
static GstFlowReturn transform_sink_chain_cb(GstPad *pad, GstObject *parent, GstBuffer *buffer) @@ -64,6 +65,10 @@ NTSTATUS wg_transform_destroy(void *args) struct wg_transform *transform = args;
gst_element_set_state(transform->container, GST_STATE_NULL); + gst_pad_unlink(transform->their_src, transform->my_sink); + gst_pad_unlink(transform->my_src, transform->their_sink); + 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); @@ -237,9 +242,22 @@ NTSTATUS wg_transform_create(void *args) goto out_free_sink_pad; }
+ if (!(transform->their_sink = gst_element_get_static_pad(first, "sink"))) + goto out_free_sink_pad; + if (!(transform->their_src = gst_element_get_static_pad(last, "src"))) + goto out_free_their_sink; + if (gst_pad_link(transform->my_src, transform->their_sink) < 0) + goto out_free_their_src; + if (gst_pad_link(transform->their_src, transform->my_sink) < 0) + goto out_unlink_src_pad; + if (!gst_pad_set_active(transform->my_sink, 1)) + goto out_unlink_sink_pad; + if (!gst_pad_set_active(transform->my_src, 1)) + goto out_unlink_sink_pad; + gst_element_set_state(transform->container, GST_STATE_PAUSED); if (!gst_element_get_state(transform->container, NULL, NULL, -1)) - goto out_free_sink_pad; + goto out_unlink_sink_pad;
gst_caps_unref(sink_caps); gst_caps_unref(src_caps); @@ -248,6 +266,14 @@ NTSTATUS wg_transform_create(void *args) params->transform = transform; return STATUS_SUCCESS;
+out_unlink_sink_pad: + gst_pad_unlink(transform->their_src, transform->my_sink); +out_unlink_src_pad: + gst_pad_unlink(transform->my_src, transform->their_sink); +out_free_their_src: + g_object_unref(transform->their_src); +out_free_their_sink: + g_object_unref(transform->their_sink); out_free_sink_pad: gst_object_unref(transform->my_sink); out_free_sink_caps: