mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 11:45:25 +00:00
tests: fix test-effect-switch
Make it into an example of how to dynamically change an element in a playing pipeline using pad blocking.
This commit is contained in:
parent
cdb22274e6
commit
7b6d465586
1 changed files with 66 additions and 64 deletions
|
@ -28,8 +28,9 @@
|
|||
static gchar *opt_effects = NULL;
|
||||
|
||||
#define DEFAULT_EFFECTS "identity,exclusion,navigationtest," \
|
||||
"agingtv,videoflip,vertigotv,gaussianblur,identity"
|
||||
"agingtv,videoflip,vertigotv,gaussianblur,shagadelictv,edgetv"
|
||||
|
||||
static GstPad *blockpad;
|
||||
static GstElement *conv_before;
|
||||
static GstElement *conv_after;
|
||||
static GstElement *cur_effect;
|
||||
|
@ -37,86 +38,80 @@ static GstElement *pipeline;
|
|||
|
||||
static GQueue effects = G_QUEUE_INIT;
|
||||
|
||||
|
||||
#if 0
|
||||
static GstPadProbeReturn
|
||||
pad_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
|
||||
{
|
||||
GstElement *next = user_data;
|
||||
|
||||
GST_ERROR_OBJECT (pad, "pad is idle now");
|
||||
|
||||
gst_element_set_state (cur_effect, GST_STATE_NULL);
|
||||
|
||||
/* remove unlinks automatically */
|
||||
GST_ERROR_OBJECT (pipeline, "removing %" GST_PTR_FORMAT, cur_effect);
|
||||
gst_bin_remove (GST_BIN (pipeline), cur_effect);
|
||||
GST_ERROR_OBJECT (pipeline, "adding %" GST_PTR_FORMAT, next);
|
||||
gst_bin_add (GST_BIN (pipeline), next);
|
||||
GST_ERROR_OBJECT (pipeline, "linking..");
|
||||
gst_element_link_many (conv_before, next, conv_after, NULL);
|
||||
gst_element_set_state (next, GST_STATE_PLAYING);
|
||||
cur_effect = next;
|
||||
/* FIXME: this seems to not work */
|
||||
gst_pad_remove_probe (pad, info->id);
|
||||
g_print ("Done\n");
|
||||
/* FIXME: returning PROBE_REMOVE from an idle probe seems to do nothing */
|
||||
return GST_PAD_PROBE_REMOVE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
timeout_cb (gpointer user_data)
|
||||
event_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
|
||||
{
|
||||
GMainLoop *loop = user_data;
|
||||
GstElement *next;
|
||||
gulong block_id;
|
||||
GstPad *pad;
|
||||
|
||||
if (GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) != GST_EVENT_EOS)
|
||||
return GST_PAD_PROBE_OK;
|
||||
|
||||
gst_pad_remove_probe (pad, GST_PAD_PROBE_INFO_ID (info));
|
||||
|
||||
/* push current event back into the queue */
|
||||
g_queue_push_tail (&effects, gst_object_ref (cur_effect));
|
||||
|
||||
/* take next effect from the queue */
|
||||
next = g_queue_pop_head (&effects);
|
||||
|
||||
if (next == NULL) {
|
||||
GST_DEBUG_OBJECT (pad, "no more effects");
|
||||
g_main_loop_quit (loop);
|
||||
return FALSE;
|
||||
return GST_PAD_PROBE_DROP;
|
||||
}
|
||||
|
||||
g_print ("Switching from '%s' to '%s'..\n", GST_OBJECT_NAME (cur_effect),
|
||||
GST_OBJECT_NAME (next));
|
||||
|
||||
pad = gst_element_get_static_pad (conv_before, "src");
|
||||
|
||||
block_id =
|
||||
gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BLOCK, NULL, NULL, NULL);
|
||||
g_print ("Blocked\n");
|
||||
gst_pad_remove_probe (pad, block_id);
|
||||
gst_element_set_state (cur_effect, GST_STATE_NULL);
|
||||
|
||||
/* remove unlinks automatically */
|
||||
GST_DEBUG_OBJECT (pipeline, "removing %" GST_PTR_FORMAT, cur_effect);
|
||||
gst_bin_remove (GST_BIN (pipeline), cur_effect);
|
||||
g_print ("Removed\n");
|
||||
gst_bin_add (GST_BIN (pipeline), next);
|
||||
g_print ("Added\n");
|
||||
gst_element_link_many (conv_before, next, conv_after, NULL);
|
||||
g_print ("Re-linked\n");
|
||||
gst_element_set_state (next, GST_STATE_PLAYING);
|
||||
cur_effect = next;
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
/* FIXME: we have to remove the block before we link, otherwise the
|
||||
* caps queries on linking will deadlock us - check if that's intentional */
|
||||
#if 0
|
||||
gst_pad_remove_probe (pad, block_id);
|
||||
#endif
|
||||
g_print ("Done\n\n\n");
|
||||
|
||||
/* FIXME: waiting for the pad to be idle, and then relinking from there
|
||||
* doesn't seem to work very well either for some reason, and returning
|
||||
* GST_PAD_PROBE_REMOVE does not seem to work. Doing the same from a
|
||||
* BLOCKING callback has the same problem as above */
|
||||
#if 0
|
||||
gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_IDLE, pad_probe_cb, next, NULL);
|
||||
#endif
|
||||
GST_DEBUG_OBJECT (pipeline, "adding %" GST_PTR_FORMAT, next);
|
||||
gst_bin_add (GST_BIN (pipeline), next);
|
||||
|
||||
GST_DEBUG_OBJECT (pipeline, "linking..");
|
||||
gst_element_link_many (conv_before, next, conv_after, NULL);
|
||||
|
||||
gst_element_set_state (next, GST_STATE_PLAYING);
|
||||
|
||||
cur_effect = next;
|
||||
GST_DEBUG_OBJECT (pipeline, "done");
|
||||
|
||||
return GST_PAD_PROBE_DROP;
|
||||
}
|
||||
|
||||
static GstPadProbeReturn
|
||||
pad_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
|
||||
{
|
||||
GstPad *srcpad, *sinkpad;
|
||||
|
||||
GST_DEBUG_OBJECT (pad, "pad is blocked now");
|
||||
|
||||
/* remove the probe first */
|
||||
gst_pad_remove_probe (pad, GST_PAD_PROBE_INFO_ID (info));
|
||||
|
||||
/* install new probe for EOS */
|
||||
srcpad = gst_element_get_static_pad (cur_effect, "src");
|
||||
gst_pad_add_probe (srcpad, GST_PAD_PROBE_TYPE_BLOCK |
|
||||
GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, event_probe_cb, user_data, NULL);
|
||||
gst_object_unref (srcpad);
|
||||
|
||||
/* push EOS into the element, the probe will be fired when the
|
||||
* EOS leaves the effect and it has thus drained all of its data */
|
||||
sinkpad = gst_element_get_static_pad (cur_effect, "sink");
|
||||
gst_pad_send_event (sinkpad, gst_event_new_eos ());
|
||||
gst_object_unref (sinkpad);
|
||||
|
||||
return GST_PAD_PROBE_OK;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
timeout_cb (gpointer user_data)
|
||||
{
|
||||
gst_pad_add_probe (blockpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
|
||||
pad_probe_cb, user_data, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -175,8 +170,13 @@ main (int argc, char **argv)
|
|||
effect_names = g_strsplit (DEFAULT_EFFECTS, ",", -1);
|
||||
|
||||
for (e = effect_names; e != NULL && *e != NULL; ++e) {
|
||||
g_print ("Adding effect '%s'\n", *e);
|
||||
g_queue_push_tail (&effects, gst_element_factory_make (*e, NULL));
|
||||
GstElement *el;
|
||||
|
||||
el = gst_element_factory_make (*e, NULL);
|
||||
if (el) {
|
||||
g_print ("Adding effect '%s'\n", *e);
|
||||
g_queue_push_tail (&effects, el);
|
||||
}
|
||||
}
|
||||
|
||||
pipeline = gst_pipeline_new ("pipeline");
|
||||
|
@ -192,6 +192,8 @@ main (int argc, char **argv)
|
|||
|
||||
q1 = gst_element_factory_make ("queue", NULL);
|
||||
|
||||
blockpad = gst_element_get_static_pad (q1, "src");
|
||||
|
||||
conv_before = gst_element_factory_make ("videoconvert", NULL);
|
||||
|
||||
effect = g_queue_pop_head (&effects);
|
||||
|
|
Loading…
Reference in a new issue