Commit a191a0c2 authored by Zebediah Figura's avatar Zebediah Figura Committed by Alexandre Julliard

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: 's avatarZebediah Figura <z.figura12@gmail.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent f99d307a
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment