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
@ -28,8 +28,9 @@
|
|||||||
static gchar *opt_effects = NULL;
|
static gchar *opt_effects = NULL;
|
||||||
|
|
||||||
#define DEFAULT_EFFECTS "identity,exclusion,navigationtest," \
|
#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_before;
|
||||||
static GstElement *conv_after;
|
static GstElement *conv_after;
|
||||||
static GstElement *cur_effect;
|
static GstElement *cur_effect;
|
||||||
@ -37,86 +38,80 @@ static GstElement *pipeline;
|
|||||||
|
|
||||||
static GQueue effects = G_QUEUE_INIT;
|
static GQueue effects = G_QUEUE_INIT;
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
static GstPadProbeReturn
|
static GstPadProbeReturn
|
||||||
pad_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
|
event_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)
|
|
||||||
{
|
{
|
||||||
GMainLoop *loop = user_data;
|
GMainLoop *loop = user_data;
|
||||||
GstElement *next;
|
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));
|
g_queue_push_tail (&effects, gst_object_ref (cur_effect));
|
||||||
|
/* take next effect from the queue */
|
||||||
next = g_queue_pop_head (&effects);
|
next = g_queue_pop_head (&effects);
|
||||||
|
|
||||||
if (next == NULL) {
|
if (next == NULL) {
|
||||||
|
GST_DEBUG_OBJECT (pad, "no more effects");
|
||||||
g_main_loop_quit (loop);
|
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),
|
g_print ("Switching from '%s' to '%s'..\n", GST_OBJECT_NAME (cur_effect),
|
||||||
GST_OBJECT_NAME (next));
|
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);
|
gst_element_set_state (cur_effect, GST_STATE_NULL);
|
||||||
|
|
||||||
/* remove unlinks automatically */
|
/* remove unlinks automatically */
|
||||||
|
GST_DEBUG_OBJECT (pipeline, "removing %" GST_PTR_FORMAT, cur_effect);
|
||||||
gst_bin_remove (GST_BIN (pipeline), 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
|
GST_DEBUG_OBJECT (pipeline, "adding %" GST_PTR_FORMAT, next);
|
||||||
* doesn't seem to work very well either for some reason, and returning
|
gst_bin_add (GST_BIN (pipeline), next);
|
||||||
* GST_PAD_PROBE_REMOVE does not seem to work. Doing the same from a
|
|
||||||
* BLOCKING callback has the same problem as above */
|
GST_DEBUG_OBJECT (pipeline, "linking..");
|
||||||
#if 0
|
gst_element_link_many (conv_before, next, conv_after, NULL);
|
||||||
gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_IDLE, pad_probe_cb, next, NULL);
|
|
||||||
#endif
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -175,8 +170,13 @@ main (int argc, char **argv)
|
|||||||
effect_names = g_strsplit (DEFAULT_EFFECTS, ",", -1);
|
effect_names = g_strsplit (DEFAULT_EFFECTS, ",", -1);
|
||||||
|
|
||||||
for (e = effect_names; e != NULL && *e != NULL; ++e) {
|
for (e = effect_names; e != NULL && *e != NULL; ++e) {
|
||||||
|
GstElement *el;
|
||||||
|
|
||||||
|
el = gst_element_factory_make (*e, NULL);
|
||||||
|
if (el) {
|
||||||
g_print ("Adding effect '%s'\n", *e);
|
g_print ("Adding effect '%s'\n", *e);
|
||||||
g_queue_push_tail (&effects, gst_element_factory_make (*e, NULL));
|
g_queue_push_tail (&effects, el);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeline = gst_pipeline_new ("pipeline");
|
pipeline = gst_pipeline_new ("pipeline");
|
||||||
@ -192,6 +192,8 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
q1 = gst_element_factory_make ("queue", NULL);
|
q1 = gst_element_factory_make ("queue", NULL);
|
||||||
|
|
||||||
|
blockpad = gst_element_get_static_pad (q1, "src");
|
||||||
|
|
||||||
conv_before = gst_element_factory_make ("videoconvert", NULL);
|
conv_before = gst_element_factory_make ("videoconvert", NULL);
|
||||||
|
|
||||||
effect = g_queue_pop_head (&effects);
|
effect = g_queue_pop_head (&effects);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user