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;
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;
- g_queue_push_tail (&effects, gst_object_ref (cur_effect));
+ if (GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) != GST_EVENT_EOS)
+ return GST_PAD_PROBE_OK;
- next = g_queue_pop_head (&effects);
+ 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_DEBUG_OBJECT (pipeline, "adding %" GST_PTR_FORMAT, next);
gst_bin_add (GST_BIN (pipeline), next);
- g_print ("Added\n");
+
+ GST_DEBUG_OBJECT (pipeline, "linking..");
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, "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;
}
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");
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);