+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.
+
2004-01-22 Ronald Bultje <rbultje@ronald.bitfreak.net>
* sys/oss/gstosselement.c: (gst_osselement_class_probe_devices):
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;
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))
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");
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;
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;
}
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);
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");
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);
}
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);
}
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);
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);
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);
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);
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;
}
*/
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;
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;
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))
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");
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;
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;
}
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);
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");
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);
}
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);
}
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);
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);
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);
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);
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;
}
*/
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;