[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