[PATCH resend 4/5] winegstreamer: Find an appropriate demuxer for the source.
Zebediah Figura
zfigura at codeweavers.com
Mon Apr 6 14:02:12 CDT 2020
On 4/6/20 12:57 PM, Derek Lesho wrote:
> We can add a path later which uses decodebin as the demuxer, for use with formats not supported on windows. (like Theora)
I still don't see a good reason why this can't be the general solution
for all formats.
>
> 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 c0d35df6fa..d3ed74876e 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;
> @@ -930,6 +1021,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");
>
More information about the wine-devel
mailing list