summaryrefslogtreecommitdiffstats
path: root/gst-libs/gst/play
diff options
context:
space:
mode:
authorJulien Moutte <julien@moutte.net>2004-01-22 23:54:34 +0000
committerJulien Moutte <julien@moutte.net>2004-01-22 23:54:34 +0000
commit4bb604a90b483a87fbab1025a1a1fcb97781658c (patch)
treec435ae53034cd0af55ac249f496e0c10c8f4a6b5 /gst-libs/gst/play
parent0a0ccb33e380f474fd9f9d21d00b18699faa0b9c (diff)
downloadgst-plugins-bad-4bb604a90b483a87fbab1025a1a1fcb97781658c.tar.gz
gst-plugins-bad-4bb604a90b483a87fbab1025a1a1fcb97781658c.tar.bz2
gst-plugins-bad-4bb604a90b483a87fbab1025a1a1fcb97781658c.zip
gst-libs/gst/play/gstplay.c: Reworked the pipeline from scratch. Visualization is back and switch went out as i reali...
Original commit message from CVS: 2004-01-23 Julien MOUTTE <julien@moutte.net> * gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup), (gst_play_set_location), (gst_play_seek_to_time), (gst_play_set_audio_sink), (gst_play_set_visualization), (gst_play_connect_visualization), (gst_play_get_sink_element): Reworked the pipeline from scratch. Visualization is back and switch went out as i realized it was not possible to use the way i wanted. * sys/ximage/ximagesink.c: (gst_ximagesink_imagepool_clear), (gst_ximagesink_change_state), (gst_ximagesink_dispose): Move xcontext clearing in state change from READY to NULL. So that one can clean the X ressources keeping the element. * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get), (gst_xvimagesink_imagepool_clear), (gst_xvimagesink_change_state), (gst_xvimagesink_colorbalance_set_value), (gst_xvimagesink_colorbalance_get_value), (gst_xvimagesink_set_property), (gst_xvimagesink_dispose), (gst_xvimagesink_init): Same xcontext cleaning than ximagesink in state change from READY to NULL and fixed some stupid bugs in colorbalance get/set values. Also added the following feature : when nobody tries to set some values to the colorbalance levels before the xcontext is grabbed, then when creating channels list from Xv attributes we set the internal values to the Xv defaults. This way we handle buggy Xv drivers that set default hue values far from the middle of the range (Thanks to Jon Trowbridge for pointing that issue). * sys/xvimage/xvimagesink.h: Adding a cb_changed boolean to know if colorbalance levels have been set before xcontext is grabbed.
Diffstat (limited to 'gst-libs/gst/play')
-rw-r--r--gst-libs/gst/play/gstplay.c442
-rw-r--r--gst-libs/gst/play/play.c442
2 files changed, 490 insertions, 394 deletions
diff --git a/gst-libs/gst/play/gstplay.c b/gst-libs/gst/play/gstplay.c
index be165ddc..871e74ab 100644
--- a/gst-libs/gst/play/gstplay.c
+++ b/gst-libs/gst/play/gstplay.c
@@ -59,41 +59,86 @@ static GstPipelineClass *parent_class = NULL;
static gboolean
gst_play_pipeline_setup (GstPlay *play)
{
- GstElement *work_thread, *video_thread, *source;
- GstElement *autoplugger, *switch_colorspace, *video_switch, *video_queue;
- GstElement *video_balance, *video_colorspace, *video_scaler, *video_sink;
- GstElement *audio_thread, *audio_queue, *audio_volume, *audio_sink;
- GstElement *audio_tee, *vis_thread, *vis_queue, *vis_element, *end_vis_queue;
- GstPad *audio_tee_pad1, *audio_tee_pad2, *vis_thread_pad, *audio_sink_pad;
+ /* Threads */
+ GstElement *work_thread, *audio_thread, *video_thread;
+ /* Main Thread elements */
+ GstElement *source, *autoplugger, *audioconvert, *volume, *tee, *vis_element;
+ /* Video Thread elements */
+ GstElement *video_queue, *video_cs, *video_balance, *balance_cs;
+ GstElement *video_scaler, *video_sink;
+ /* Audio Thread elements */
+ GstElement *audio_queue, *audio_sink;
+ /* Some useful pads */
+ GstPad *tee_pad1, *tee_pad2;
g_return_val_if_fail (play != NULL, FALSE);
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
+ /* Creating main thread and its elements
+ { fakesrc ! spider ! audioconvert ! volume ! tee } */
+ {
work_thread = gst_element_factory_make ("thread", "work_thread");
if (!GST_IS_ELEMENT (work_thread))
return FALSE;
g_hash_table_insert (play->priv->elements, "work_thread", work_thread);
gst_bin_add (GST_BIN (play), work_thread);
-
- /* Placeholder for the source and autoplugger { fakesrc ! spider } */
+
+ /* Placeholder for datasrc */
source = gst_element_factory_make ("fakesrc", "source");
if (!GST_IS_ELEMENT (source))
return FALSE;
g_hash_table_insert (play->priv->elements, "source", source);
+ /* Autoplugger */
autoplugger = gst_element_factory_make ("spider", "autoplugger");
if (!GST_IS_ELEMENT (autoplugger))
return FALSE;
g_hash_table_insert (play->priv->elements, "autoplugger", autoplugger);
- gst_bin_add_many (GST_BIN (work_thread), source, autoplugger, NULL);
- gst_element_link (source, autoplugger);
+ /* Make sure we convert audio to the needed format */
+ audioconvert = gst_element_factory_make ("audioconvert",
+ "audioconvert");
+ if (!GST_IS_ELEMENT (audioconvert))
+ return FALSE;
+
+ g_hash_table_insert (play->priv->elements, "volume", audioconvert);
+
+ /* Volume control */
+ volume = gst_element_factory_make ("volume", "volume");
+ if (!GST_IS_ELEMENT (volume))
+ return FALSE;
- /* Creating our video output bin
- { queue ! videobalance ! colorspace ! videoscale ! fakesink } */
+ g_hash_table_insert (play->priv->elements, "audioconvert", volume);
+
+ /* Duplicate audio signal to audio sink and visualization thread */
+ tee = gst_element_factory_make ("tee", "tee");
+ if (!GST_IS_ELEMENT (tee))
+ return FALSE;
+
+ tee_pad1 = gst_element_get_request_pad (tee, "src%d");
+ tee_pad2 = gst_element_get_request_pad (tee, "src%d");
+ g_hash_table_insert (play->priv->elements, "tee_pad1", tee_pad1);
+ g_hash_table_insert (play->priv->elements, "tee_pad2", tee_pad2);
+ g_hash_table_insert (play->priv->elements, "tee", tee);
+
+ gst_bin_add_many (GST_BIN (work_thread), source, autoplugger,/* audioconvert,*/
+ volume, tee, NULL);
+ gst_element_link_many (source, autoplugger,/* audioconvert,*/ volume, tee, NULL);
+
+ /* Visualization element placeholder (note: it s not added to the pipeline
+ yet) */
+ vis_element = gst_element_factory_make ("identity", "vis_element");
+ if (!GST_IS_ELEMENT (vis_element))
+ return FALSE;
+
+ g_hash_table_insert (play->priv->elements, "vis_element", vis_element);
+
+ }
+ /* Creating our video output bin */
+ {
video_thread = gst_element_factory_make ("thread", "video_thread");
if (!GST_IS_ELEMENT (video_thread))
return FALSE;
@@ -101,13 +146,24 @@ gst_play_pipeline_setup (GstPlay *play)
g_hash_table_insert (play->priv->elements, "video_thread", video_thread);
gst_bin_add (GST_BIN (work_thread), video_thread);
- /* Buffer queue for our video thread */
+ /* Buffer queue for video data */
video_queue = gst_element_factory_make ("queue", "video_queue");
if (!GST_IS_ELEMENT (video_queue))
return FALSE;
g_hash_table_insert (play->priv->elements, "video_queue", video_queue);
+ /* Colorspace conversion */
+ video_cs = gst_element_factory_make ("ffcolorspace", "video_cs");
+ if (!GST_IS_ELEMENT (video_cs)) {
+ video_cs = gst_element_factory_make ("colorspace", "video_cs");
+ if (!GST_IS_ELEMENT (video_cs))
+ return FALSE;
+ }
+
+ g_hash_table_insert (play->priv->elements, "video_cs", video_cs);
+
+ /* Software colorbalance */
video_balance = gst_element_factory_make ("videobalance",
"video_balance");
if (!GST_IS_ELEMENT (video_balance))
@@ -117,17 +173,14 @@ gst_play_pipeline_setup (GstPlay *play)
video_balance);
/* Colorspace conversion */
- video_colorspace = gst_element_factory_make ("ffcolorspace",
- "video_colorspace");
- if (!GST_IS_ELEMENT (video_colorspace)) {
- video_colorspace = gst_element_factory_make ("colorspace",
- "video_colorspace");
- if (!GST_IS_ELEMENT (video_colorspace))
+ balance_cs = gst_element_factory_make ("ffcolorspace", "balance_cs");
+ if (!GST_IS_ELEMENT (balance_cs)) {
+ balance_cs = gst_element_factory_make ("colorspace", "balance_cs");
+ if (!GST_IS_ELEMENT (balance_cs))
return FALSE;
}
- g_hash_table_insert (play->priv->elements, "video_colorspace",
- video_colorspace);
+ g_hash_table_insert (play->priv->elements, "balance_cs", balance_cs);
/* Software scaling of video stream */
video_scaler = gst_element_factory_make ("videoscale", "video_scaler");
@@ -143,46 +196,18 @@ gst_play_pipeline_setup (GstPlay *play)
g_hash_table_insert (play->priv->elements, "video_sink", video_sink);
- /* Linking, Adding, Ghosting */
- gst_element_link_many (video_queue, video_balance, video_colorspace,
+ gst_bin_add_many (GST_BIN (video_thread), video_queue, video_cs,
+ video_balance, balance_cs, video_scaler, video_sink, NULL);
+ gst_element_link_many (video_queue, video_cs, video_balance, balance_cs,
video_scaler, video_sink, NULL);
- gst_bin_add_many (GST_BIN (video_thread), video_queue, video_balance,
- video_colorspace, video_scaler, video_sink, NULL);
gst_element_add_ghost_pad (video_thread,
gst_element_get_pad (video_queue, "sink"),
"sink");
-
- /* autoplugger ! ffcolorspace ! switch */
- switch_colorspace = NULL;
- switch_colorspace = gst_element_factory_make ("ffcolorspace",
- "switch_colorspace");
- if (!GST_IS_ELEMENT (switch_colorspace)) {
- switch_colorspace = gst_element_factory_make ("colorspace",
- "switch_colorspace");
- if (!GST_IS_ELEMENT (switch_colorspace))
- return FALSE;
+ gst_element_link (autoplugger, video_thread);
}
-
- g_hash_table_insert (play->priv->elements, "switch_colorspace",
- switch_colorspace);
-
- video_switch = gst_element_factory_make ("switch",
- "video_switch");
- if (!GST_IS_ELEMENT (video_switch))
- return FALSE;
-
- g_hash_table_insert (play->priv->elements, "video_switch", video_switch);
-
- gst_bin_add_many (GST_BIN (work_thread), switch_colorspace,
- /*video_switch,*/ NULL);
-
- /* Connecting autoplugger to video switch and video switch to video output */
- gst_element_link_many (autoplugger, switch_colorspace,
- /*video_switch,*/ video_thread, NULL);
- /* gst_element_link (autoplugger, video_thread); */
-
/* Creating our audio output bin
- { queue ! volume ! tee ! { queue ! goom } ! fakesink } */
+ { queue ! fakesink } */
+ {
audio_thread = gst_element_factory_make ("thread", "audio_thread");
if (!GST_IS_ELEMENT (audio_thread))
return FALSE;
@@ -197,85 +222,20 @@ gst_play_pipeline_setup (GstPlay *play)
g_hash_table_insert (play->priv->elements, "audio_queue", audio_queue);
- /* Volume control */
- audio_volume = gst_element_factory_make ("volume", "audio_volume");
- if (!GST_IS_ELEMENT (audio_volume))
- return FALSE;
-
- g_hash_table_insert (play->priv->elements, "audio_volume", audio_volume);
-
- /* Duplicate audio signal to sink and visualization thread */
- audio_tee = gst_element_factory_make ("tee", "audio_tee");
- if (!GST_IS_ELEMENT (audio_tee))
- return FALSE;
-
- audio_tee_pad1 = gst_element_get_request_pad (audio_tee, "src%d");
- audio_tee_pad2 = gst_element_get_request_pad (audio_tee, "src%d");
- g_hash_table_insert (play->priv->elements, "audio_tee_pad1",
- audio_tee_pad1);
- g_hash_table_insert (play->priv->elements, "audio_tee_pad2",
- audio_tee_pad2);
- g_hash_table_insert (play->priv->elements, "audio_tee", audio_tee);
-
/* Placeholder for future audio sink bin */
audio_sink = gst_element_factory_make ("fakesink", "audio_sink");
if (!GST_IS_ELEMENT (audio_sink))
return FALSE;
- audio_sink_pad = gst_element_get_pad (audio_sink, "sink");
- g_hash_table_insert (play->priv->elements, "audio_sink_pad",
- audio_sink_pad);
g_hash_table_insert (play->priv->elements, "audio_sink", audio_sink);
- /* Visualization thread */
- vis_thread = gst_element_factory_make ("thread", "vis_thread");
- if (!GST_IS_ELEMENT (vis_thread))
- return FALSE;
-
- g_hash_table_insert (play->priv->elements, "vis_thread", vis_thread);
-
- /* Buffer queue for our visualization thread */
- vis_queue = gst_element_factory_make ("queue", "vis_queue");
- if (!GST_IS_ELEMENT (vis_queue))
- return FALSE;
-
- g_hash_table_insert (play->priv->elements, "vis_queue", vis_queue);
-
- vis_element = gst_element_factory_make ("identity", "vis_element");
- if (!GST_IS_ELEMENT (vis_element))
- return FALSE;
-
- g_hash_table_insert (play->priv->elements, "vis_element", vis_element);
-
- end_vis_queue = gst_element_factory_make ("queue", "end_vis_queue");
- if (!GST_IS_ELEMENT (end_vis_queue))
- return FALSE;
-
- g_hash_table_insert (play->priv->elements, "end_vis_queue",
- end_vis_queue);
-
- /* Adding, Linking, Ghosting in visualization */
- gst_bin_add_many (GST_BIN (vis_thread), vis_queue, vis_element,
- end_vis_queue, NULL);
- gst_element_link_many (vis_queue, vis_element, end_vis_queue, NULL);
- vis_thread_pad = gst_element_add_ghost_pad (vis_thread,
- gst_element_get_pad (vis_queue, "sink"),
- "sink");
- g_hash_table_insert (play->priv->elements, "vis_thread_pad",
- vis_thread_pad);
-
-
- /* Linking, Adding, Ghosting in audio */
- gst_element_link_many (audio_queue, audio_volume, audio_tee, NULL);
- gst_pad_link (audio_tee_pad1, audio_sink_pad);
- gst_bin_add_many (GST_BIN (audio_thread), audio_queue, audio_volume,
- audio_tee, vis_thread, audio_sink, NULL);
+ gst_bin_add_many (GST_BIN (audio_thread), audio_queue, audio_sink, NULL);
+ gst_element_link (audio_queue, audio_sink);
gst_element_add_ghost_pad (audio_thread,
gst_element_get_pad (audio_queue, "sink"),
"sink");
-
- /* Connecting audio output to autoplugger */
- gst_element_link (autoplugger, audio_thread);
+ gst_pad_link (tee_pad2, gst_element_get_pad (audio_queue, "sink"));
+ }
return TRUE;
}
@@ -505,7 +465,7 @@ gboolean
gst_play_set_location (GstPlay *play, const char *location)
{
GstElement *work_thread, *source, *autoplugger;
- GstElement *switch_colorspace, *audio_thread;
+ GstElement *audioconvert, *video_thread;
g_return_val_if_fail (play != NULL, FALSE);
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
@@ -521,25 +481,24 @@ gst_play_set_location (GstPlay *play, const char *location)
work_thread = g_hash_table_lookup (play->priv->elements, "work_thread");
if (!GST_IS_ELEMENT (work_thread))
return FALSE;
- switch_colorspace = g_hash_table_lookup (play->priv->elements,
- "switch_colorspace");
- if (!GST_IS_ELEMENT (switch_colorspace))
- return FALSE;
- audio_thread = g_hash_table_lookup (play->priv->elements, "audio_thread");
- if (!GST_IS_ELEMENT (audio_thread))
- return FALSE;
source = g_hash_table_lookup (play->priv->elements, "source");
if (!GST_IS_ELEMENT (source))
return FALSE;
autoplugger = g_hash_table_lookup (play->priv->elements, "autoplugger");
if (!GST_IS_ELEMENT (autoplugger))
return FALSE;
+ audioconvert = g_hash_table_lookup (play->priv->elements, "audioconvert");
+ if (!GST_IS_ELEMENT (audioconvert))
+ return FALSE;
+ video_thread = g_hash_table_lookup (play->priv->elements, "video_thread");
+ if (!GST_IS_ELEMENT (video_thread))
+ return FALSE;
/* Spider can autoplugg only once. We remove the actual one and put a new
autoplugger */
gst_element_unlink (source, autoplugger);
- gst_element_unlink (autoplugger, switch_colorspace);
- gst_element_unlink (autoplugger, audio_thread);
+ gst_element_unlink (autoplugger, video_thread);
+ gst_element_unlink (autoplugger, audioconvert);
gst_bin_remove (GST_BIN (work_thread), autoplugger);
autoplugger = gst_element_factory_make ("spider", "autoplugger");
@@ -548,8 +507,8 @@ gst_play_set_location (GstPlay *play, const char *location)
gst_bin_add (GST_BIN (work_thread), autoplugger);
gst_element_link (source, autoplugger);
- gst_element_link (autoplugger, switch_colorspace);
- gst_element_link (autoplugger, audio_thread);
+ gst_element_link (autoplugger, video_thread);
+ gst_element_link (autoplugger, audioconvert);
g_hash_table_replace (play->priv->elements, "autoplugger", autoplugger);
@@ -618,8 +577,9 @@ gst_play_seek_to_time (GstPlay * play, gint64 time_nanos)
}
if (s) {
- GstClock *clock = gst_bin_get_clock (GST_BIN (play));
- play->priv->time_nanos = gst_clock_get_time (clock);
+ GstClockTime time;
+ time = gst_element_get_time (audio_sink_element);
+ play->priv->time_nanos = GST_CLOCK_TIME_IS_VALID (time) ? time : 0;
g_signal_emit (G_OBJECT (play), gst_play_signals[TIME_TICK],
0,play->priv->time_nanos);
}
@@ -745,8 +705,7 @@ gst_play_set_video_sink (GstPlay *play, GstElement *video_sink)
gboolean
gst_play_set_audio_sink (GstPlay *play, GstElement *audio_sink)
{
- GstElement *old_audio_sink, *audio_thread, *audio_sink_element;
- GstPad *audio_tee_pad1, *audio_sink_pad, *old_audio_sink_pad;
+ GstElement *old_audio_sink, *audio_thread, *audio_queue, *audio_sink_element;
g_return_val_if_fail (play != NULL, FALSE);
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
@@ -761,31 +720,21 @@ gst_play_set_audio_sink (GstPlay *play, GstElement *audio_sink)
old_audio_sink = g_hash_table_lookup (play->priv->elements, "audio_sink");
if (!GST_IS_ELEMENT (old_audio_sink))
return FALSE;
- old_audio_sink_pad = g_hash_table_lookup (play->priv->elements,
- "audio_sink_pad");
- if (!GST_IS_PAD (old_audio_sink_pad))
- return FALSE;
audio_thread = g_hash_table_lookup (play->priv->elements, "audio_thread");
if (!GST_IS_ELEMENT (audio_thread))
return FALSE;
- audio_tee_pad1 = g_hash_table_lookup (play->priv->elements,
- "audio_tee_pad1");
- if (!GST_IS_PAD (audio_tee_pad1))
- return FALSE;
- audio_sink_pad = gst_element_get_pad (audio_sink, "sink");
- if (!GST_IS_PAD (audio_sink_pad))
+ audio_queue = g_hash_table_lookup (play->priv->elements, "audio_queue");
+ if (!GST_IS_ELEMENT (audio_queue))
return FALSE;
/* Unlinking old audiosink, removing it from pipeline, putting the new one
and linking it */
- gst_pad_unlink (audio_tee_pad1, old_audio_sink_pad);
+ gst_element_unlink (audio_queue, old_audio_sink);
gst_bin_remove (GST_BIN (audio_thread), old_audio_sink);
gst_bin_add (GST_BIN (audio_thread), audio_sink);
- gst_pad_link (audio_tee_pad1, audio_sink_pad);
+ gst_element_link (audio_queue, audio_sink);
g_hash_table_replace (play->priv->elements, "audio_sink", audio_sink);
- g_hash_table_replace (play->priv->elements, "audio_sink_pad",
- audio_sink_pad);
audio_sink_element = gst_play_get_sink_element (play, audio_sink,
GST_PLAY_SINK_TYPE_AUDIO);
@@ -811,7 +760,8 @@ gst_play_set_audio_sink (GstPlay *play, GstElement *audio_sink)
gboolean
gst_play_set_visualization (GstPlay *play, GstElement *vis_element)
{
- GstElement *old_vis_element, *vis_thread, *vis_queue, *end_vis_queue;
+ GstElement *work_thread, *old_vis_element, *video_thread;
+ GstPad *tee_pad1;
gboolean was_playing = FALSE;
g_return_val_if_fail (play != NULL, FALSE);
@@ -819,34 +769,50 @@ gst_play_set_visualization (GstPlay *play, GstElement *vis_element)
g_return_val_if_fail (vis_element != NULL, FALSE);
g_return_val_if_fail (GST_IS_ELEMENT (vis_element), FALSE);
- /* We bring back the pipeline to READY */
- if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
- gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
- was_playing = TRUE;
- }
-
/* Getting needed objects */
- vis_thread = g_hash_table_lookup (play->priv->elements, "vis_thread");
- if (!GST_IS_ELEMENT (vis_thread))
+ work_thread = g_hash_table_lookup (play->priv->elements, "work_thread");
+ if (!GST_IS_ELEMENT (work_thread))
return FALSE;
old_vis_element = g_hash_table_lookup (play->priv->elements,
"vis_element");
if (!GST_IS_ELEMENT (old_vis_element))
return FALSE;
- vis_queue = g_hash_table_lookup (play->priv->elements, "vis_queue");
- if (!GST_IS_ELEMENT (vis_queue))
+ tee_pad1 = g_hash_table_lookup (play->priv->elements, "tee_pad1");
+ if (!GST_IS_PAD (tee_pad1))
return FALSE;
- end_vis_queue = g_hash_table_lookup (play->priv->elements, "end_vis_queue");
- if (!GST_IS_ELEMENT (end_vis_queue))
+ video_thread = g_hash_table_lookup (play->priv->elements, "video_thread");
+ if (!GST_IS_ELEMENT (video_thread))
return FALSE;
+
+ /* Let's check if the current vis element has a managing bin. If yes that
+ means the element is inside the pipeline and need to be unlinked and
+ removed. We also need to pause the pipeline if it is currently playing. */
+ if (gst_element_get_managing_bin (old_vis_element)) {
+ GstPad *vis_element_pad;
+
+ /* We bring back the pipeline to PAUSED */
+ if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
+ gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
+ was_playing = TRUE;
+ }
- /* Unlinking, removing the old element then adding and linking the new one */
- gst_element_unlink (vis_queue, old_vis_element);
- gst_element_unlink (old_vis_element, end_vis_queue);
- gst_bin_remove (GST_BIN (vis_thread), old_vis_element);
- gst_bin_add (GST_BIN (vis_thread), vis_element);
- gst_element_link (vis_queue, vis_element);
- gst_element_link (vis_element, end_vis_queue);
+ /* Unlinking, removing the old element then adding and linking the new one */
+ vis_element_pad = gst_element_get_pad (old_vis_element, "sink");
+ if (GST_IS_PAD (vis_element_pad))
+ gst_pad_unlink (tee_pad1, vis_element_pad);
+ gst_element_unlink (old_vis_element, video_thread);
+ gst_bin_remove (GST_BIN (work_thread), old_vis_element);
+ gst_bin_add (GST_BIN (work_thread), vis_element);
+ vis_element_pad = gst_element_get_pad (vis_element, "sink");
+ if (GST_IS_PAD (vis_element_pad))
+ gst_pad_link (tee_pad1, vis_element_pad);
+ gst_element_link (vis_element, video_thread);
+ }
+ else {
+ gst_object_unref (GST_OBJECT (old_vis_element));
+ }
+
+ g_hash_table_replace (play->priv->elements, "vis_element", vis_element);
if (was_playing)
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PLAYING);
@@ -867,39 +833,121 @@ gst_play_set_visualization (GstPlay *play, GstElement *vis_element)
gboolean
gst_play_connect_visualization (GstPlay * play, gboolean connect)
{
- GstPad *audio_tee_pad2, *vis_thread_pad;
- gboolean connected = FALSE, was_playing = FALSE;
+ GstElement *work_thread, *vis_element, *autoplugger, *video_thread;
+ GstElement *audioconvert, *source;
+ GstPad *tee_pad1, *vis_element_pad;
g_return_val_if_fail (play != NULL, FALSE);
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
- vis_thread_pad = g_hash_table_lookup (play->priv->elements,
- "vis_thread_pad");
- if (!GST_IS_PAD (vis_thread_pad))
+ /* Getting needed objects */
+ work_thread = g_hash_table_lookup (play->priv->elements, "work_thread");
+ if (!GST_IS_ELEMENT (work_thread))
return FALSE;
- audio_tee_pad2 = g_hash_table_lookup (play->priv->elements,
- "audio_tee_pad2");
- if (!GST_IS_PAD (audio_tee_pad2))
+ vis_element = g_hash_table_lookup (play->priv->elements, "vis_element");
+ if (!GST_IS_ELEMENT (vis_element))
+ return FALSE;
+ tee_pad1 = g_hash_table_lookup (play->priv->elements, "tee_pad1");
+ if (!GST_IS_PAD (tee_pad1))
+ return FALSE;
+ video_thread = g_hash_table_lookup (play->priv->elements, "video_thread");
+ if (!GST_IS_ELEMENT (video_thread))
+ return FALSE;
+ autoplugger = g_hash_table_lookup (play->priv->elements, "autoplugger");
+ if (!GST_IS_ELEMENT (autoplugger))
return FALSE;
+ source = g_hash_table_lookup (play->priv->elements, "source");
+ if (!GST_IS_ELEMENT (source))
+ return FALSE;
+ audioconvert = g_hash_table_lookup (play->priv->elements, "audioconvert");
+ if (!GST_IS_ELEMENT (audioconvert))
+ return FALSE;
+
+ /* Check if the vis element is in the pipeline. That means visualization is
+ connected already */
+ if (gst_element_get_managing_bin (vis_element)) {
+
+ /* If we are supposed to connect then nothing to do we return */
+ if (connect) {
+ return TRUE;
+ }
+
+ /* We have to modify the pipeline. Changing autoplugger requires going to
+ READY */
+ gst_element_set_state (GST_ELEMENT (play), GST_STATE_READY);
+
+ /* Otherwise we unlink and remove the vis element refing it so that
+ it won't be destroyed when removed from the bin. */
+ vis_element_pad = gst_element_get_pad (vis_element, "sink");
+ if (GST_IS_PAD (vis_element_pad))
+ gst_pad_unlink (tee_pad1, vis_element_pad);
+ gst_element_unlink (vis_element, video_thread);
+ gst_object_ref (GST_OBJECT (vis_element));
+ gst_bin_remove (GST_BIN (work_thread), vis_element);
+
+ /* Removing autoplugger */
+ gst_element_unlink (source, autoplugger);
+ gst_element_unlink (autoplugger, audioconvert);
+ gst_bin_remove (GST_BIN (work_thread), autoplugger);
- if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
- gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
- was_playing = TRUE;
+ autoplugger = gst_element_factory_make ("spider", "autoplugger");
+ if (!GST_IS_ELEMENT (autoplugger))
+ return FALSE;
+
+ /* Adding and connecting a new autoplugger connected to video_thread */
+ gst_bin_add (GST_BIN (work_thread), autoplugger);
+ gst_element_link (source, autoplugger);
+ gst_element_link (autoplugger, video_thread);
+ gst_element_link (autoplugger, audioconvert);
+
+ g_hash_table_replace (play->priv->elements, "autoplugger", autoplugger);
}
+ else {
+ GstCaps *filtered_caps;
- if (gst_pad_get_peer (vis_thread_pad) != NULL)
- connected = TRUE;
- else
- connected = FALSE;
-
- if ((connect) && (!connected))
- gst_pad_link (audio_tee_pad2, vis_thread_pad);
- else if ((!connect) && (connected))
- gst_pad_unlink (audio_tee_pad2, vis_thread_pad);
+ /* If we are supposed to disconnect then nothing to do we return */
+ if (!connect) {
+ return TRUE;
+ }
+
+ /* We have to modify the pipeline. Changing autoplugger requires going to
+ READY */
+ gst_element_set_state (GST_ELEMENT (play), GST_STATE_READY);
+
+ /* Removing autoplugger */
+ gst_element_unlink (source, autoplugger);
+ gst_element_unlink (autoplugger, video_thread);
+ gst_element_unlink (autoplugger, audioconvert);
+ gst_bin_remove (GST_BIN (work_thread), autoplugger);
+
+ autoplugger = gst_element_factory_make ("spider", "autoplugger");
+ if (!GST_IS_ELEMENT (autoplugger))
+ return FALSE;
- if (was_playing)
- gst_element_set_state (GST_ELEMENT (play), GST_STATE_PLAYING);
+ /* Adding and connecting a new autoplugger */
+ gst_bin_add (GST_BIN (work_thread), autoplugger);
+ gst_element_link (source, autoplugger);
+ gst_element_link (autoplugger, audioconvert);
+
+ g_hash_table_replace (play->priv->elements, "autoplugger", autoplugger);
+
+ /* Otherwise we add the element to the bin and link it to video_thread */
+ gst_bin_add (GST_BIN (work_thread), vis_element);
+ vis_element_pad = gst_element_get_pad (vis_element, "sink");
+ if (GST_IS_PAD (vis_element_pad))
+ gst_pad_link (tee_pad1, vis_element_pad);
+
+ filtered_caps = gst_caps_from_string ("video/x-raw-rgb, "
+ "framerate = 30.0; "
+ "video/x-raw-yuv, "
+ "framerate = 30.0");
+ if (!gst_element_link_filtered (vis_element, video_thread, filtered_caps))
+ g_message ("failed linking filtered vis with video thread");
+
+ gst_caps_free (filtered_caps);
+ }
+
return TRUE;
}
@@ -916,7 +964,7 @@ gst_play_connect_visualization (GstPlay * play, gboolean connect)
*/
GstElement *
gst_play_get_sink_element (GstPlay *play,
- GstElement *element, GstPlaySinkType sink_type)
+ GstElement *element, GstPlaySinkType sink_type)
{
GList *elements = NULL;
const GList *pads = NULL;
diff --git a/gst-libs/gst/play/play.c b/gst-libs/gst/play/play.c
index be165ddc..871e74ab 100644
--- a/gst-libs/gst/play/play.c
+++ b/gst-libs/gst/play/play.c
@@ -59,41 +59,86 @@ static GstPipelineClass *parent_class = NULL;
static gboolean
gst_play_pipeline_setup (GstPlay *play)
{
- GstElement *work_thread, *video_thread, *source;
- GstElement *autoplugger, *switch_colorspace, *video_switch, *video_queue;
- GstElement *video_balance, *video_colorspace, *video_scaler, *video_sink;
- GstElement *audio_thread, *audio_queue, *audio_volume, *audio_sink;
- GstElement *audio_tee, *vis_thread, *vis_queue, *vis_element, *end_vis_queue;
- GstPad *audio_tee_pad1, *audio_tee_pad2, *vis_thread_pad, *audio_sink_pad;
+ /* Threads */
+ GstElement *work_thread, *audio_thread, *video_thread;
+ /* Main Thread elements */
+ GstElement *source, *autoplugger, *audioconvert, *volume, *tee, *vis_element;
+ /* Video Thread elements */
+ GstElement *video_queue, *video_cs, *video_balance, *balance_cs;
+ GstElement *video_scaler, *video_sink;
+ /* Audio Thread elements */
+ GstElement *audio_queue, *audio_sink;
+ /* Some useful pads */
+ GstPad *tee_pad1, *tee_pad2;
g_return_val_if_fail (play != NULL, FALSE);
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
+ /* Creating main thread and its elements
+ { fakesrc ! spider ! audioconvert ! volume ! tee } */
+ {
work_thread = gst_element_factory_make ("thread", "work_thread");
if (!GST_IS_ELEMENT (work_thread))
return FALSE;
g_hash_table_insert (play->priv->elements, "work_thread", work_thread);
gst_bin_add (GST_BIN (play), work_thread);
-
- /* Placeholder for the source and autoplugger { fakesrc ! spider } */
+
+ /* Placeholder for datasrc */
source = gst_element_factory_make ("fakesrc", "source");
if (!GST_IS_ELEMENT (source))
return FALSE;
g_hash_table_insert (play->priv->elements, "source", source);
+ /* Autoplugger */
autoplugger = gst_element_factory_make ("spider", "autoplugger");
if (!GST_IS_ELEMENT (autoplugger))
return FALSE;
g_hash_table_insert (play->priv->elements, "autoplugger", autoplugger);
- gst_bin_add_many (GST_BIN (work_thread), source, autoplugger, NULL);
- gst_element_link (source, autoplugger);
+ /* Make sure we convert audio to the needed format */
+ audioconvert = gst_element_factory_make ("audioconvert",
+ "audioconvert");
+ if (!GST_IS_ELEMENT (audioconvert))
+ return FALSE;
+
+ g_hash_table_insert (play->priv->elements, "volume", audioconvert);
+
+ /* Volume control */
+ volume = gst_element_factory_make ("volume", "volume");
+ if (!GST_IS_ELEMENT (volume))
+ return FALSE;
- /* Creating our video output bin
- { queue ! videobalance ! colorspace ! videoscale ! fakesink } */
+ g_hash_table_insert (play->priv->elements, "audioconvert", volume);
+
+ /* Duplicate audio signal to audio sink and visualization thread */
+ tee = gst_element_factory_make ("tee", "tee");
+ if (!GST_IS_ELEMENT (tee))
+ return FALSE;
+
+ tee_pad1 = gst_element_get_request_pad (tee, "src%d");
+ tee_pad2 = gst_element_get_request_pad (tee, "src%d");
+ g_hash_table_insert (play->priv->elements, "tee_pad1", tee_pad1);
+ g_hash_table_insert (play->priv->elements, "tee_pad2", tee_pad2);
+ g_hash_table_insert (play->priv->elements, "tee", tee);
+
+ gst_bin_add_many (GST_BIN (work_thread), source, autoplugger,/* audioconvert,*/
+ volume, tee, NULL);
+ gst_element_link_many (source, autoplugger,/* audioconvert,*/ volume, tee, NULL);
+
+ /* Visualization element placeholder (note: it s not added to the pipeline
+ yet) */
+ vis_element = gst_element_factory_make ("identity", "vis_element");
+ if (!GST_IS_ELEMENT (vis_element))
+ return FALSE;
+
+ g_hash_table_insert (play->priv->elements, "vis_element", vis_element);
+
+ }
+ /* Creating our video output bin */
+ {
video_thread = gst_element_factory_make ("thread", "video_thread");
if (!GST_IS_ELEMENT (video_thread))
return FALSE;
@@ -101,13 +146,24 @@ gst_play_pipeline_setup (GstPlay *play)
g_hash_table_insert (play->priv->elements, "video_thread", video_thread);
gst_bin_add (GST_BIN (work_thread), video_thread);
- /* Buffer queue for our video thread */
+ /* Buffer queue for video data */
video_queue = gst_element_factory_make ("queue", "video_queue");
if (!GST_IS_ELEMENT (video_queue))
return FALSE;
g_hash_table_insert (play->priv->elements, "video_queue", video_queue);
+ /* Colorspace conversion */
+ video_cs = gst_element_factory_make ("ffcolorspace", "video_cs");
+ if (!GST_IS_ELEMENT (video_cs)) {
+ video_cs = gst_element_factory_make ("colorspace", "video_cs");
+ if (!GST_IS_ELEMENT (video_cs))
+ return FALSE;
+ }
+
+ g_hash_table_insert (play->priv->elements, "video_cs", video_cs);
+
+ /* Software colorbalance */
video_balance = gst_element_factory_make ("videobalance",
"video_balance");
if (!GST_IS_ELEMENT (video_balance))
@@ -117,17 +173,14 @@ gst_play_pipeline_setup (GstPlay *play)
video_balance);
/* Colorspace conversion */
- video_colorspace = gst_element_factory_make ("ffcolorspace",
- "video_colorspace");
- if (!GST_IS_ELEMENT (video_colorspace)) {
- video_colorspace = gst_element_factory_make ("colorspace",
- "video_colorspace");
- if (!GST_IS_ELEMENT (video_colorspace))
+ balance_cs = gst_element_factory_make ("ffcolorspace", "balance_cs");
+ if (!GST_IS_ELEMENT (balance_cs)) {
+ balance_cs = gst_element_factory_make ("colorspace", "balance_cs");
+ if (!GST_IS_ELEMENT (balance_cs))
return FALSE;
}
- g_hash_table_insert (play->priv->elements, "video_colorspace",
- video_colorspace);
+ g_hash_table_insert (play->priv->elements, "balance_cs", balance_cs);
/* Software scaling of video stream */
video_scaler = gst_element_factory_make ("videoscale", "video_scaler");
@@ -143,46 +196,18 @@ gst_play_pipeline_setup (GstPlay *play)
g_hash_table_insert (play->priv->elements, "video_sink", video_sink);
- /* Linking, Adding, Ghosting */
- gst_element_link_many (video_queue, video_balance, video_colorspace,
+ gst_bin_add_many (GST_BIN (video_thread), video_queue, video_cs,
+ video_balance, balance_cs, video_scaler, video_sink, NULL);
+ gst_element_link_many (video_queue, video_cs, video_balance, balance_cs,
video_scaler, video_sink, NULL);
- gst_bin_add_many (GST_BIN (video_thread), video_queue, video_balance,
- video_colorspace, video_scaler, video_sink, NULL);
gst_element_add_ghost_pad (video_thread,
gst_element_get_pad (video_queue, "sink"),
"sink");
-
- /* autoplugger ! ffcolorspace ! switch */
- switch_colorspace = NULL;
- switch_colorspace = gst_element_factory_make ("ffcolorspace",
- "switch_colorspace");
- if (!GST_IS_ELEMENT (switch_colorspace)) {
- switch_colorspace = gst_element_factory_make ("colorspace",
- "switch_colorspace");
- if (!GST_IS_ELEMENT (switch_colorspace))
- return FALSE;
+ gst_element_link (autoplugger, video_thread);
}
-
- g_hash_table_insert (play->priv->elements, "switch_colorspace",
- switch_colorspace);
-
- video_switch = gst_element_factory_make ("switch",
- "video_switch");
- if (!GST_IS_ELEMENT (video_switch))
- return FALSE;
-
- g_hash_table_insert (play->priv->elements, "video_switch", video_switch);
-
- gst_bin_add_many (GST_BIN (work_thread), switch_colorspace,
- /*video_switch,*/ NULL);
-
- /* Connecting autoplugger to video switch and video switch to video output */
- gst_element_link_many (autoplugger, switch_colorspace,
- /*video_switch,*/ video_thread, NULL);
- /* gst_element_link (autoplugger, video_thread); */
-
/* Creating our audio output bin
- { queue ! volume ! tee ! { queue ! goom } ! fakesink } */
+ { queue ! fakesink } */
+ {
audio_thread = gst_element_factory_make ("thread", "audio_thread");
if (!GST_IS_ELEMENT (audio_thread))
return FALSE;
@@ -197,85 +222,20 @@ gst_play_pipeline_setup (GstPlay *play)
g_hash_table_insert (play->priv->elements, "audio_queue", audio_queue);
- /* Volume control */
- audio_volume = gst_element_factory_make ("volume", "audio_volume");
- if (!GST_IS_ELEMENT (audio_volume))
- return FALSE;
-
- g_hash_table_insert (play->priv->elements, "audio_volume", audio_volume);
-
- /* Duplicate audio signal to sink and visualization thread */
- audio_tee = gst_element_factory_make ("tee", "audio_tee");
- if (!GST_IS_ELEMENT (audio_tee))
- return FALSE;
-
- audio_tee_pad1 = gst_element_get_request_pad (audio_tee, "src%d");
- audio_tee_pad2 = gst_element_get_request_pad (audio_tee, "src%d");
- g_hash_table_insert (play->priv->elements, "audio_tee_pad1",
- audio_tee_pad1);
- g_hash_table_insert (play->priv->elements, "audio_tee_pad2",
- audio_tee_pad2);
- g_hash_table_insert (play->priv->elements, "audio_tee", audio_tee);
-
/* Placeholder for future audio sink bin */
audio_sink = gst_element_factory_make ("fakesink", "audio_sink");
if (!GST_IS_ELEMENT (audio_sink))
return FALSE;
- audio_sink_pad = gst_element_get_pad (audio_sink, "sink");
- g_hash_table_insert (play->priv->elements, "audio_sink_pad",
- audio_sink_pad);
g_hash_table_insert (play->priv->elements, "audio_sink", audio_sink);
- /* Visualization thread */
- vis_thread = gst_element_factory_make ("thread", "vis_thread");
- if (!GST_IS_ELEMENT (vis_thread))
- return FALSE;
-
- g_hash_table_insert (play->priv->elements, "vis_thread", vis_thread);
-
- /* Buffer queue for our visualization thread */
- vis_queue = gst_element_factory_make ("queue", "vis_queue");
- if (!GST_IS_ELEMENT (vis_queue))
- return FALSE;
-
- g_hash_table_insert (play->priv->elements, "vis_queue", vis_queue);
-
- vis_element = gst_element_factory_make ("identity", "vis_element");
- if (!GST_IS_ELEMENT (vis_element))
- return FALSE;
-
- g_hash_table_insert (play->priv->elements, "vis_element", vis_element);
-
- end_vis_queue = gst_element_factory_make ("queue", "end_vis_queue");
- if (!GST_IS_ELEMENT (end_vis_queue))
- return FALSE;
-
- g_hash_table_insert (play->priv->elements, "end_vis_queue",
- end_vis_queue);
-
- /* Adding, Linking, Ghosting in visualization */
- gst_bin_add_many (GST_BIN (vis_thread), vis_queue, vis_element,
- end_vis_queue, NULL);
- gst_element_link_many (vis_queue, vis_element, end_vis_queue, NULL);
- vis_thread_pad = gst_element_add_ghost_pad (vis_thread,
- gst_element_get_pad (vis_queue, "sink"),
- "sink");
- g_hash_table_insert (play->priv->elements, "vis_thread_pad",
- vis_thread_pad);
-
-
- /* Linking, Adding, Ghosting in audio */
- gst_element_link_many (audio_queue, audio_volume, audio_tee, NULL);
- gst_pad_link (audio_tee_pad1, audio_sink_pad);
- gst_bin_add_many (GST_BIN (audio_thread), audio_queue, audio_volume,
- audio_tee, vis_thread, audio_sink, NULL);
+ gst_bin_add_many (GST_BIN (audio_thread), audio_queue, audio_sink, NULL);
+ gst_element_link (audio_queue, audio_sink);
gst_element_add_ghost_pad (audio_thread,
gst_element_get_pad (audio_queue, "sink"),
"sink");
-
- /* Connecting audio output to autoplugger */
- gst_element_link (autoplugger, audio_thread);
+ gst_pad_link (tee_pad2, gst_element_get_pad (audio_queue, "sink"));
+ }
return TRUE;
}
@@ -505,7 +465,7 @@ gboolean
gst_play_set_location (GstPlay *play, const char *location)
{
GstElement *work_thread, *source, *autoplugger;
- GstElement *switch_colorspace, *audio_thread;
+ GstElement *audioconvert, *video_thread;
g_return_val_if_fail (play != NULL, FALSE);
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
@@ -521,25 +481,24 @@ gst_play_set_location (GstPlay *play, const char *location)
work_thread = g_hash_table_lookup (play->priv->elements, "work_thread");
if (!GST_IS_ELEMENT (work_thread))
return FALSE;
- switch_colorspace = g_hash_table_lookup (play->priv->elements,
- "switch_colorspace");
- if (!GST_IS_ELEMENT (switch_colorspace))
- return FALSE;
- audio_thread = g_hash_table_lookup (play->priv->elements, "audio_thread");
- if (!GST_IS_ELEMENT (audio_thread))
- return FALSE;
source = g_hash_table_lookup (play->priv->elements, "source");
if (!GST_IS_ELEMENT (source))
return FALSE;
autoplugger = g_hash_table_lookup (play->priv->elements, "autoplugger");
if (!GST_IS_ELEMENT (autoplugger))
return FALSE;
+ audioconvert = g_hash_table_lookup (play->priv->elements, "audioconvert");
+ if (!GST_IS_ELEMENT (audioconvert))
+ return FALSE;
+ video_thread = g_hash_table_lookup (play->priv->elements, "video_thread");
+ if (!GST_IS_ELEMENT (video_thread))
+ return FALSE;
/* Spider can autoplugg only once. We remove the actual one and put a new
autoplugger */
gst_element_unlink (source, autoplugger);
- gst_element_unlink (autoplugger, switch_colorspace);
- gst_element_unlink (autoplugger, audio_thread);
+ gst_element_unlink (autoplugger, video_thread);
+ gst_element_unlink (autoplugger, audioconvert);
gst_bin_remove (GST_BIN (work_thread), autoplugger);
autoplugger = gst_element_factory_make ("spider", "autoplugger");
@@ -548,8 +507,8 @@ gst_play_set_location (GstPlay *play, const char *location)
gst_bin_add (GST_BIN (work_thread), autoplugger);
gst_element_link (source, autoplugger);
- gst_element_link (autoplugger, switch_colorspace);
- gst_element_link (autoplugger, audio_thread);
+ gst_element_link (autoplugger, video_thread);
+ gst_element_link (autoplugger, audioconvert);
g_hash_table_replace (play->priv->elements, "autoplugger", autoplugger);
@@ -618,8 +577,9 @@ gst_play_seek_to_time (GstPlay * play, gint64 time_nanos)
}
if (s) {
- GstClock *clock = gst_bin_get_clock (GST_BIN (play));
- play->priv->time_nanos = gst_clock_get_time (clock);
+ GstClockTime time;
+ time = gst_element_get_time (audio_sink_element);
+ play->priv->time_nanos = GST_CLOCK_TIME_IS_VALID (time) ? time : 0;
g_signal_emit (G_OBJECT (play), gst_play_signals[TIME_TICK],
0,play->priv->time_nanos);
}
@@ -745,8 +705,7 @@ gst_play_set_video_sink (GstPlay *play, GstElement *video_sink)
gboolean
gst_play_set_audio_sink (GstPlay *play, GstElement *audio_sink)
{
- GstElement *old_audio_sink, *audio_thread, *audio_sink_element;
- GstPad *audio_tee_pad1, *audio_sink_pad, *old_audio_sink_pad;
+ GstElement *old_audio_sink, *audio_thread, *audio_queue, *audio_sink_element;
g_return_val_if_fail (play != NULL, FALSE);
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
@@ -761,31 +720,21 @@ gst_play_set_audio_sink (GstPlay *play, GstElement *audio_sink)
old_audio_sink = g_hash_table_lookup (play->priv->elements, "audio_sink");
if (!GST_IS_ELEMENT (old_audio_sink))
return FALSE;
- old_audio_sink_pad = g_hash_table_lookup (play->priv->elements,
- "audio_sink_pad");
- if (!GST_IS_PAD (old_audio_sink_pad))
- return FALSE;
audio_thread = g_hash_table_lookup (play->priv->elements, "audio_thread");
if (!GST_IS_ELEMENT (audio_thread))
return FALSE;
- audio_tee_pad1 = g_hash_table_lookup (play->priv->elements,
- "audio_tee_pad1");
- if (!GST_IS_PAD (audio_tee_pad1))
- return FALSE;
- audio_sink_pad = gst_element_get_pad (audio_sink, "sink");
- if (!GST_IS_PAD (audio_sink_pad))
+ audio_queue = g_hash_table_lookup (play->priv->elements, "audio_queue");
+ if (!GST_IS_ELEMENT (audio_queue))
return FALSE;
/* Unlinking old audiosink, removing it from pipeline, putting the new one
and linking it */
- gst_pad_unlink (audio_tee_pad1, old_audio_sink_pad);
+ gst_element_unlink (audio_queue, old_audio_sink);
gst_bin_remove (GST_BIN (audio_thread), old_audio_sink);
gst_bin_add (GST_BIN (audio_thread), audio_sink);
- gst_pad_link (audio_tee_pad1, audio_sink_pad);
+ gst_element_link (audio_queue, audio_sink);
g_hash_table_replace (play->priv->elements, "audio_sink", audio_sink);
- g_hash_table_replace (play->priv->elements, "audio_sink_pad",
- audio_sink_pad);
audio_sink_element = gst_play_get_sink_element (play, audio_sink,
GST_PLAY_SINK_TYPE_AUDIO);
@@ -811,7 +760,8 @@ gst_play_set_audio_sink (GstPlay *play, GstElement *audio_sink)
gboolean
gst_play_set_visualization (GstPlay *play, GstElement *vis_element)
{
- GstElement *old_vis_element, *vis_thread, *vis_queue, *end_vis_queue;
+ GstElement *work_thread, *old_vis_element, *video_thread;
+ GstPad *tee_pad1;
gboolean was_playing = FALSE;
g_return_val_if_fail (play != NULL, FALSE);
@@ -819,34 +769,50 @@ gst_play_set_visualization (GstPlay *play, GstElement *vis_element)
g_return_val_if_fail (vis_element != NULL, FALSE);
g_return_val_if_fail (GST_IS_ELEMENT (vis_element), FALSE);
- /* We bring back the pipeline to READY */
- if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
- gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
- was_playing = TRUE;
- }
-
/* Getting needed objects */
- vis_thread = g_hash_table_lookup (play->priv->elements, "vis_thread");
- if (!GST_IS_ELEMENT (vis_thread))
+ work_thread = g_hash_table_lookup (play->priv->elements, "work_thread");
+ if (!GST_IS_ELEMENT (work_thread))
return FALSE;
old_vis_element = g_hash_table_lookup (play->priv->elements,
"vis_element");
if (!GST_IS_ELEMENT (old_vis_element))
return FALSE;
- vis_queue = g_hash_table_lookup (play->priv->elements, "vis_queue");
- if (!GST_IS_ELEMENT (vis_queue))
+ tee_pad1 = g_hash_table_lookup (play->priv->elements, "tee_pad1");
+ if (!GST_IS_PAD (tee_pad1))
return FALSE;
- end_vis_queue = g_hash_table_lookup (play->priv->elements, "end_vis_queue");
- if (!GST_IS_ELEMENT (end_vis_queue))
+ video_thread = g_hash_table_lookup (play->priv->elements, "video_thread");
+ if (!GST_IS_ELEMENT (video_thread))
return FALSE;
+
+ /* Let's check if the current vis element has a managing bin. If yes that
+ means the element is inside the pipeline and need to be unlinked and
+ removed. We also need to pause the pipeline if it is currently playing. */
+ if (gst_element_get_managing_bin (old_vis_element)) {
+ GstPad *vis_element_pad;
+
+ /* We bring back the pipeline to PAUSED */
+ if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
+ gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
+ was_playing = TRUE;
+ }
- /* Unlinking, removing the old element then adding and linking the new one */
- gst_element_unlink (vis_queue, old_vis_element);
- gst_element_unlink (old_vis_element, end_vis_queue);
- gst_bin_remove (GST_BIN (vis_thread), old_vis_element);
- gst_bin_add (GST_BIN (vis_thread), vis_element);
- gst_element_link (vis_queue, vis_element);
- gst_element_link (vis_element, end_vis_queue);
+ /* Unlinking, removing the old element then adding and linking the new one */
+ vis_element_pad = gst_element_get_pad (old_vis_element, "sink");
+ if (GST_IS_PAD (vis_element_pad))
+ gst_pad_unlink (tee_pad1, vis_element_pad);
+ gst_element_unlink (old_vis_element, video_thread);
+ gst_bin_remove (GST_BIN (work_thread), old_vis_element);
+ gst_bin_add (GST_BIN (work_thread), vis_element);
+ vis_element_pad = gst_element_get_pad (vis_element, "sink");
+ if (GST_IS_PAD (vis_element_pad))
+ gst_pad_link (tee_pad1, vis_element_pad);
+ gst_element_link (vis_element, video_thread);
+ }
+ else {
+ gst_object_unref (GST_OBJECT (old_vis_element));
+ }
+
+ g_hash_table_replace (play->priv->elements, "vis_element", vis_element);
if (was_playing)
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PLAYING);
@@ -867,39 +833,121 @@ gst_play_set_visualization (GstPlay *play, GstElement *vis_element)
gboolean
gst_play_connect_visualization (GstPlay * play, gboolean connect)
{
- GstPad *audio_tee_pad2, *vis_thread_pad;
- gboolean connected = FALSE, was_playing = FALSE;
+ GstElement *work_thread, *vis_element, *autoplugger, *video_thread;
+ GstElement *audioconvert, *source;
+ GstPad *tee_pad1, *vis_element_pad;
g_return_val_if_fail (play != NULL, FALSE);
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
- vis_thread_pad = g_hash_table_lookup (play->priv->elements,
- "vis_thread_pad");
- if (!GST_IS_PAD (vis_thread_pad))
+ /* Getting needed objects */
+ work_thread = g_hash_table_lookup (play->priv->elements, "work_thread");
+ if (!GST_IS_ELEMENT (work_thread))
return FALSE;
- audio_tee_pad2 = g_hash_table_lookup (play->priv->elements,
- "audio_tee_pad2");
- if (!GST_IS_PAD (audio_tee_pad2))
+ vis_element = g_hash_table_lookup (play->priv->elements, "vis_element");
+ if (!GST_IS_ELEMENT (vis_element))
+ return FALSE;
+ tee_pad1 = g_hash_table_lookup (play->priv->elements, "tee_pad1");
+ if (!GST_IS_PAD (tee_pad1))
+ return FALSE;
+ video_thread = g_hash_table_lookup (play->priv->elements, "video_thread");
+ if (!GST_IS_ELEMENT (video_thread))
+ return FALSE;
+ autoplugger = g_hash_table_lookup (play->priv->elements, "autoplugger");
+ if (!GST_IS_ELEMENT (autoplugger))
return FALSE;
+ source = g_hash_table_lookup (play->priv->elements, "source");
+ if (!GST_IS_ELEMENT (source))
+ return FALSE;
+ audioconvert = g_hash_table_lookup (play->priv->elements, "audioconvert");
+ if (!GST_IS_ELEMENT (audioconvert))
+ return FALSE;
+
+ /* Check if the vis element is in the pipeline. That means visualization is
+ connected already */
+ if (gst_element_get_managing_bin (vis_element)) {
+
+ /* If we are supposed to connect then nothing to do we return */
+ if (connect) {
+ return TRUE;
+ }
+
+ /* We have to modify the pipeline. Changing autoplugger requires going to
+ READY */
+ gst_element_set_state (GST_ELEMENT (play), GST_STATE_READY);
+
+ /* Otherwise we unlink and remove the vis element refing it so that
+ it won't be destroyed when removed from the bin. */
+ vis_element_pad = gst_element_get_pad (vis_element, "sink");
+ if (GST_IS_PAD (vis_element_pad))
+ gst_pad_unlink (tee_pad1, vis_element_pad);
+ gst_element_unlink (vis_element, video_thread);
+ gst_object_ref (GST_OBJECT (vis_element));
+ gst_bin_remove (GST_BIN (work_thread), vis_element);
+
+ /* Removing autoplugger */
+ gst_element_unlink (source, autoplugger);
+ gst_element_unlink (autoplugger, audioconvert);
+ gst_bin_remove (GST_BIN (work_thread), autoplugger);
- if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
- gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
- was_playing = TRUE;
+ autoplugger = gst_element_factory_make ("spider", "autoplugger");
+ if (!GST_IS_ELEMENT (autoplugger))
+ return FALSE;
+
+ /* Adding and connecting a new autoplugger connected to video_thread */
+ gst_bin_add (GST_BIN (work_thread), autoplugger);
+ gst_element_link (source, autoplugger);
+ gst_element_link (autoplugger, video_thread);
+ gst_element_link (autoplugger, audioconvert);
+
+ g_hash_table_replace (play->priv->elements, "autoplugger", autoplugger);
}
+ else {
+ GstCaps *filtered_caps;
- if (gst_pad_get_peer (vis_thread_pad) != NULL)
- connected = TRUE;
- else
- connected = FALSE;
-
- if ((connect) && (!connected))
- gst_pad_link (audio_tee_pad2, vis_thread_pad);
- else if ((!connect) && (connected))
- gst_pad_unlink (audio_tee_pad2, vis_thread_pad);
+ /* If we are supposed to disconnect then nothing to do we return */
+ if (!connect) {
+ return TRUE;
+ }
+
+ /* We have to modify the pipeline. Changing autoplugger requires going to
+ READY */
+ gst_element_set_state (GST_ELEMENT (play), GST_STATE_READY);
+
+ /* Removing autoplugger */
+ gst_element_unlink (source, autoplugger);
+ gst_element_unlink (autoplugger, video_thread);
+ gst_element_unlink (autoplugger, audioconvert);
+ gst_bin_remove (GST_BIN (work_thread), autoplugger);
+
+ autoplugger = gst_element_factory_make ("spider", "autoplugger");
+ if (!GST_IS_ELEMENT (autoplugger))
+ return FALSE;
- if (was_playing)
- gst_element_set_state (GST_ELEMENT (play), GST_STATE_PLAYING);
+ /* Adding and connecting a new autoplugger */
+ gst_bin_add (GST_BIN (work_thread), autoplugger);
+ gst_element_link (source, autoplugger);
+ gst_element_link (autoplugger, audioconvert);
+
+ g_hash_table_replace (play->priv->elements, "autoplugger", autoplugger);
+
+ /* Otherwise we add the element to the bin and link it to video_thread */
+ gst_bin_add (GST_BIN (work_thread), vis_element);
+ vis_element_pad = gst_element_get_pad (vis_element, "sink");
+ if (GST_IS_PAD (vis_element_pad))
+ gst_pad_link (tee_pad1, vis_element_pad);
+
+ filtered_caps = gst_caps_from_string ("video/x-raw-rgb, "
+ "framerate = 30.0; "
+ "video/x-raw-yuv, "
+ "framerate = 30.0");
+ if (!gst_element_link_filtered (vis_element, video_thread, filtered_caps))
+ g_message ("failed linking filtered vis with video thread");
+
+ gst_caps_free (filtered_caps);
+ }
+
return TRUE;
}
@@ -916,7 +964,7 @@ gst_play_connect_visualization (GstPlay * play, gboolean connect)
*/
GstElement *
gst_play_get_sink_element (GstPlay *play,
- GstElement *element, GstPlaySinkType sink_type)
+ GstElement *element, GstPlaySinkType sink_type)
{
GList *elements = NULL;
const GList *pads = NULL;