[PATCH] winegstreamer: Catch errors while waiting for pin connection.

Zebediah Figura z.figura12 at gmail.com
Wed Jan 1 20:28:41 CST 2020


In the event that the user is missing GStreamer plugins this may allow the
program to terminate gracefully rather than hanging in the init_gst() callback.

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/winegstreamer/gstdemux.c | 33 +++++++++++++++++++++++++++------
 1 file changed, 27 insertions(+), 6 deletions(-)

diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c
index e67efd58eb..7ae70d0a73 100644
--- a/dlls/winegstreamer/gstdemux.c
+++ b/dlls/winegstreamer/gstdemux.c
@@ -68,7 +68,7 @@ struct gstdemux
     GstBus *bus;
     guint64 start, nextofs, nextpullofs, stop;
     ALLOCATOR_PROPERTIES props;
-    HANDLE no_more_pads_event, duration_event;
+    HANDLE no_more_pads_event, duration_event, error_event;
 
     HANDLE push_thread;
 
@@ -1139,6 +1139,7 @@ static GstBusSyncReply watch_bus(GstBus *bus, GstMessage *msg, gpointer data)
         ERR("%s\n", dbg_info);
         g_error_free(err);
         g_free(dbg_info);
+        SetEvent(filter->error_event);
         break;
     case GST_MESSAGE_WARNING:
         gst_message_parse_warning(msg, &err, &dbg_info);
@@ -1225,6 +1226,7 @@ static void gstdemux_destroy(struct strmbase_filter *iface)
 
     CloseHandle(filter->no_more_pads_event);
     CloseHandle(filter->duration_event);
+    CloseHandle(filter->error_event);
 
     /* Don't need to clean up output pins, disconnecting input pin will do that */
     if (filter->sink.pin.peer)
@@ -1498,12 +1500,14 @@ static BOOL gstdecoder_init_gst(struct gstdemux *filter)
     for (i = 0; i < filter->cStreams; ++i)
     {
         struct gstdemux_source *pin = filter->ppPins[i];
+        const HANDLE events[2] = {pin->caps_event, filter->error_event};
 
         pin->seek.llDuration = pin->seek.llStop = duration / 100;
         pin->seek.llCurrent = 0;
         if (!pin->seek.llDuration)
             pin->seek.dwCapabilities = 0;
-        WaitForSingleObject(pin->caps_event, INFINITE);
+        if (WaitForMultipleObjects(2, events, FALSE, INFINITE))
+            return FALSE;
     }
 
     filter->ignore_flush = TRUE;
@@ -1536,6 +1540,7 @@ IUnknown * CALLBACK Gstreamer_Splitter_create(IUnknown *outer, HRESULT *phr)
     strmbase_sink_init(&object->sink, &object->filter, wcsInputPinName, &sink_ops, NULL);
 
     object->no_more_pads_event = CreateEventW(NULL, FALSE, FALSE, NULL);
+    object->error_event = CreateEventW(NULL, TRUE, FALSE, NULL);
     object->init_gst = gstdecoder_init_gst;
     *phr = S_OK;
 
@@ -2171,6 +2176,7 @@ static BOOL wave_parser_init_gst(struct gstdemux *filter)
     struct gstdemux_source *pin;
     GstElement *element;
     LONGLONG duration;
+    HANDLE events[2];
     int ret;
 
     if (!(element = gst_element_factory_make("wavparse", NULL)))
@@ -2214,7 +2220,10 @@ static BOOL wave_parser_init_gst(struct gstdemux *filter)
     if (!pin->seek.llDuration)
         pin->seek.dwCapabilities = 0;
 
-    WaitForSingleObject(pin->caps_event, INFINITE);
+    events[0] = pin->caps_event;
+    events[1] = filter->error_event;
+    if (WaitForMultipleObjects(2, events, FALSE, INFINITE))
+        return FALSE;
 
     filter->ignore_flush = TRUE;
     gst_element_set_state(filter->container, GST_STATE_READY);
@@ -2246,6 +2255,7 @@ IUnknown * CALLBACK wave_parser_create(IUnknown *outer, HRESULT *phr)
     strmbase_filter_init(&object->filter, outer, &CLSID_WAVEParser, &filter_ops);
     strmbase_sink_init(&object->sink, &object->filter, sink_name, &wave_parser_sink_ops, NULL);
     object->init_gst = wave_parser_init_gst;
+    object->error_event = CreateEventW(NULL, TRUE, FALSE, NULL);
     *phr = S_OK;
 
     TRACE("Created WAVE parser %p.\n", object);
@@ -2311,12 +2321,14 @@ static BOOL avi_splitter_init_gst(struct gstdemux *filter)
     for (i = 0; i < filter->cStreams; ++i)
     {
         struct gstdemux_source *pin = filter->ppPins[i];
+        const HANDLE events[2] = {pin->caps_event, filter->error_event};
 
         pin->seek.llDuration = pin->seek.llStop = duration / 100;
         pin->seek.llCurrent = 0;
         if (!pin->seek.llDuration)
             pin->seek.dwCapabilities = 0;
-        WaitForSingleObject(pin->caps_event, INFINITE);
+        if (WaitForMultipleObjects(2, events, FALSE, INFINITE))
+            return FALSE;
     }
 
     filter->ignore_flush = TRUE;
@@ -2349,6 +2361,7 @@ IUnknown * CALLBACK avi_splitter_create(IUnknown *outer, HRESULT *phr)
     strmbase_filter_init(&object->filter, outer, &CLSID_AviSplitter, &filter_ops);
     strmbase_sink_init(&object->sink, &object->filter, sink_name, &avi_splitter_sink_ops, NULL);
     object->no_more_pads_event = CreateEventW(NULL, FALSE, FALSE, NULL);
+    object->error_event = CreateEventW(NULL, TRUE, FALSE, NULL);
     object->init_gst = avi_splitter_init_gst;
     *phr = S_OK;
 
@@ -2383,6 +2396,7 @@ static BOOL mpeg_splitter_init_gst(struct gstdemux *filter)
     struct gstdemux_source *pin;
     GstElement *element;
     LONGLONG duration;
+    HANDLE events[2];
     int ret;
 
     if (!(element = gst_element_factory_make("mpegaudioparse", NULL)))
@@ -2419,14 +2433,20 @@ static BOOL mpeg_splitter_init_gst(struct gstdemux *filter)
         return FALSE;
     }
 
-    WaitForSingleObject(filter->duration_event, INFINITE);
+    events[0] = filter->duration_event;
+    events[1] = filter->error_event;
+    if (WaitForMultipleObjects(2, events, FALSE, INFINITE))
+        return FALSE;
+
     gst_pad_query_duration(pin->their_src, GST_FORMAT_TIME, &duration);
     pin->seek.llDuration = pin->seek.llStop = duration / 100;
     pin->seek.llCurrent = 0;
     if (!pin->seek.llDuration)
         pin->seek.dwCapabilities = 0;
 
-    WaitForSingleObject(pin->caps_event, INFINITE);
+    events[0] = pin->caps_event;
+    if (WaitForMultipleObjects(2, events, FALSE, INFINITE))
+        return FALSE;
 
     filter->ignore_flush = TRUE;
     gst_element_set_state(filter->container, GST_STATE_READY);
@@ -2486,6 +2506,7 @@ IUnknown * CALLBACK mpeg_splitter_create(IUnknown *outer, HRESULT *phr)
     object->IAMStreamSelect_iface.lpVtbl = &stream_select_vtbl;
 
     object->duration_event = CreateEventW(NULL, FALSE, FALSE, NULL);
+    object->error_event = CreateEventW(NULL, TRUE, FALSE, NULL);
     object->init_gst = mpeg_splitter_init_gst;
     *phr = S_OK;
 
-- 
2.24.1




More information about the wine-devel mailing list