gst/playback/gstplaybasebin.*: Prepare to handle errors betters.

Original commit message from CVS:
* gst/playback/gstplaybasebin.c: (group_commit), (probe_triggered):
* gst/playback/gstplaybasebin.h:
Prepare to handle errors betters.

* gst/playback/gstplaybin.c: (add_sink), (setup_sinks):
Set sinks to PAUSED first before adding and linking them so that
we don't interrupt dataflow.
This commit is contained in:
Wim Taymans 2005-11-28 15:56:03 +00:00
parent 3f05db1828
commit 078d7c5e8c
4 changed files with 62 additions and 27 deletions

View file

@ -1,3 +1,13 @@
2005-11-28 Wim Taymans <wim@fluendo.com>
* gst/playback/gstplaybasebin.c: (group_commit), (probe_triggered):
* gst/playback/gstplaybasebin.h:
Prepare to handle errors betters.
* gst/playback/gstplaybin.c: (add_sink), (setup_sinks):
Set sinks to PAUSED first before adding and linking them so that
we don't interrupt dataflow.
2005-11-28 Wim Taymans <wim@fluendo.com> 2005-11-28 Wim Taymans <wim@fluendo.com>
* gst-libs/gst/audio/TODO: * gst-libs/gst/audio/TODO:

View file

@ -355,6 +355,7 @@ group_commit (GstPlayBaseBin * play_base_bin, gboolean fatal, gboolean subtitle)
{ {
GstPlayBaseGroup *group; GstPlayBaseGroup *group;
gboolean had_active_group; gboolean had_active_group;
gboolean res;
GROUP_LOCK (play_base_bin); GROUP_LOCK (play_base_bin);
group = play_base_bin->building_group; group = play_base_bin->building_group;
@ -408,7 +409,7 @@ group_commit (GstPlayBaseBin * play_base_bin, gboolean fatal, gboolean subtitle)
setup_substreams (play_base_bin); setup_substreams (play_base_bin);
GST_DEBUG ("Emitting signal"); GST_DEBUG ("Emitting signal");
GST_PLAY_BASE_BIN_GET_CLASS (play_base_bin)-> res = GST_PLAY_BASE_BIN_GET_CLASS (play_base_bin)->
setup_output_pads (play_base_bin, group); setup_output_pads (play_base_bin, group);
GST_DEBUG ("done"); GST_DEBUG ("done");
@ -782,6 +783,7 @@ probe_triggered (GstPad * pad, GstEvent * event, gpointer user_data)
GstPlayBaseGroup *group; GstPlayBaseGroup *group;
GstPlayBaseBin *play_base_bin; GstPlayBaseBin *play_base_bin;
GstStreamInfo *info = GST_STREAM_INFO (user_data); GstStreamInfo *info = GST_STREAM_INFO (user_data);
gboolean res;
group = (GstPlayBaseGroup *) g_object_get_data (G_OBJECT (info), "group"); group = (GstPlayBaseGroup *) g_object_get_data (G_OBJECT (info), "group");
play_base_bin = group->bin; play_base_bin = group->bin;
@ -837,7 +839,7 @@ probe_triggered (GstPad * pad, GstEvent * event, gpointer user_data)
setup_substreams (play_base_bin); setup_substreams (play_base_bin);
GST_DEBUG ("switching to next group %p - emitting signal", group); GST_DEBUG ("switching to next group %p - emitting signal", group);
/* and signal the new group */ /* and signal the new group */
GST_PLAY_BASE_BIN_GET_CLASS (play_base_bin)-> res = GST_PLAY_BASE_BIN_GET_CLASS (play_base_bin)->
setup_output_pads (play_base_bin, group); setup_output_pads (play_base_bin, group);
GROUP_UNLOCK (play_base_bin); GROUP_UNLOCK (play_base_bin);

View file

@ -92,7 +92,7 @@ struct _GstPlayBaseBinClass {
GstPipelineClass parent_class; GstPipelineClass parent_class;
/* virtual fuctions */ /* virtual fuctions */
void (*setup_output_pads) (GstPlayBaseBin *play_base_bin, gboolean (*setup_output_pads) (GstPlayBaseBin *play_base_bin,
GstPlayBaseGroup *group); GstPlayBaseGroup *group);
}; };

View file

@ -95,7 +95,7 @@ static void gst_play_bin_class_init (GstPlayBinClass * klass);
static void gst_play_bin_init (GstPlayBin * play_bin); static void gst_play_bin_init (GstPlayBin * play_bin);
static void gst_play_bin_dispose (GObject * object); static void gst_play_bin_dispose (GObject * object);
static void setup_sinks (GstPlayBaseBin * play_base_bin, static gboolean setup_sinks (GstPlayBaseBin * play_base_bin,
GstPlayBaseGroup * group); GstPlayBaseGroup * group);
static void remove_sinks (GstPlayBin * play_bin); static void remove_sinks (GstPlayBin * play_bin);
@ -762,15 +762,9 @@ static gboolean
add_sink (GstPlayBin * play_bin, GstElement * sink, GstPad * srcpad) add_sink (GstPlayBin * play_bin, GstElement * sink, GstPad * srcpad)
{ {
GstPad *sinkpad; GstPad *sinkpad;
GstPadLinkReturn res; GstPadLinkReturn linkres;
GstElement *parent; GstElement *parent;
GstStateChangeReturn stateret;
gst_bin_add (GST_BIN (play_bin), sink);
/* we found a sink for this stream, now try to install it */
sinkpad = gst_element_get_pad (sink, "sink");
res = gst_pad_link (srcpad, sinkpad);
gst_object_unref (sinkpad);
/* this is only for debugging */ /* this is only for debugging */
parent = gst_pad_get_parent_element (srcpad); parent = gst_pad_get_parent_element (srcpad);
@ -780,30 +774,56 @@ add_sink (GstPlayBin * play_bin, GstElement * sink, GstPad * srcpad)
gst_object_unref (parent); gst_object_unref (parent);
} }
/* bring it to the PAUSED state so we can link to the peer without
* breaking the flow */
if ((stateret = gst_element_set_state (sink, GST_STATE_PAUSED)) ==
GST_STATE_CHANGE_FAILURE)
goto state_failed;
gst_bin_add (GST_BIN (play_bin), sink);
/* we found a sink for this stream, now try to install it */
sinkpad = gst_element_get_pad (sink, "sink");
linkres = gst_pad_link (srcpad, sinkpad);
gst_object_unref (sinkpad);
/* try to link the pad of the sink to the stream */ /* try to link the pad of the sink to the stream */
if (res < 0) { if (GST_PAD_LINK_FAILED (linkres))
goto link_failed;
/* we got the sink succesfully linked, now keep the sink
* in out internal list */
play_bin->sinks = g_list_prepend (play_bin->sinks, sink);
return TRUE;
/* ERRORS */
state_failed:
{
GST_DEBUG_OBJECT (play_bin, "state change failure when adding sink");
return FALSE;
}
link_failed:
{
gchar *capsstr; gchar *capsstr;
GstCaps *caps;
/* could not link this stream */ /* could not link this stream */
capsstr = gst_caps_to_string (gst_pad_get_caps (srcpad)); caps = gst_pad_get_caps (srcpad);
g_warning ("could not link %s: %d", capsstr, res); capsstr = gst_caps_to_string (caps);
g_warning ("could not link %s: %d", capsstr, linkres);
GST_DEBUG_OBJECT (play_bin,
"link failed when adding sink, caps %s, reason %d", capsstr, linkres);
g_free (capsstr); g_free (capsstr);
g_free (caps);
gst_element_set_state (sink, GST_STATE_NULL); gst_element_set_state (sink, GST_STATE_NULL);
gst_bin_remove (GST_BIN (play_bin), sink); gst_bin_remove (GST_BIN (play_bin), sink);
} else { return FALSE;
/* we got the sink succesfully linked, now keep the sink
* in out internal list */
play_bin->sinks = g_list_prepend (play_bin->sinks, sink);
gst_element_set_state (sink,
(GST_STATE (play_bin) == GST_STATE_PLAYING) ?
GST_STATE_PLAYING : GST_STATE_PAUSED);
} }
return res;
} }
static void static gboolean
setup_sinks (GstPlayBaseBin * play_base_bin, GstPlayBaseGroup * group) setup_sinks (GstPlayBaseBin * play_base_bin, GstPlayBaseGroup * group)
{ {
GstPlayBin *play_bin = GST_PLAY_BIN (play_base_bin); GstPlayBin *play_bin = GST_PLAY_BIN (play_base_bin);
@ -812,6 +832,7 @@ setup_sinks (GstPlayBaseBin * play_base_bin, GstPlayBaseGroup * group)
gboolean need_text = FALSE; gboolean need_text = FALSE;
GstPad *textsrcpad = NULL, *textsinkpad = NULL, *pad; GstPad *textsrcpad = NULL, *textsinkpad = NULL, *pad;
GstElement *sink; GstElement *sink;
gboolean res = TRUE;
/* get rid of existing sinks */ /* get rid of existing sinks */
if (play_bin->sinks) { if (play_bin->sinks) {
@ -849,7 +870,7 @@ setup_sinks (GstPlayBaseBin * play_base_bin, GstPlayBaseGroup * group)
} }
pad = gst_element_get_pad (group->type[GST_STREAM_TYPE_AUDIO - 1].preroll, pad = gst_element_get_pad (group->type[GST_STREAM_TYPE_AUDIO - 1].preroll,
"src"); "src");
add_sink (play_bin, sink, pad); res = add_sink (play_bin, sink, pad);
gst_object_unref (pad); gst_object_unref (pad);
} }
@ -870,7 +891,7 @@ setup_sinks (GstPlayBaseBin * play_base_bin, GstPlayBaseGroup * group)
} }
pad = gst_element_get_pad (group->type[GST_STREAM_TYPE_VIDEO - 1].preroll, pad = gst_element_get_pad (group->type[GST_STREAM_TYPE_VIDEO - 1].preroll,
"src"); "src");
add_sink (play_bin, sink, pad); res = add_sink (play_bin, sink, pad);
gst_object_unref (pad); gst_object_unref (pad);
} }
@ -881,6 +902,8 @@ setup_sinks (GstPlayBaseBin * play_base_bin, GstPlayBaseGroup * group)
gst_bin_remove (GST_BIN (play_bin), play_bin->fakesink); gst_bin_remove (GST_BIN (play_bin), play_bin->fakesink);
play_bin->fakesink = NULL; play_bin->fakesink = NULL;
} }
return res;
} }
/* Send an event to our sinks until one of them works; don't then send to the /* Send an event to our sinks until one of them works; don't then send to the