[PATCH v2 04/18] winegstreamer: Find an appropriate demuxer for the source.

Derek Lesho dlesho at codeweavers.com
Wed Apr 1 17:05:25 CDT 2020


We can add a path later which uses decodebin as the demuxer, for use with formats not supported on windows.  (like Theora)

Signed-off-by: Derek Lesho <dlesho at codeweavers.com>
---
 dlls/winegstreamer/gst_cbs.c      |  15 ++++-
 dlls/winegstreamer/gst_cbs.h      |   2 +
 dlls/winegstreamer/media_source.c | 101 +++++++++++++++++++++++++++++-
 3 files changed, 115 insertions(+), 3 deletions(-)

diff --git a/dlls/winegstreamer/gst_cbs.c b/dlls/winegstreamer/gst_cbs.c
index 141ab3c611..51b017ded6 100644
--- a/dlls/winegstreamer/gst_cbs.c
+++ b/dlls/winegstreamer/gst_cbs.c
@@ -358,4 +358,17 @@ gboolean process_bytestream_pad_event_wrapper(GstPad *pad, GstObject *parent, Gs
     call_cb(&cbdata);
 
     return cbdata.u.event_src_data.ret;
-}
\ No newline at end of file
+}
+
+GstBusSyncReply watch_source_bus_wrapper(GstBus *bus, GstMessage *message, gpointer user)
+{
+    struct cb_data cbdata = { WATCH_SOURCE_BUS };
+
+    cbdata.u.watch_bus_data.bus = bus;
+    cbdata.u.watch_bus_data.msg = message;
+    cbdata.u.watch_bus_data.user = user;
+
+    call_cb(&cbdata);
+
+    return cbdata.u.watch_bus_data.ret;
+}
diff --git a/dlls/winegstreamer/gst_cbs.h b/dlls/winegstreamer/gst_cbs.h
index 10e999feea..0d7acaf0b8 100644
--- a/dlls/winegstreamer/gst_cbs.h
+++ b/dlls/winegstreamer/gst_cbs.h
@@ -48,6 +48,7 @@ enum CB_TYPE {
     QUERY_BYTESTREAM,
     ACTIVATE_BYTESTREAM_PAD_MODE,
     PROCESS_BYTESTREAM_PAD_EVENT,
+    WATCH_SOURCE_BUS,
     MEDIA_SOURCE_MAX,
 };
 
@@ -164,5 +165,6 @@ GstFlowReturn pull_from_bytestream_wrapper(GstPad *pad, GstObject *parent, guint
 gboolean query_bytestream_wrapper(GstPad *pad, GstObject *parent, GstQuery *query) DECLSPEC_HIDDEN;
 gboolean activate_bytestream_pad_mode_wrapper(GstPad *pad, GstObject *parent, GstPadMode mode, gboolean activate) DECLSPEC_HIDDEN;
 gboolean process_bytestream_pad_event_wrapper(GstPad *pad, GstObject *parent, GstEvent *event) DECLSPEC_HIDDEN;
+GstBusSyncReply watch_source_bus_wrapper(GstBus *bus, GstMessage *message, gpointer user) DECLSPEC_HIDDEN;
 
 #endif
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c
index 4d2aea54e1..d6380f059e 100644
--- a/dlls/winegstreamer/media_source.c
+++ b/dlls/winegstreamer/media_source.c
@@ -38,7 +38,12 @@ struct media_source
     enum source_type type;
     IMFMediaEventQueue *event_queue;
     IMFByteStream *byte_stream;
-    GstPad *my_src;
+    struct media_stream **streams;
+    ULONG stream_count;
+    GstBus *bus;
+    GstElement *container;
+    GstElement *demuxer;
+    GstPad *my_src, *their_sink;
     enum
     {
         SOURCE_OPENING,
@@ -218,6 +223,13 @@ static HRESULT media_source_teardown(struct media_source *This)
 {
     if (This->my_src)
         gst_object_unref(GST_OBJECT(This->my_src));
+    if (This->their_sink)
+        gst_object_unref(GST_OBJECT(This->their_sink));
+    if (This->container)
+    {
+        gst_element_set_state(This->container, GST_STATE_NULL);
+        gst_object_unref(GST_OBJECT(This->container));
+    }
     if (This->event_queue)
         IMFMediaEventQueue_Release(This->event_queue);
     if (This->byte_stream)
@@ -390,6 +402,37 @@ static gboolean process_bytestream_pad_event(GstPad *pad, GstObject *parent, Gst
     return TRUE;
 }
 
+GstBusSyncReply watch_source_bus(GstBus *bus, GstMessage *message, gpointer user)
+{
+    struct media_stream *This = (struct media_stream *) user;
+    GError *err = NULL;
+    gchar *dbg_info = NULL;
+
+    TRACE("source %p message type %s\n", This, GST_MESSAGE_TYPE_NAME(message));
+
+    switch (message->type)
+    {
+        case GST_MESSAGE_ERROR:
+            gst_message_parse_error(message, &err, &dbg_info);
+            ERR("%s: %s\n", GST_OBJECT_NAME(message->src), err->message);
+            ERR("%s\n", dbg_info);
+            g_error_free(err);
+            g_free(dbg_info);
+            break;
+        case GST_MESSAGE_WARNING:
+            gst_message_parse_warning(message, &err, &dbg_info);
+            WARN("%s: %s\n", GST_OBJECT_NAME(message->src), err->message);
+            WARN("%s\n", dbg_info);
+            g_error_free(err);
+            g_free(dbg_info);
+            break;
+        default:
+            break;
+    }
+
+    return GST_BUS_DROP;
+}
+
 static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_type type, struct media_source **out_media_source)
 {
     GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE(
@@ -399,6 +442,9 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
         source_descs[type].bytestream_caps);
 
     struct media_source *This = heap_alloc_zero(sizeof(*This));
+    GList *demuxer_list_one, *demuxer_list_two;
+    GstElementFactory *demuxer_factory = NULL;
+    int ret;
     HRESULT hr;
 
     if (!This)
@@ -409,7 +455,25 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
     if (FAILED(hr = MFCreateEventQueue(&This->event_queue)))
         goto fail;
 
-    This->state = SOURCE_STOPPED;
+    /* Find demuxer */
+    demuxer_list_one = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DEMUXER, 1);
+
+    demuxer_list_two = gst_element_factory_list_filter(demuxer_list_one, gst_static_caps_get(&source_descs[type].bytestream_caps), GST_PAD_SINK, 0);
+    gst_plugin_feature_list_free(demuxer_list_one);
+
+    if (!(g_list_length(demuxer_list_two)))
+    {
+        ERR("Failed to find demuxer for source.\n");
+        gst_plugin_feature_list_free(demuxer_list_two);
+        hr = E_FAIL;
+        goto fail;
+    }
+
+    demuxer_factory = g_list_first(demuxer_list_two)->data;
+    gst_object_ref(demuxer_factory);
+    gst_plugin_feature_list_free(demuxer_list_two);
+
+    TRACE("Found demuxer %s.\n", GST_ELEMENT_NAME(demuxer_factory));
 
     if (FAILED(hr = IMFByteStream_QueryInterface(bytestream, &IID_IMFByteStream, (void **)&This->byte_stream)))
     {
@@ -423,6 +487,31 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
     gst_pad_set_activatemode_function(This->my_src, activate_bytestream_pad_mode_wrapper);
     gst_pad_set_event_function(This->my_src, process_bytestream_pad_event_wrapper);
 
+    This->container = gst_bin_new(NULL);
+    This->bus = gst_bus_new();
+    gst_bus_set_sync_handler(This->bus, watch_source_bus_wrapper, This, NULL);
+    gst_element_set_bus(This->container, This->bus);
+
+    This->demuxer = gst_element_factory_create(demuxer_factory, NULL);
+    if (!(This->demuxer))
+    {
+        WARN("Failed to create demuxer for source\n");
+        hr = E_OUTOFMEMORY;
+        goto fail;
+    }
+    gst_bin_add(GST_BIN(This->container), This->demuxer);
+
+    This->their_sink = gst_element_get_static_pad(This->demuxer, "sink");
+
+    if ((ret = gst_pad_link(This->my_src, This->their_sink)) < 0)
+    {
+        WARN("Failed to link our bytestream pad to the demuxer input\n");
+        hr = E_OUTOFMEMORY;
+        goto fail;
+    }
+
+    This->state = SOURCE_STOPPED;
+
     This->IMFMediaSource_iface.lpVtbl = &IMFMediaSource_vtbl;
     This->ref = 1;
 
@@ -432,6 +521,8 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, enum source_t
     fail:
     WARN("Failed to construct MFMediaSource, hr %#x.\n", hr);
 
+    if (demuxer_factory)
+        gst_object_unref(demuxer_factory);
     media_source_teardown(This);
     heap_free(This);
     *out_media_source = NULL;
@@ -927,6 +1018,12 @@ void perform_cb_media_source(struct cb_data *cbdata)
             cbdata->u.event_src_data.ret = process_bytestream_pad_event(data->pad, data->parent, data->event);
             break;
         }
+    case WATCH_SOURCE_BUS:
+        {
+            struct watch_bus_data *data = &cbdata->u.watch_bus_data;
+            cbdata->u.watch_bus_data.ret = watch_source_bus(data->bus, data->msg, data->user);
+            break;
+        }
     default:
         {
             ERR("Wrong callback forwarder called\n");
-- 
2.26.0




More information about the wine-devel mailing list