Module: wine Branch: master Commit: a191a0c23a62288ba8906283c5727c5e5a2ccca4 URL: https://source.winehq.org/git/wine.git/?a=commit;h=a191a0c23a62288ba8906283c...
Author: Zebediah Figura z.figura12@gmail.com Date: Wed Jan 1 20:28:41 2020 -0600
winegstreamer: Catch errors while waiting for pin connection.
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@gmail.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
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;