mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 12:49:40 +00:00
decodebin2: Link elements before testing if they can reach the READY state
This is made possible by filtering errors. This is required to let harware accelerated element query the video context. The video context is used to determine if the HW is capable, and thus if the element is supported or not. Fixes bug #662330.
This commit is contained in:
parent
54be243757
commit
cf9da5c280
1 changed files with 72 additions and 24 deletions
|
@ -175,6 +175,8 @@ struct _GstDecodeBin
|
|||
gboolean expose_allstreams; /* Whether to expose unknow type streams or not */
|
||||
|
||||
gboolean upstream_seekable; /* if upstream is seekable */
|
||||
|
||||
GList *filtered; /* elements for which error messages are filtered */
|
||||
};
|
||||
|
||||
struct _GstDecodeBinClass
|
||||
|
@ -296,6 +298,7 @@ static void caps_notify_cb (GstPad * pad, GParamSpec * unused,
|
|||
static GstPad *find_sink_pad (GstElement * element);
|
||||
static GstStateChangeReturn gst_decode_bin_change_state (GstElement * element,
|
||||
GstStateChange transition);
|
||||
static void gst_decode_bin_handle_message (GstBin * bin, GstMessage * message);
|
||||
|
||||
#define EXPOSE_LOCK(dbin) G_STMT_START { \
|
||||
GST_LOG_OBJECT (dbin, \
|
||||
|
@ -588,9 +591,11 @@ gst_decode_bin_class_init (GstDecodeBinClass * klass)
|
|||
{
|
||||
GObjectClass *gobject_klass;
|
||||
GstElementClass *gstelement_klass;
|
||||
GstBinClass *gstbin_klass;
|
||||
|
||||
gobject_klass = (GObjectClass *) klass;
|
||||
gstelement_klass = (GstElementClass *) klass;
|
||||
gstbin_klass = (GstBinClass *) klass;
|
||||
|
||||
parent_class = g_type_class_peek_parent (klass);
|
||||
|
||||
|
@ -937,6 +942,9 @@ gst_decode_bin_class_init (GstDecodeBinClass * klass)
|
|||
|
||||
gstelement_klass->change_state =
|
||||
GST_DEBUG_FUNCPTR (gst_decode_bin_change_state);
|
||||
|
||||
gstbin_klass->handle_message =
|
||||
GST_DEBUG_FUNCPTR (gst_decode_bin_handle_message);
|
||||
}
|
||||
|
||||
/* Must be called with factories lock! */
|
||||
|
@ -1731,6 +1739,21 @@ setup_caps_delay:
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
add_error_filter (GstDecodeBin * dbin, GstElement * element)
|
||||
{
|
||||
GST_OBJECT_LOCK (dbin);
|
||||
dbin->filtered = g_list_prepend (dbin->filtered, element);
|
||||
GST_OBJECT_UNLOCK (dbin);
|
||||
}
|
||||
|
||||
static void
|
||||
remove_error_filter (GstDecodeBin * dbin, GstElement * element)
|
||||
{
|
||||
GST_OBJECT_LOCK (dbin);
|
||||
dbin->filtered = g_list_remove (dbin->filtered, element);
|
||||
GST_OBJECT_UNLOCK (dbin);
|
||||
}
|
||||
|
||||
/* connect_pad:
|
||||
*
|
||||
|
@ -1855,45 +1878,52 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad,
|
|||
continue;
|
||||
}
|
||||
|
||||
/* ... activate it ... We do this before adding it to the bin so that we
|
||||
* don't accidentally make it post error messages that will stop
|
||||
* everything. */
|
||||
if ((gst_element_set_state (element,
|
||||
GST_STATE_READY)) == GST_STATE_CHANGE_FAILURE) {
|
||||
GST_WARNING_OBJECT (dbin, "Couldn't set %s to READY",
|
||||
GST_ELEMENT_NAME (element));
|
||||
gst_object_unref (element);
|
||||
continue;
|
||||
}
|
||||
/* Filter errors, this will prevent the element from causing the pipeline
|
||||
* to error while we test it using READY state. */
|
||||
add_error_filter (dbin, element);
|
||||
|
||||
/* 2.3. Find its sink pad, this should work after activating it. */
|
||||
if (!(sinkpad = find_sink_pad (element))) {
|
||||
GST_WARNING_OBJECT (dbin, "Element %s doesn't have a sink pad",
|
||||
GST_ELEMENT_NAME (element));
|
||||
gst_element_set_state (element, GST_STATE_NULL);
|
||||
gst_object_unref (element);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 2.4 add it ... */
|
||||
/* ... add it ... */
|
||||
if (!(gst_bin_add (GST_BIN_CAST (dbin), element))) {
|
||||
GST_WARNING_OBJECT (dbin, "Couldn't add %s to the bin",
|
||||
GST_ELEMENT_NAME (element));
|
||||
gst_object_unref (sinkpad);
|
||||
gst_element_set_state (element, GST_STATE_NULL);
|
||||
remove_error_filter (dbin, element);
|
||||
gst_object_unref (element);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 2.5 ...and try to link */
|
||||
/* Find its sink pad. */
|
||||
if (!(sinkpad = find_sink_pad (element))) {
|
||||
GST_WARNING_OBJECT (dbin, "Element %s doesn't have a sink pad",
|
||||
GST_ELEMENT_NAME (element));
|
||||
remove_error_filter (dbin, element);
|
||||
gst_bin_remove (GST_BIN (dbin), element);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* ... and try to link */
|
||||
if ((gst_pad_link (pad, sinkpad)) != GST_PAD_LINK_OK) {
|
||||
GST_WARNING_OBJECT (dbin, "Link failed on pad %s:%s",
|
||||
GST_DEBUG_PAD_NAME (sinkpad));
|
||||
gst_element_set_state (element, GST_STATE_NULL);
|
||||
remove_error_filter (dbin, element);
|
||||
gst_object_unref (sinkpad);
|
||||
gst_bin_remove (GST_BIN (dbin), element);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* ... activate it ... */
|
||||
if ((gst_element_set_state (element,
|
||||
GST_STATE_READY)) == GST_STATE_CHANGE_FAILURE) {
|
||||
GST_WARNING_OBJECT (dbin, "Couldn't set %s to READY",
|
||||
GST_ELEMENT_NAME (element));
|
||||
remove_error_filter (dbin, element);
|
||||
gst_object_unref (sinkpad);
|
||||
gst_bin_remove (GST_BIN (dbin), element);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Stop filtering errors. */
|
||||
remove_error_filter (dbin, element);
|
||||
|
||||
gst_object_unref (sinkpad);
|
||||
GST_LOG_OBJECT (dbin, "linked on pad %s:%s", GST_DEBUG_PAD_NAME (pad));
|
||||
|
||||
|
@ -3993,6 +4023,24 @@ activate_failed:
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_decode_bin_handle_message (GstBin * bin, GstMessage * msg)
|
||||
{
|
||||
GstDecodeBin *dbin = GST_DECODE_BIN (bin);
|
||||
gboolean drop = FALSE;
|
||||
|
||||
if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
|
||||
GST_OBJECT_LOCK (dbin);
|
||||
drop = (g_list_find (dbin->filtered, GST_MESSAGE_SRC (msg)) != NULL);
|
||||
GST_OBJECT_UNLOCK (dbin);
|
||||
}
|
||||
|
||||
if (drop)
|
||||
gst_message_unref (msg);
|
||||
else
|
||||
GST_BIN_CLASS (parent_class)->handle_message (bin, msg);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_decode_bin_plugin_init (GstPlugin * plugin)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue