[rhythmbox] xfade: use common tee/filter implementation (bug 499052)
- From: Jonathan Matthew <jmatthew src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [rhythmbox] xfade: use common tee/filter implementation (bug 499052)
- Date: Sun, 8 Nov 2009 12:11:31 +0000 (UTC)
commit 8b3120d4e81031c3e2bf8e1e7d1eb2cd1e36c38c
Author: Jonathan Matthew <jonathan d14n org>
Date: Sun Nov 8 21:56:20 2009 +1000
xfade: use common tee/filter implementation (bug 499052)
backends/gstreamer/rb-player-gst-xfade.c | 365 ++----------------------------
1 files changed, 14 insertions(+), 351 deletions(-)
---
diff --git a/backends/gstreamer/rb-player-gst-xfade.c b/backends/gstreamer/rb-player-gst-xfade.c
index fcc891b..e3f6af2 100644
--- a/backends/gstreamer/rb-player-gst-xfade.c
+++ b/backends/gstreamer/rb-player-gst-xfade.c
@@ -263,6 +263,8 @@ struct _RBPlayerGstXFadePrivate
GstElement *sink;
GstElement *tee;
GstElement *filterbin;
+ GstElement *filteridentity;
+ GstElement *filterconvert;
GstElement *volume_handler;
enum {
SINK_NULL,
@@ -2984,12 +2986,10 @@ create_sink (RBPlayerGstXFade *player, GError **error)
{
GstElement *audiotestsrc;
GstElement *audioconvert;
- GstElement *audioconvert2;
GstElement *audioresample;
GstElement *capsfilter;
GstElement *queue;
GstCaps *caps;
- GstPad *pad;
GstPad *filterpad;
GstPad *outputghostpad;
GstPad *ghostpad;
@@ -3027,7 +3027,8 @@ create_sink (RBPlayerGstXFade *player, GError **error)
player->priv->tee = gst_element_factory_make ("tee", "outputtee");
queue = gst_element_factory_make ("queue", NULL);
player->priv->volume = gst_element_factory_make ("volume", "outputvolume");
- player->priv->filterbin = gst_bin_new ("filterbin");
+ player->priv->filterbin = rb_gst_create_filter_bin ();
+ capsfilter = gst_element_factory_make ("capsfilter", NULL);
if (player->priv->pipeline == NULL ||
player->priv->adder == NULL ||
player->priv->capsfilter == NULL ||
@@ -3036,7 +3037,8 @@ create_sink (RBPlayerGstXFade *player, GError **error)
player->priv->tee == NULL ||
queue == NULL ||
player->priv->volume == NULL ||
- player->priv->filterbin == NULL) {
+ player->priv->filterbin == NULL ||
+ capsfilter == NULL) {
/* we could include the element name in the error message,
* but these are all fundamental elements that are always
* available.
@@ -3061,20 +3063,7 @@ create_sink (RBPlayerGstXFade *player, GError **error)
}
g_object_set (player->priv->capsfilter, "caps", caps, NULL);
-
- /* set up initial filterbin contents */
- audioconvert2 = gst_element_factory_make ("audioconvert", NULL);
- gst_bin_add (GST_BIN (player->priv->filterbin), audioconvert2);
-
- pad = gst_element_get_static_pad (audioconvert2, "sink");
- gst_element_add_pad (player->priv->filterbin,
- gst_ghost_pad_new ("sink", pad));
- gst_object_unref (pad);
-
- pad = gst_element_get_static_pad (audioconvert2, "src");
- gst_element_add_pad (player->priv->filterbin,
- gst_ghost_pad_new ("src", pad));
- gst_object_unref (pad);
+ g_object_set (capsfilter, "caps", caps, NULL);
g_object_set (queue, "max-size-buffers", 10, NULL);
@@ -3084,6 +3073,7 @@ create_sink (RBPlayerGstXFade *player, GError **error)
player->priv->filterbin,
audioconvert,
audioresample,
+ capsfilter,
player->priv->tee,
queue,
player->priv->sink,
@@ -3093,6 +3083,7 @@ create_sink (RBPlayerGstXFade *player, GError **error)
player->priv->filterbin,
audioconvert,
audioresample,
+ capsfilter,
player->priv->tee,
queue,
player->priv->sink,
@@ -3861,166 +3852,6 @@ rb_player_gst_xfade_get_time (RBPlayer *iplayer)
return pos;
}
-/* RBPlayerGstTee implementation */
-
-typedef struct {
- RBPlayerGstXFade *player;
- GstElement *element;
-} RBPlayerGstXFadePipelineOp;
-
-
-static RBPlayerGstXFadePipelineOp *
-new_pipeline_op (RBPlayerGstXFade *player, GstElement *element)
-{
- RBPlayerGstXFadePipelineOp *op;
- op = g_new0 (RBPlayerGstXFadePipelineOp, 1);
- op->player = g_object_ref (player);
- op->element = g_object_ref (element);
- return op;
-}
-
-static void
-free_pipeline_op (RBPlayerGstXFadePipelineOp *op)
-{
- g_object_unref (op->player);
- g_object_unref (op->element);
- g_free (op);
-}
-
-static void
-pipeline_op_done (GstPad *pad, gboolean blocked, GstPad *new_pad)
-{
- GstEvent *segment;
- if (new_pad == NULL)
- return;
-
- /* send a very unimaginative new segment through the new pad */
- segment = gst_event_new_new_segment (TRUE,
- 1.0,
- GST_FORMAT_DEFAULT,
- 0,
- GST_CLOCK_TIME_NONE,
- 0);
- gst_pad_send_event (new_pad, segment);
- gst_object_unref (new_pad);
-}
-
-static void
-really_add_tee (GstPad *pad, gboolean blocked, RBPlayerGstXFadePipelineOp *op)
-{
- GstElement *queue;
- GstElement *audioconvert;
- GstElement *bin;
- GstPad *sinkpad;
- GstPad *ghostpad;
-
- rb_debug ("really adding tee %p", op->element);
-
- /* set up containing bin */
- bin = gst_bin_new (NULL);
- queue = gst_element_factory_make ("queue", NULL);
- audioconvert = gst_element_factory_make ("audioconvert", NULL);
-
- /* The bin contains elements that change state asynchronously
- * and not as part of a state change in the entire pipeline.
- * With GStreamer core 0.10.13+, we need to ask the bin to
- * handle this specifically using its 'async-handling' property.
- */
- if (g_object_class_find_property (G_OBJECT_GET_CLASS (bin), "async-handling")) {
- g_object_set (bin, "async-handling", TRUE, NULL);
- }
-
- g_object_set (queue, "max-size-buffers", 3, NULL);
-
- gst_bin_add_many (GST_BIN (bin), queue, audioconvert, op->element, NULL);
- gst_element_link_many (queue, audioconvert, op->element, NULL);
-
- /* add ghost pad */
- sinkpad = gst_element_get_static_pad (queue, "sink");
- ghostpad = gst_ghost_pad_new ("sink", sinkpad);
- gst_element_add_pad (bin, ghostpad);
- gst_object_unref (sinkpad);
-
- /* add it into the pipeline */
- gst_bin_add (GST_BIN (op->player->priv->outputbin), bin);
- gst_element_link (op->player->priv->tee, bin);
-
- /* if we're supposed to be playing, unblock the sink */
- if (blocked) {
- rb_debug ("unblocking pad after adding tee");
-
- gst_element_set_state (op->player->priv->outputbin,
- GST_STATE_PLAYING);
- gst_object_ref (ghostpad);
- gst_pad_set_blocked_async (pad,
- FALSE,
- (GstPadBlockCallback)pipeline_op_done,
- ghostpad);
- } else {
- gst_element_set_state (bin, GST_STATE_PAUSED);
- gst_object_ref (ghostpad);
- pipeline_op_done (NULL, FALSE, ghostpad);
- }
-
- _rb_player_gst_tee_emit_tee_inserted (RB_PLAYER_GST_TEE (op->player), op->element);
-
- free_pipeline_op (op);
-}
-
-static void
-really_remove_tee (GstPad *pad, gboolean blocked, RBPlayerGstXFadePipelineOp *op)
-{
- GstElement *bin;
-
- rb_debug ("really removing tee %p", op->element);
-
- _rb_player_gst_tee_emit_tee_pre_remove (RB_PLAYER_GST_TEE (op->player), op->element);
-
- /* find bin, remove everything */
- bin = GST_ELEMENT_PARENT (op->element);
- g_object_ref (bin);
- gst_bin_remove (GST_BIN (op->player->priv->outputbin), bin);
-
- gst_element_set_state (bin, GST_STATE_NULL);
- gst_bin_remove (GST_BIN (bin), op->element);
- g_object_unref (bin);
-
- /* if we're supposed to be playing, unblock the sink */
- if (blocked) {
- rb_debug ("unblocking pad after removing tee");
- gst_pad_set_blocked_async (pad, FALSE, (GstPadBlockCallback)pipeline_op_done, NULL);
- }
-
- free_pipeline_op (op);
-}
-
-static gboolean
-pipeline_op (RBPlayerGstXFade *player,
- GstElement *element,
- GstElement *previous_element,
- GstPadBlockCallback callback)
-{
- RBPlayerGstXFadePipelineOp *op;
- GstPad *block_pad;
-
- op = new_pipeline_op (player, element);
-
- block_pad = gst_element_get_static_pad (previous_element, "src");
- if (player->priv->sink_state == SINK_PLAYING) {
- rb_debug ("blocking the volume src pad to perform an operation");
- gst_pad_set_blocked_async (block_pad,
- TRUE,
- callback,
- op);
- } else {
- rb_debug ("sink not playing; calling op directly");
- (*callback) (block_pad, FALSE, op);
- }
-
- gst_object_unref (block_pad);
- return TRUE;
-}
-
static gboolean
rb_player_gst_xfade_add_tee (RBPlayerGstTee *iplayer, GstElement *element)
{
@@ -4030,10 +3861,7 @@ rb_player_gst_xfade_add_tee (RBPlayerGstTee *iplayer, GstElement *element)
return TRUE;
}
- return pipeline_op (player,
- element,
- player->priv->volume,
- (GstPadBlockCallback) really_add_tee);
+ return rb_gst_add_tee (RB_PLAYER (player), player->priv->tee, element);
}
static gboolean
@@ -4046,169 +3874,9 @@ rb_player_gst_xfade_remove_tee (RBPlayerGstTee *iplayer, GstElement *element)
return TRUE;
}
- return pipeline_op (RB_PLAYER_GST_XFADE (iplayer),
- element,
- player->priv->volume,
- (GstPadBlockCallback) really_remove_tee);
-}
-
-
-/* RBPlayerGstFilter implementation */
-
-
-static void
-really_add_filter (GstPad *pad,
- gboolean blocked,
- RBPlayerGstXFadePipelineOp *op)
-{
- GstPad *binsinkpad;
- GstPad *binsrcpad;
- GstPad *realpad;
- GstPad *ghostpad;
- GstElement *bin;
- GstElement *audioconvert;
- GstIterator *sink_pads;
- gboolean sink_pad_found;
- gboolean stop_scan;
- gpointer element_sink_pad;
- GstPadLinkReturn link;
-
- rb_debug ("adding filter %p", op->element);
-
- /* find the element's first unlinked source pad */
- sink_pad_found = FALSE;
- stop_scan = FALSE;
- sink_pads = gst_element_iterate_sink_pads (op->element);
- while (!sink_pad_found && !stop_scan) {
- gpointer *esp_pointer = &element_sink_pad; /* stop type-punning warnings */
- switch (gst_iterator_next (sink_pads, esp_pointer)) {
- case GST_ITERATOR_OK:
- sink_pad_found = !gst_pad_is_linked (GST_PAD (element_sink_pad));
- break;
- case GST_ITERATOR_RESYNC:
- gst_iterator_resync (sink_pads);
- break;
- case GST_ITERATOR_ERROR:
- case GST_ITERATOR_DONE:
- stop_scan = TRUE;
- break;
- }
- }
- gst_iterator_free (sink_pads);
-
- if (!sink_pad_found) {
- g_warning ("Could not find a free sink pad on filter");
- return;
- }
-
- /* create containing bin */
- bin = gst_bin_new (NULL);
- audioconvert = gst_element_factory_make ("audioconvert", NULL);
- gst_bin_add_many (GST_BIN (bin), op->element, audioconvert, NULL);
- gst_element_link (op->element, audioconvert);
-
- /* create ghost pads */
- binsinkpad = gst_ghost_pad_new ("sink", GST_PAD (element_sink_pad));
- gst_element_add_pad (bin, binsinkpad);
-
- realpad = gst_element_get_static_pad (audioconvert, "src");
- binsrcpad = gst_ghost_pad_new ("src", realpad);
- gst_element_add_pad (bin, binsrcpad);
- gst_object_unref (realpad);
-
- /* chuck it into the filter bin */
- gst_bin_add (GST_BIN (op->player->priv->filterbin), bin);
-
- ghostpad = gst_element_get_static_pad (op->player->priv->filterbin, "src");
- realpad = gst_ghost_pad_get_target (GST_GHOST_PAD (ghostpad));
- gst_ghost_pad_set_target (GST_GHOST_PAD (ghostpad), binsrcpad);
- gst_object_unref (ghostpad);
-
- link = gst_pad_link (realpad, binsinkpad);
- gst_object_unref (realpad);
- if (link != GST_PAD_LINK_OK) {
- g_warning ("could not link new filter into pipeline");
- /* can't really do much else at this point.. */
- }
-
- /* if we're supposed to be playing, unblock the sink */
- if (blocked) {
- rb_debug ("unblocking pad after adding filter");
- gst_element_set_state (bin, GST_STATE_PLAYING);
- gst_pad_set_blocked_async (pad, FALSE, (GstPadBlockCallback)pipeline_op_done, NULL);
- } else {
- gst_element_set_state (bin, GST_STATE_PAUSED);
- }
-
- _rb_player_gst_filter_emit_filter_inserted (RB_PLAYER_GST_FILTER (op->player), op->element);
-
- free_pipeline_op (op);
+ return rb_gst_remove_tee (RB_PLAYER (player), player->priv->tee, element);
}
-static void
-really_remove_filter (GstPad *pad,
- gboolean blocked,
- RBPlayerGstXFadePipelineOp *op)
-{
- GstPad *mypad;
- GstPad *prevpad, *nextpad;
- GstPad *ghostpad;
- GstPad *targetpad;
- GstElement *bin;
-
- /* get the containing bin and remove it */
- bin = GST_ELEMENT (gst_element_get_parent (op->element));
- if (bin == NULL) {
- return;
- }
-
- rb_debug ("removing filter %p", op->element);
- _rb_player_gst_filter_emit_filter_pre_remove (RB_PLAYER_GST_FILTER (op->player), op->element);
-
- /* probably check return? */
- gst_element_set_state (bin, GST_STATE_NULL);
-
- mypad = gst_element_get_static_pad (bin, "sink");
- prevpad = gst_pad_get_peer (mypad);
- gst_pad_unlink (prevpad, mypad);
- gst_object_unref (mypad);
-
- ghostpad = gst_element_get_static_pad (bin, "src");
- nextpad = gst_element_get_static_pad (op->player->priv->filterbin, "src");
-
- targetpad = gst_ghost_pad_get_target (GST_GHOST_PAD (nextpad));
- if (targetpad == ghostpad) {
- /* we're at the end of the filter chain, so redirect
- * the ghostpad to the previous element.
- */
- gst_ghost_pad_set_target (GST_GHOST_PAD (nextpad), prevpad);
- } else {
- /* we are in the middle, so link the previous and next elements */
- gst_object_unref (nextpad);
- nextpad = gst_pad_get_peer (ghostpad);
- gst_pad_unlink (ghostpad, nextpad);
-
- if (gst_pad_link (prevpad, nextpad) != GST_PAD_LINK_OK) {
- /* crap */
- }
- }
-
- gst_object_unref (prevpad);
- gst_object_unref (ghostpad);
- gst_object_unref (targetpad);
- gst_object_unref (nextpad);
-
- gst_bin_remove (GST_BIN (op->player->priv->filterbin), bin);
- gst_object_unref (bin);
-
- /* if we're supposed to be playing, unblock the sink */
- if (blocked) {
- rb_debug ("unblocking pad after removing filter");
- gst_pad_set_blocked_async (pad, FALSE, (GstPadBlockCallback)pipeline_op_done, NULL);
- }
-
- free_pipeline_op (op);
-}
static gboolean
rb_player_gst_xfade_add_filter (RBPlayerGstFilter *iplayer, GstElement *element)
@@ -4219,10 +3887,7 @@ rb_player_gst_xfade_add_filter (RBPlayerGstFilter *iplayer, GstElement *element)
return TRUE;
}
- return pipeline_op (player,
- element,
- player->priv->volume,
- (GstPadBlockCallback) really_add_filter);
+ return rb_gst_add_filter (RB_PLAYER (player), player->priv->filterbin, element);
}
@@ -4235,9 +3900,7 @@ rb_player_gst_xfade_remove_filter (RBPlayerGstFilter *iplayer, GstElement *eleme
player->priv->waiting_filters = g_list_remove (player->priv->waiting_filters, element);
return TRUE;
}
- return pipeline_op (player,
- element,
- player->priv->volume,
- (GstPadBlockCallback) really_remove_filter);
+
+ return rb_gst_remove_filter (RB_PLAYER (player), player->priv->filterbin, element);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]