mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-03 05:59:10 +00:00
gst-libs/gst/play/gstplay.c: Another try in visualization implementation. Still have an issue with switch blocking wh...
Original commit message from CVS: 2004-01-25 Julien MOUTTE <julien@moutte.net> * gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup), (gst_play_identity_handoff), (gst_play_set_location), (gst_play_set_visualization), (gst_play_connect_visualization): Another try in visualization implementation. Still have an issue with switch blocking when pulling from video_queue and only audio comes out of spider. * gst/switch/gstswitch.c: (gst_switch_release_pad), (gst_switch_poll_sinkpads), (gst_switch_class_init): Implementing pad release method. And check if the pad is usable before pulling.
This commit is contained in:
parent
1f4616059c
commit
a77fcb5d88
4 changed files with 367 additions and 282 deletions
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
||||||
|
2004-01-25 Julien MOUTTE <julien@moutte.net>
|
||||||
|
|
||||||
|
* gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup),
|
||||||
|
(gst_play_identity_handoff), (gst_play_set_location),
|
||||||
|
(gst_play_set_visualization), (gst_play_connect_visualization): Another
|
||||||
|
try in visualization implementation. Still have an issue with switch
|
||||||
|
blocking when pulling from video_queue and only audio comes out of
|
||||||
|
spider.
|
||||||
|
* gst/switch/gstswitch.c: (gst_switch_release_pad),
|
||||||
|
(gst_switch_poll_sinkpads), (gst_switch_class_init): Implementing pad
|
||||||
|
release method. And check if the pad is usable before pulling.
|
||||||
|
|
||||||
2004-01-25 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
2004-01-25 Ronald Bultje <rbultje@ronald.bitfreak.net>
|
||||||
|
|
||||||
* gst/videofilter/gstvideobalance.c: (gst_videobalance_dispose),
|
* gst/videofilter/gstvideobalance.c: (gst_videobalance_dispose),
|
||||||
|
|
|
@ -44,6 +44,8 @@ struct _GstPlayPrivate {
|
||||||
|
|
||||||
guint tick_id;
|
guint tick_id;
|
||||||
guint length_id;
|
guint length_id;
|
||||||
|
|
||||||
|
gulong handoff_hid;
|
||||||
};
|
};
|
||||||
|
|
||||||
static guint gst_play_signals[LAST_SIGNAL] = { 0 };
|
static guint gst_play_signals[LAST_SIGNAL] = { 0 };
|
||||||
|
@ -62,10 +64,13 @@ gst_play_pipeline_setup (GstPlay *play)
|
||||||
/* Threads */
|
/* Threads */
|
||||||
GstElement *work_thread, *audio_thread, *video_thread;
|
GstElement *work_thread, *audio_thread, *video_thread;
|
||||||
/* Main Thread elements */
|
/* Main Thread elements */
|
||||||
GstElement *source, *autoplugger, *audioconvert, *volume, *tee, *vis_element;
|
GstElement *source, *autoplugger, *audioconvert, *volume, *tee, *identity;
|
||||||
|
GstElement *identity_cs;
|
||||||
|
/* Visualization bin */
|
||||||
|
GstElement *vis_bin, *vis_queue, *vis_element, *vis_cs;
|
||||||
/* Video Thread elements */
|
/* Video Thread elements */
|
||||||
GstElement *video_queue, *video_cs, *video_balance, *balance_cs;
|
GstElement *video_queue, *video_switch, *video_cs, *video_balance;
|
||||||
GstElement *video_scaler, *video_sink;
|
GstElement *balance_cs, *video_scaler, *video_sink;
|
||||||
/* Audio Thread elements */
|
/* Audio Thread elements */
|
||||||
GstElement *audio_queue, *audio_sink;
|
GstElement *audio_queue, *audio_sink;
|
||||||
/* Some useful pads */
|
/* Some useful pads */
|
||||||
|
@ -74,8 +79,7 @@ gst_play_pipeline_setup (GstPlay *play)
|
||||||
g_return_val_if_fail (play != NULL, FALSE);
|
g_return_val_if_fail (play != NULL, FALSE);
|
||||||
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
||||||
|
|
||||||
/* Creating main thread and its elements
|
/* Creating main thread and its elements */
|
||||||
{ fakesrc ! spider ! audioconvert ! volume ! tee } */
|
|
||||||
{
|
{
|
||||||
work_thread = gst_element_factory_make ("thread", "work_thread");
|
work_thread = gst_element_factory_make ("thread", "work_thread");
|
||||||
if (!GST_IS_ELEMENT (work_thread))
|
if (!GST_IS_ELEMENT (work_thread))
|
||||||
|
@ -128,14 +132,62 @@ gst_play_pipeline_setup (GstPlay *play)
|
||||||
volume, tee, NULL);
|
volume, tee, NULL);
|
||||||
gst_element_link_many (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
|
/* identity ! colorspace ! switch */
|
||||||
yet) */
|
identity = gst_element_factory_make ("identity", "identity");
|
||||||
|
if (!GST_IS_ELEMENT (identity))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
g_hash_table_insert (play->priv->elements, "identity", identity);
|
||||||
|
|
||||||
|
identity_cs = gst_element_factory_make ("ffcolorspace", "identity_cs");
|
||||||
|
if (!GST_IS_ELEMENT (identity_cs)) {
|
||||||
|
identity_cs = gst_element_factory_make ("colorspace", "identity_cs");
|
||||||
|
if (!GST_IS_ELEMENT (identity_cs))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_insert (play->priv->elements, "identity_cs", identity_cs);
|
||||||
|
|
||||||
|
gst_bin_add_many (GST_BIN (work_thread), identity, identity_cs, NULL);
|
||||||
|
gst_element_link_many (autoplugger, identity, identity_cs, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Visualization bin (note: it s not added to the pipeline yet) */
|
||||||
|
{
|
||||||
|
vis_bin = gst_bin_new ("vis_bin");
|
||||||
|
if (!GST_IS_ELEMENT (vis_bin))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
g_hash_table_insert (play->priv->elements, "vis_bin", vis_bin);
|
||||||
|
|
||||||
|
/* Buffer queue for video data */
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* Visualization element placeholder */
|
||||||
vis_element = gst_element_factory_make ("identity", "vis_element");
|
vis_element = gst_element_factory_make ("identity", "vis_element");
|
||||||
if (!GST_IS_ELEMENT (vis_element))
|
if (!GST_IS_ELEMENT (vis_element))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
g_hash_table_insert (play->priv->elements, "vis_element", vis_element);
|
g_hash_table_insert (play->priv->elements, "vis_element", vis_element);
|
||||||
|
|
||||||
|
/* Colorspace conversion */
|
||||||
|
vis_cs = gst_element_factory_make ("ffcolorspace", "vis_cs");
|
||||||
|
if (!GST_IS_ELEMENT (vis_cs)) {
|
||||||
|
vis_cs = gst_element_factory_make ("colorspace", "vis_cs");
|
||||||
|
if (!GST_IS_ELEMENT (vis_cs))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_insert (play->priv->elements, "vis_cs", vis_cs);
|
||||||
|
|
||||||
|
gst_bin_add_many (GST_BIN (vis_bin), vis_queue, vis_element, vis_cs, NULL);
|
||||||
|
gst_element_link_many (vis_queue, vis_element, vis_cs, NULL);
|
||||||
|
gst_element_add_ghost_pad (vis_bin,
|
||||||
|
gst_element_get_pad (vis_cs, "src"), "src");
|
||||||
}
|
}
|
||||||
/* Creating our video output bin */
|
/* Creating our video output bin */
|
||||||
{
|
{
|
||||||
|
@ -153,6 +205,12 @@ gst_play_pipeline_setup (GstPlay *play)
|
||||||
|
|
||||||
g_hash_table_insert (play->priv->elements, "video_queue", video_queue);
|
g_hash_table_insert (play->priv->elements, "video_queue", video_queue);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
/* Colorspace conversion */
|
/* Colorspace conversion */
|
||||||
video_cs = gst_element_factory_make ("ffcolorspace", "video_cs");
|
video_cs = gst_element_factory_make ("ffcolorspace", "video_cs");
|
||||||
if (!GST_IS_ELEMENT (video_cs)) {
|
if (!GST_IS_ELEMENT (video_cs)) {
|
||||||
|
@ -196,14 +254,14 @@ gst_play_pipeline_setup (GstPlay *play)
|
||||||
|
|
||||||
g_hash_table_insert (play->priv->elements, "video_sink", video_sink);
|
g_hash_table_insert (play->priv->elements, "video_sink", video_sink);
|
||||||
|
|
||||||
gst_bin_add_many (GST_BIN (video_thread), video_queue, video_cs,
|
gst_bin_add_many (GST_BIN (video_thread), video_queue, video_switch, video_cs,
|
||||||
video_balance, balance_cs, video_scaler, video_sink, NULL);
|
video_balance, balance_cs, video_scaler, video_sink, NULL);
|
||||||
gst_element_link_many (video_queue, video_cs, video_balance, balance_cs,
|
gst_element_link_many (video_queue, video_switch, video_cs, video_balance,
|
||||||
video_scaler, video_sink, NULL);
|
balance_cs, video_scaler, video_sink, NULL);
|
||||||
gst_element_add_ghost_pad (video_thread,
|
gst_element_add_ghost_pad (video_thread,
|
||||||
gst_element_get_pad (video_queue, "sink"),
|
gst_element_get_pad (video_queue, "sink"),
|
||||||
"sink");
|
"sink");
|
||||||
gst_element_link (autoplugger, video_thread);
|
gst_element_link (identity_cs, video_thread);
|
||||||
}
|
}
|
||||||
/* Creating our audio output bin
|
/* Creating our audio output bin
|
||||||
{ queue ! fakesink } */
|
{ queue ! fakesink } */
|
||||||
|
@ -365,6 +423,14 @@ gst_play_state_change (GstElement *element, GstElementState old,
|
||||||
GST_ELEMENT_CLASS (parent_class)->state_change (element, old, state);
|
GST_ELEMENT_CLASS (parent_class)->state_change (element, old, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_play_identity_handoff (GstElement *identity, GstBuffer *buf, GstPlay *play)
|
||||||
|
{
|
||||||
|
g_signal_handler_disconnect (G_OBJECT (identity), play->priv->handoff_hid);
|
||||||
|
play->priv->handoff_hid = 0;
|
||||||
|
gst_play_connect_visualization (play, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
/* =========================================== */
|
/* =========================================== */
|
||||||
/* */
|
/* */
|
||||||
/* Init & Dispose & Class init */
|
/* Init & Dispose & Class init */
|
||||||
|
@ -465,7 +531,7 @@ gboolean
|
||||||
gst_play_set_location (GstPlay *play, const char *location)
|
gst_play_set_location (GstPlay *play, const char *location)
|
||||||
{
|
{
|
||||||
GstElement *work_thread, *source, *autoplugger;
|
GstElement *work_thread, *source, *autoplugger;
|
||||||
GstElement *audioconvert, *video_thread;
|
GstElement *audioconvert, *identity;
|
||||||
|
|
||||||
g_return_val_if_fail (play != NULL, FALSE);
|
g_return_val_if_fail (play != NULL, FALSE);
|
||||||
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
||||||
|
@ -490,14 +556,14 @@ gst_play_set_location (GstPlay *play, const char *location)
|
||||||
audioconvert = g_hash_table_lookup (play->priv->elements, "audioconvert");
|
audioconvert = g_hash_table_lookup (play->priv->elements, "audioconvert");
|
||||||
if (!GST_IS_ELEMENT (audioconvert))
|
if (!GST_IS_ELEMENT (audioconvert))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
video_thread = g_hash_table_lookup (play->priv->elements, "video_thread");
|
identity = g_hash_table_lookup (play->priv->elements, "identity");
|
||||||
if (!GST_IS_ELEMENT (video_thread))
|
if (!GST_IS_ELEMENT (identity))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Spider can autoplugg only once. We remove the actual one and put a new
|
/* Spider can autoplugg only once. We remove the actual one and put a new
|
||||||
autoplugger */
|
autoplugger */
|
||||||
gst_element_unlink (source, autoplugger);
|
gst_element_unlink (source, autoplugger);
|
||||||
gst_element_unlink (autoplugger, video_thread);
|
gst_element_unlink (autoplugger, identity);
|
||||||
gst_element_unlink (autoplugger, audioconvert);
|
gst_element_unlink (autoplugger, audioconvert);
|
||||||
gst_bin_remove (GST_BIN (work_thread), autoplugger);
|
gst_bin_remove (GST_BIN (work_thread), autoplugger);
|
||||||
|
|
||||||
|
@ -507,7 +573,7 @@ gst_play_set_location (GstPlay *play, const char *location)
|
||||||
|
|
||||||
gst_bin_add (GST_BIN (work_thread), autoplugger);
|
gst_bin_add (GST_BIN (work_thread), autoplugger);
|
||||||
gst_element_link (source, autoplugger);
|
gst_element_link (source, autoplugger);
|
||||||
gst_element_link (autoplugger, video_thread);
|
gst_element_link (autoplugger, identity);
|
||||||
gst_element_link (autoplugger, audioconvert);
|
gst_element_link (autoplugger, audioconvert);
|
||||||
|
|
||||||
g_hash_table_replace (play->priv->elements, "autoplugger", autoplugger);
|
g_hash_table_replace (play->priv->elements, "autoplugger", autoplugger);
|
||||||
|
@ -760,8 +826,7 @@ gst_play_set_audio_sink (GstPlay *play, GstElement *audio_sink)
|
||||||
gboolean
|
gboolean
|
||||||
gst_play_set_visualization (GstPlay *play, GstElement *vis_element)
|
gst_play_set_visualization (GstPlay *play, GstElement *vis_element)
|
||||||
{
|
{
|
||||||
GstElement *work_thread, *old_vis_element, *video_thread;
|
GstElement *vis_bin, *vis_queue, *old_vis_element, *vis_cs;
|
||||||
GstPad *tee_pad1;
|
|
||||||
gboolean was_playing = FALSE;
|
gboolean was_playing = FALSE;
|
||||||
|
|
||||||
g_return_val_if_fail (play != NULL, FALSE);
|
g_return_val_if_fail (play != NULL, FALSE);
|
||||||
|
@ -770,47 +835,30 @@ gst_play_set_visualization (GstPlay *play, GstElement *vis_element)
|
||||||
g_return_val_if_fail (GST_IS_ELEMENT (vis_element), FALSE);
|
g_return_val_if_fail (GST_IS_ELEMENT (vis_element), FALSE);
|
||||||
|
|
||||||
/* Getting needed objects */
|
/* Getting needed objects */
|
||||||
work_thread = g_hash_table_lookup (play->priv->elements, "work_thread");
|
vis_bin = g_hash_table_lookup (play->priv->elements, "vis_bin");
|
||||||
if (!GST_IS_ELEMENT (work_thread))
|
if (!GST_IS_ELEMENT (vis_bin))
|
||||||
|
return FALSE;
|
||||||
|
vis_queue = g_hash_table_lookup (play->priv->elements, "vis_queue");
|
||||||
|
if (!GST_IS_ELEMENT (vis_queue))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
old_vis_element = g_hash_table_lookup (play->priv->elements,
|
old_vis_element = g_hash_table_lookup (play->priv->elements,
|
||||||
"vis_element");
|
"vis_element");
|
||||||
if (!GST_IS_ELEMENT (old_vis_element))
|
if (!GST_IS_ELEMENT (old_vis_element))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
tee_pad1 = g_hash_table_lookup (play->priv->elements, "tee_pad1");
|
vis_cs = g_hash_table_lookup (play->priv->elements, "vis_cs");
|
||||||
if (!GST_IS_PAD (tee_pad1))
|
if (!GST_IS_ELEMENT (vis_cs))
|
||||||
return FALSE;
|
|
||||||
video_thread = g_hash_table_lookup (play->priv->elements, "video_thread");
|
|
||||||
if (!GST_IS_ELEMENT (video_thread))
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Let's check if the current vis element has a managing bin. If yes that
|
/* We bring back the pipeline to PAUSED */
|
||||||
means the element is inside the pipeline and need to be unlinked and
|
if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
|
||||||
removed. We also need to pause the pipeline if it is currently playing. */
|
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
|
||||||
if (gst_element_get_managing_bin (old_vis_element)) {
|
was_playing = TRUE;
|
||||||
GstPad *vis_element_pad;
|
}
|
||||||
|
|
||||||
/* We bring back the pipeline to PAUSED */
|
gst_element_unlink_many (vis_queue, old_vis_element, vis_cs, NULL);
|
||||||
if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
|
gst_bin_remove (GST_BIN (vis_bin), old_vis_element);
|
||||||
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
|
gst_bin_add (GST_BIN (vis_bin), vis_element);
|
||||||
was_playing = TRUE;
|
gst_element_link_many (vis_queue, vis_element, vis_cs, NULL);
|
||||||
}
|
|
||||||
|
|
||||||
/* 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);
|
g_hash_table_replace (play->priv->elements, "vis_element", vis_element);
|
||||||
|
|
||||||
|
@ -833,121 +881,88 @@ gst_play_set_visualization (GstPlay *play, GstElement *vis_element)
|
||||||
gboolean
|
gboolean
|
||||||
gst_play_connect_visualization (GstPlay * play, gboolean connect)
|
gst_play_connect_visualization (GstPlay * play, gboolean connect)
|
||||||
{
|
{
|
||||||
GstElement *work_thread, *vis_element, *autoplugger, *video_thread;
|
GstElement *video_thread, *vis_queue, *vis_bin, *video_switch, *identity;
|
||||||
GstElement *audioconvert, *source;
|
GstPad *tee_pad1, *vis_queue_pad, *vis_bin_pad, *switch_pad;
|
||||||
GstPad *tee_pad1, *vis_element_pad;
|
gboolean was_playing = FALSE;
|
||||||
|
|
||||||
g_return_val_if_fail (play != NULL, FALSE);
|
g_return_val_if_fail (play != NULL, FALSE);
|
||||||
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
||||||
|
|
||||||
/* Getting needed objects */
|
/* Getting needed objects */
|
||||||
work_thread = g_hash_table_lookup (play->priv->elements, "work_thread");
|
video_thread = g_hash_table_lookup (play->priv->elements, "video_thread");
|
||||||
if (!GST_IS_ELEMENT (work_thread))
|
if (!GST_IS_ELEMENT (video_thread))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
vis_element = g_hash_table_lookup (play->priv->elements, "vis_element");
|
vis_bin = g_hash_table_lookup (play->priv->elements, "vis_bin");
|
||||||
if (!GST_IS_ELEMENT (vis_element))
|
if (!GST_IS_ELEMENT (vis_bin))
|
||||||
|
return FALSE;
|
||||||
|
vis_queue = g_hash_table_lookup (play->priv->elements, "vis_queue");
|
||||||
|
if (!GST_IS_ELEMENT (vis_queue))
|
||||||
|
return FALSE;
|
||||||
|
video_switch = g_hash_table_lookup (play->priv->elements, "video_switch");
|
||||||
|
if (!GST_IS_ELEMENT (video_switch))
|
||||||
|
return FALSE;
|
||||||
|
identity = g_hash_table_lookup (play->priv->elements, "identity");
|
||||||
|
if (!GST_IS_ELEMENT (identity))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
tee_pad1 = g_hash_table_lookup (play->priv->elements, "tee_pad1");
|
tee_pad1 = g_hash_table_lookup (play->priv->elements, "tee_pad1");
|
||||||
if (!GST_IS_PAD (tee_pad1))
|
if (!GST_IS_PAD (tee_pad1))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
video_thread = g_hash_table_lookup (play->priv->elements, "video_thread");
|
|
||||||
if (!GST_IS_ELEMENT (video_thread))
|
vis_queue_pad = gst_element_get_pad (vis_queue, "sink");
|
||||||
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
|
/* Check if the vis element is in the pipeline. That means visualization is
|
||||||
connected already */
|
connected already */
|
||||||
if (gst_element_get_managing_bin (vis_element)) {
|
if (gst_element_get_managing_bin (vis_bin)) {
|
||||||
|
|
||||||
/* If we are supposed to connect then nothing to do we return */
|
/* If we are supposed to connect then nothing to do we return */
|
||||||
if (connect) {
|
if (connect) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have to modify the pipeline. Changing autoplugger requires going to
|
/* Disconnecting visualization */
|
||||||
READY */
|
|
||||||
gst_element_set_state (GST_ELEMENT (play), GST_STATE_READY);
|
|
||||||
|
|
||||||
/* Otherwise we unlink and remove the vis element refing it so that
|
/* We bring back the pipeline to PAUSED */
|
||||||
it won't be destroyed when removed from the bin. */
|
if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
|
||||||
vis_element_pad = gst_element_get_pad (vis_element, "sink");
|
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
|
||||||
if (GST_IS_PAD (vis_element_pad))
|
was_playing = TRUE;
|
||||||
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 */
|
/* Unlinking, removing */
|
||||||
gst_element_unlink (source, autoplugger);
|
gst_pad_unlink (tee_pad1, vis_queue_pad);
|
||||||
gst_element_unlink (autoplugger, audioconvert);
|
vis_bin_pad = gst_element_get_pad (vis_bin, "src");
|
||||||
gst_bin_remove (GST_BIN (work_thread), autoplugger);
|
switch_pad = gst_pad_get_peer (vis_bin_pad);
|
||||||
|
gst_pad_unlink (vis_bin_pad, switch_pad);
|
||||||
autoplugger = gst_element_factory_make ("spider", "autoplugger");
|
gst_element_release_request_pad (video_switch, switch_pad);
|
||||||
if (!GST_IS_ELEMENT (autoplugger))
|
gst_object_ref (GST_OBJECT (vis_bin));
|
||||||
return FALSE;
|
gst_bin_remove (GST_BIN (video_thread), vis_bin);
|
||||||
|
|
||||||
/* 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 {
|
else {
|
||||||
GstCaps *filtered_caps;
|
|
||||||
|
|
||||||
/* If we are supposed to disconnect then nothing to do we return */
|
/* If we are supposed to disconnect then nothing to do we return */
|
||||||
if (!connect) {
|
if (!connect) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have to modify the pipeline. Changing autoplugger requires going to
|
/* Connecting visualization */
|
||||||
READY */
|
|
||||||
gst_element_set_state (GST_ELEMENT (play), GST_STATE_READY);
|
|
||||||
|
|
||||||
/* Removing autoplugger */
|
/* We bring back the pipeline to PAUSED */
|
||||||
gst_element_unlink (source, autoplugger);
|
if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
|
||||||
gst_element_unlink (autoplugger, video_thread);
|
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
|
||||||
gst_element_unlink (autoplugger, audioconvert);
|
was_playing = TRUE;
|
||||||
gst_bin_remove (GST_BIN (work_thread), autoplugger);
|
}
|
||||||
|
|
||||||
autoplugger = gst_element_factory_make ("spider", "autoplugger");
|
|
||||||
if (!GST_IS_ELEMENT (autoplugger))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* 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);
|
/* Adding, linking */
|
||||||
|
play->priv->handoff_hid = g_signal_connect (G_OBJECT (identity),
|
||||||
/* Otherwise we add the element to the bin and link it to video_thread */
|
"handoff",
|
||||||
gst_bin_add (GST_BIN (work_thread), vis_element);
|
G_CALLBACK (gst_play_identity_handoff), play);
|
||||||
vis_element_pad = gst_element_get_pad (vis_element, "sink");
|
gst_bin_add (GST_BIN (video_thread), vis_bin);
|
||||||
if (GST_IS_PAD (vis_element_pad))
|
gst_pad_link (tee_pad1, vis_queue_pad);
|
||||||
gst_pad_link (tee_pad1, vis_element_pad);
|
gst_element_link (vis_bin, video_switch);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (was_playing)
|
||||||
|
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PLAYING);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,8 @@ struct _GstPlayPrivate {
|
||||||
|
|
||||||
guint tick_id;
|
guint tick_id;
|
||||||
guint length_id;
|
guint length_id;
|
||||||
|
|
||||||
|
gulong handoff_hid;
|
||||||
};
|
};
|
||||||
|
|
||||||
static guint gst_play_signals[LAST_SIGNAL] = { 0 };
|
static guint gst_play_signals[LAST_SIGNAL] = { 0 };
|
||||||
|
@ -62,10 +64,13 @@ gst_play_pipeline_setup (GstPlay *play)
|
||||||
/* Threads */
|
/* Threads */
|
||||||
GstElement *work_thread, *audio_thread, *video_thread;
|
GstElement *work_thread, *audio_thread, *video_thread;
|
||||||
/* Main Thread elements */
|
/* Main Thread elements */
|
||||||
GstElement *source, *autoplugger, *audioconvert, *volume, *tee, *vis_element;
|
GstElement *source, *autoplugger, *audioconvert, *volume, *tee, *identity;
|
||||||
|
GstElement *identity_cs;
|
||||||
|
/* Visualization bin */
|
||||||
|
GstElement *vis_bin, *vis_queue, *vis_element, *vis_cs;
|
||||||
/* Video Thread elements */
|
/* Video Thread elements */
|
||||||
GstElement *video_queue, *video_cs, *video_balance, *balance_cs;
|
GstElement *video_queue, *video_switch, *video_cs, *video_balance;
|
||||||
GstElement *video_scaler, *video_sink;
|
GstElement *balance_cs, *video_scaler, *video_sink;
|
||||||
/* Audio Thread elements */
|
/* Audio Thread elements */
|
||||||
GstElement *audio_queue, *audio_sink;
|
GstElement *audio_queue, *audio_sink;
|
||||||
/* Some useful pads */
|
/* Some useful pads */
|
||||||
|
@ -74,8 +79,7 @@ gst_play_pipeline_setup (GstPlay *play)
|
||||||
g_return_val_if_fail (play != NULL, FALSE);
|
g_return_val_if_fail (play != NULL, FALSE);
|
||||||
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
||||||
|
|
||||||
/* Creating main thread and its elements
|
/* Creating main thread and its elements */
|
||||||
{ fakesrc ! spider ! audioconvert ! volume ! tee } */
|
|
||||||
{
|
{
|
||||||
work_thread = gst_element_factory_make ("thread", "work_thread");
|
work_thread = gst_element_factory_make ("thread", "work_thread");
|
||||||
if (!GST_IS_ELEMENT (work_thread))
|
if (!GST_IS_ELEMENT (work_thread))
|
||||||
|
@ -128,14 +132,62 @@ gst_play_pipeline_setup (GstPlay *play)
|
||||||
volume, tee, NULL);
|
volume, tee, NULL);
|
||||||
gst_element_link_many (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
|
/* identity ! colorspace ! switch */
|
||||||
yet) */
|
identity = gst_element_factory_make ("identity", "identity");
|
||||||
|
if (!GST_IS_ELEMENT (identity))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
g_hash_table_insert (play->priv->elements, "identity", identity);
|
||||||
|
|
||||||
|
identity_cs = gst_element_factory_make ("ffcolorspace", "identity_cs");
|
||||||
|
if (!GST_IS_ELEMENT (identity_cs)) {
|
||||||
|
identity_cs = gst_element_factory_make ("colorspace", "identity_cs");
|
||||||
|
if (!GST_IS_ELEMENT (identity_cs))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_insert (play->priv->elements, "identity_cs", identity_cs);
|
||||||
|
|
||||||
|
gst_bin_add_many (GST_BIN (work_thread), identity, identity_cs, NULL);
|
||||||
|
gst_element_link_many (autoplugger, identity, identity_cs, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Visualization bin (note: it s not added to the pipeline yet) */
|
||||||
|
{
|
||||||
|
vis_bin = gst_bin_new ("vis_bin");
|
||||||
|
if (!GST_IS_ELEMENT (vis_bin))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
g_hash_table_insert (play->priv->elements, "vis_bin", vis_bin);
|
||||||
|
|
||||||
|
/* Buffer queue for video data */
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* Visualization element placeholder */
|
||||||
vis_element = gst_element_factory_make ("identity", "vis_element");
|
vis_element = gst_element_factory_make ("identity", "vis_element");
|
||||||
if (!GST_IS_ELEMENT (vis_element))
|
if (!GST_IS_ELEMENT (vis_element))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
g_hash_table_insert (play->priv->elements, "vis_element", vis_element);
|
g_hash_table_insert (play->priv->elements, "vis_element", vis_element);
|
||||||
|
|
||||||
|
/* Colorspace conversion */
|
||||||
|
vis_cs = gst_element_factory_make ("ffcolorspace", "vis_cs");
|
||||||
|
if (!GST_IS_ELEMENT (vis_cs)) {
|
||||||
|
vis_cs = gst_element_factory_make ("colorspace", "vis_cs");
|
||||||
|
if (!GST_IS_ELEMENT (vis_cs))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_insert (play->priv->elements, "vis_cs", vis_cs);
|
||||||
|
|
||||||
|
gst_bin_add_many (GST_BIN (vis_bin), vis_queue, vis_element, vis_cs, NULL);
|
||||||
|
gst_element_link_many (vis_queue, vis_element, vis_cs, NULL);
|
||||||
|
gst_element_add_ghost_pad (vis_bin,
|
||||||
|
gst_element_get_pad (vis_cs, "src"), "src");
|
||||||
}
|
}
|
||||||
/* Creating our video output bin */
|
/* Creating our video output bin */
|
||||||
{
|
{
|
||||||
|
@ -153,6 +205,12 @@ gst_play_pipeline_setup (GstPlay *play)
|
||||||
|
|
||||||
g_hash_table_insert (play->priv->elements, "video_queue", video_queue);
|
g_hash_table_insert (play->priv->elements, "video_queue", video_queue);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
/* Colorspace conversion */
|
/* Colorspace conversion */
|
||||||
video_cs = gst_element_factory_make ("ffcolorspace", "video_cs");
|
video_cs = gst_element_factory_make ("ffcolorspace", "video_cs");
|
||||||
if (!GST_IS_ELEMENT (video_cs)) {
|
if (!GST_IS_ELEMENT (video_cs)) {
|
||||||
|
@ -196,14 +254,14 @@ gst_play_pipeline_setup (GstPlay *play)
|
||||||
|
|
||||||
g_hash_table_insert (play->priv->elements, "video_sink", video_sink);
|
g_hash_table_insert (play->priv->elements, "video_sink", video_sink);
|
||||||
|
|
||||||
gst_bin_add_many (GST_BIN (video_thread), video_queue, video_cs,
|
gst_bin_add_many (GST_BIN (video_thread), video_queue, video_switch, video_cs,
|
||||||
video_balance, balance_cs, video_scaler, video_sink, NULL);
|
video_balance, balance_cs, video_scaler, video_sink, NULL);
|
||||||
gst_element_link_many (video_queue, video_cs, video_balance, balance_cs,
|
gst_element_link_many (video_queue, video_switch, video_cs, video_balance,
|
||||||
video_scaler, video_sink, NULL);
|
balance_cs, video_scaler, video_sink, NULL);
|
||||||
gst_element_add_ghost_pad (video_thread,
|
gst_element_add_ghost_pad (video_thread,
|
||||||
gst_element_get_pad (video_queue, "sink"),
|
gst_element_get_pad (video_queue, "sink"),
|
||||||
"sink");
|
"sink");
|
||||||
gst_element_link (autoplugger, video_thread);
|
gst_element_link (identity_cs, video_thread);
|
||||||
}
|
}
|
||||||
/* Creating our audio output bin
|
/* Creating our audio output bin
|
||||||
{ queue ! fakesink } */
|
{ queue ! fakesink } */
|
||||||
|
@ -365,6 +423,14 @@ gst_play_state_change (GstElement *element, GstElementState old,
|
||||||
GST_ELEMENT_CLASS (parent_class)->state_change (element, old, state);
|
GST_ELEMENT_CLASS (parent_class)->state_change (element, old, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_play_identity_handoff (GstElement *identity, GstBuffer *buf, GstPlay *play)
|
||||||
|
{
|
||||||
|
g_signal_handler_disconnect (G_OBJECT (identity), play->priv->handoff_hid);
|
||||||
|
play->priv->handoff_hid = 0;
|
||||||
|
gst_play_connect_visualization (play, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
/* =========================================== */
|
/* =========================================== */
|
||||||
/* */
|
/* */
|
||||||
/* Init & Dispose & Class init */
|
/* Init & Dispose & Class init */
|
||||||
|
@ -465,7 +531,7 @@ gboolean
|
||||||
gst_play_set_location (GstPlay *play, const char *location)
|
gst_play_set_location (GstPlay *play, const char *location)
|
||||||
{
|
{
|
||||||
GstElement *work_thread, *source, *autoplugger;
|
GstElement *work_thread, *source, *autoplugger;
|
||||||
GstElement *audioconvert, *video_thread;
|
GstElement *audioconvert, *identity;
|
||||||
|
|
||||||
g_return_val_if_fail (play != NULL, FALSE);
|
g_return_val_if_fail (play != NULL, FALSE);
|
||||||
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
||||||
|
@ -490,14 +556,14 @@ gst_play_set_location (GstPlay *play, const char *location)
|
||||||
audioconvert = g_hash_table_lookup (play->priv->elements, "audioconvert");
|
audioconvert = g_hash_table_lookup (play->priv->elements, "audioconvert");
|
||||||
if (!GST_IS_ELEMENT (audioconvert))
|
if (!GST_IS_ELEMENT (audioconvert))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
video_thread = g_hash_table_lookup (play->priv->elements, "video_thread");
|
identity = g_hash_table_lookup (play->priv->elements, "identity");
|
||||||
if (!GST_IS_ELEMENT (video_thread))
|
if (!GST_IS_ELEMENT (identity))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Spider can autoplugg only once. We remove the actual one and put a new
|
/* Spider can autoplugg only once. We remove the actual one and put a new
|
||||||
autoplugger */
|
autoplugger */
|
||||||
gst_element_unlink (source, autoplugger);
|
gst_element_unlink (source, autoplugger);
|
||||||
gst_element_unlink (autoplugger, video_thread);
|
gst_element_unlink (autoplugger, identity);
|
||||||
gst_element_unlink (autoplugger, audioconvert);
|
gst_element_unlink (autoplugger, audioconvert);
|
||||||
gst_bin_remove (GST_BIN (work_thread), autoplugger);
|
gst_bin_remove (GST_BIN (work_thread), autoplugger);
|
||||||
|
|
||||||
|
@ -507,7 +573,7 @@ gst_play_set_location (GstPlay *play, const char *location)
|
||||||
|
|
||||||
gst_bin_add (GST_BIN (work_thread), autoplugger);
|
gst_bin_add (GST_BIN (work_thread), autoplugger);
|
||||||
gst_element_link (source, autoplugger);
|
gst_element_link (source, autoplugger);
|
||||||
gst_element_link (autoplugger, video_thread);
|
gst_element_link (autoplugger, identity);
|
||||||
gst_element_link (autoplugger, audioconvert);
|
gst_element_link (autoplugger, audioconvert);
|
||||||
|
|
||||||
g_hash_table_replace (play->priv->elements, "autoplugger", autoplugger);
|
g_hash_table_replace (play->priv->elements, "autoplugger", autoplugger);
|
||||||
|
@ -760,8 +826,7 @@ gst_play_set_audio_sink (GstPlay *play, GstElement *audio_sink)
|
||||||
gboolean
|
gboolean
|
||||||
gst_play_set_visualization (GstPlay *play, GstElement *vis_element)
|
gst_play_set_visualization (GstPlay *play, GstElement *vis_element)
|
||||||
{
|
{
|
||||||
GstElement *work_thread, *old_vis_element, *video_thread;
|
GstElement *vis_bin, *vis_queue, *old_vis_element, *vis_cs;
|
||||||
GstPad *tee_pad1;
|
|
||||||
gboolean was_playing = FALSE;
|
gboolean was_playing = FALSE;
|
||||||
|
|
||||||
g_return_val_if_fail (play != NULL, FALSE);
|
g_return_val_if_fail (play != NULL, FALSE);
|
||||||
|
@ -770,47 +835,30 @@ gst_play_set_visualization (GstPlay *play, GstElement *vis_element)
|
||||||
g_return_val_if_fail (GST_IS_ELEMENT (vis_element), FALSE);
|
g_return_val_if_fail (GST_IS_ELEMENT (vis_element), FALSE);
|
||||||
|
|
||||||
/* Getting needed objects */
|
/* Getting needed objects */
|
||||||
work_thread = g_hash_table_lookup (play->priv->elements, "work_thread");
|
vis_bin = g_hash_table_lookup (play->priv->elements, "vis_bin");
|
||||||
if (!GST_IS_ELEMENT (work_thread))
|
if (!GST_IS_ELEMENT (vis_bin))
|
||||||
|
return FALSE;
|
||||||
|
vis_queue = g_hash_table_lookup (play->priv->elements, "vis_queue");
|
||||||
|
if (!GST_IS_ELEMENT (vis_queue))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
old_vis_element = g_hash_table_lookup (play->priv->elements,
|
old_vis_element = g_hash_table_lookup (play->priv->elements,
|
||||||
"vis_element");
|
"vis_element");
|
||||||
if (!GST_IS_ELEMENT (old_vis_element))
|
if (!GST_IS_ELEMENT (old_vis_element))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
tee_pad1 = g_hash_table_lookup (play->priv->elements, "tee_pad1");
|
vis_cs = g_hash_table_lookup (play->priv->elements, "vis_cs");
|
||||||
if (!GST_IS_PAD (tee_pad1))
|
if (!GST_IS_ELEMENT (vis_cs))
|
||||||
return FALSE;
|
|
||||||
video_thread = g_hash_table_lookup (play->priv->elements, "video_thread");
|
|
||||||
if (!GST_IS_ELEMENT (video_thread))
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Let's check if the current vis element has a managing bin. If yes that
|
/* We bring back the pipeline to PAUSED */
|
||||||
means the element is inside the pipeline and need to be unlinked and
|
if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
|
||||||
removed. We also need to pause the pipeline if it is currently playing. */
|
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
|
||||||
if (gst_element_get_managing_bin (old_vis_element)) {
|
was_playing = TRUE;
|
||||||
GstPad *vis_element_pad;
|
}
|
||||||
|
|
||||||
/* We bring back the pipeline to PAUSED */
|
gst_element_unlink_many (vis_queue, old_vis_element, vis_cs, NULL);
|
||||||
if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
|
gst_bin_remove (GST_BIN (vis_bin), old_vis_element);
|
||||||
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
|
gst_bin_add (GST_BIN (vis_bin), vis_element);
|
||||||
was_playing = TRUE;
|
gst_element_link_many (vis_queue, vis_element, vis_cs, NULL);
|
||||||
}
|
|
||||||
|
|
||||||
/* 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);
|
g_hash_table_replace (play->priv->elements, "vis_element", vis_element);
|
||||||
|
|
||||||
|
@ -833,121 +881,88 @@ gst_play_set_visualization (GstPlay *play, GstElement *vis_element)
|
||||||
gboolean
|
gboolean
|
||||||
gst_play_connect_visualization (GstPlay * play, gboolean connect)
|
gst_play_connect_visualization (GstPlay * play, gboolean connect)
|
||||||
{
|
{
|
||||||
GstElement *work_thread, *vis_element, *autoplugger, *video_thread;
|
GstElement *video_thread, *vis_queue, *vis_bin, *video_switch, *identity;
|
||||||
GstElement *audioconvert, *source;
|
GstPad *tee_pad1, *vis_queue_pad, *vis_bin_pad, *switch_pad;
|
||||||
GstPad *tee_pad1, *vis_element_pad;
|
gboolean was_playing = FALSE;
|
||||||
|
|
||||||
g_return_val_if_fail (play != NULL, FALSE);
|
g_return_val_if_fail (play != NULL, FALSE);
|
||||||
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
||||||
|
|
||||||
/* Getting needed objects */
|
/* Getting needed objects */
|
||||||
work_thread = g_hash_table_lookup (play->priv->elements, "work_thread");
|
video_thread = g_hash_table_lookup (play->priv->elements, "video_thread");
|
||||||
if (!GST_IS_ELEMENT (work_thread))
|
if (!GST_IS_ELEMENT (video_thread))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
vis_element = g_hash_table_lookup (play->priv->elements, "vis_element");
|
vis_bin = g_hash_table_lookup (play->priv->elements, "vis_bin");
|
||||||
if (!GST_IS_ELEMENT (vis_element))
|
if (!GST_IS_ELEMENT (vis_bin))
|
||||||
|
return FALSE;
|
||||||
|
vis_queue = g_hash_table_lookup (play->priv->elements, "vis_queue");
|
||||||
|
if (!GST_IS_ELEMENT (vis_queue))
|
||||||
|
return FALSE;
|
||||||
|
video_switch = g_hash_table_lookup (play->priv->elements, "video_switch");
|
||||||
|
if (!GST_IS_ELEMENT (video_switch))
|
||||||
|
return FALSE;
|
||||||
|
identity = g_hash_table_lookup (play->priv->elements, "identity");
|
||||||
|
if (!GST_IS_ELEMENT (identity))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
tee_pad1 = g_hash_table_lookup (play->priv->elements, "tee_pad1");
|
tee_pad1 = g_hash_table_lookup (play->priv->elements, "tee_pad1");
|
||||||
if (!GST_IS_PAD (tee_pad1))
|
if (!GST_IS_PAD (tee_pad1))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
video_thread = g_hash_table_lookup (play->priv->elements, "video_thread");
|
|
||||||
if (!GST_IS_ELEMENT (video_thread))
|
vis_queue_pad = gst_element_get_pad (vis_queue, "sink");
|
||||||
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
|
/* Check if the vis element is in the pipeline. That means visualization is
|
||||||
connected already */
|
connected already */
|
||||||
if (gst_element_get_managing_bin (vis_element)) {
|
if (gst_element_get_managing_bin (vis_bin)) {
|
||||||
|
|
||||||
/* If we are supposed to connect then nothing to do we return */
|
/* If we are supposed to connect then nothing to do we return */
|
||||||
if (connect) {
|
if (connect) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have to modify the pipeline. Changing autoplugger requires going to
|
/* Disconnecting visualization */
|
||||||
READY */
|
|
||||||
gst_element_set_state (GST_ELEMENT (play), GST_STATE_READY);
|
|
||||||
|
|
||||||
/* Otherwise we unlink and remove the vis element refing it so that
|
/* We bring back the pipeline to PAUSED */
|
||||||
it won't be destroyed when removed from the bin. */
|
if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
|
||||||
vis_element_pad = gst_element_get_pad (vis_element, "sink");
|
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
|
||||||
if (GST_IS_PAD (vis_element_pad))
|
was_playing = TRUE;
|
||||||
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 */
|
/* Unlinking, removing */
|
||||||
gst_element_unlink (source, autoplugger);
|
gst_pad_unlink (tee_pad1, vis_queue_pad);
|
||||||
gst_element_unlink (autoplugger, audioconvert);
|
vis_bin_pad = gst_element_get_pad (vis_bin, "src");
|
||||||
gst_bin_remove (GST_BIN (work_thread), autoplugger);
|
switch_pad = gst_pad_get_peer (vis_bin_pad);
|
||||||
|
gst_pad_unlink (vis_bin_pad, switch_pad);
|
||||||
autoplugger = gst_element_factory_make ("spider", "autoplugger");
|
gst_element_release_request_pad (video_switch, switch_pad);
|
||||||
if (!GST_IS_ELEMENT (autoplugger))
|
gst_object_ref (GST_OBJECT (vis_bin));
|
||||||
return FALSE;
|
gst_bin_remove (GST_BIN (video_thread), vis_bin);
|
||||||
|
|
||||||
/* 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 {
|
else {
|
||||||
GstCaps *filtered_caps;
|
|
||||||
|
|
||||||
/* If we are supposed to disconnect then nothing to do we return */
|
/* If we are supposed to disconnect then nothing to do we return */
|
||||||
if (!connect) {
|
if (!connect) {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have to modify the pipeline. Changing autoplugger requires going to
|
/* Connecting visualization */
|
||||||
READY */
|
|
||||||
gst_element_set_state (GST_ELEMENT (play), GST_STATE_READY);
|
|
||||||
|
|
||||||
/* Removing autoplugger */
|
/* We bring back the pipeline to PAUSED */
|
||||||
gst_element_unlink (source, autoplugger);
|
if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
|
||||||
gst_element_unlink (autoplugger, video_thread);
|
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
|
||||||
gst_element_unlink (autoplugger, audioconvert);
|
was_playing = TRUE;
|
||||||
gst_bin_remove (GST_BIN (work_thread), autoplugger);
|
}
|
||||||
|
|
||||||
autoplugger = gst_element_factory_make ("spider", "autoplugger");
|
|
||||||
if (!GST_IS_ELEMENT (autoplugger))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* 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);
|
/* Adding, linking */
|
||||||
|
play->priv->handoff_hid = g_signal_connect (G_OBJECT (identity),
|
||||||
/* Otherwise we add the element to the bin and link it to video_thread */
|
"handoff",
|
||||||
gst_bin_add (GST_BIN (work_thread), vis_element);
|
G_CALLBACK (gst_play_identity_handoff), play);
|
||||||
vis_element_pad = gst_element_get_pad (vis_element, "sink");
|
gst_bin_add (GST_BIN (video_thread), vis_bin);
|
||||||
if (GST_IS_PAD (vis_element_pad))
|
gst_pad_link (tee_pad1, vis_queue_pad);
|
||||||
gst_pad_link (tee_pad1, vis_element_pad);
|
gst_element_link (vis_bin, video_switch);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (was_playing)
|
||||||
|
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PLAYING);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,44 @@ static GstElementClass *parent_class = NULL;
|
||||||
/* */
|
/* */
|
||||||
/* ============================================================= */
|
/* ============================================================= */
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_switch_release_pad (GstElement *element, GstPad *pad)
|
||||||
|
{
|
||||||
|
GList *sinkpads = NULL;
|
||||||
|
GstSwitch *gstswitch = NULL;
|
||||||
|
GstSwitchPad *switchpad = NULL;
|
||||||
|
|
||||||
|
g_return_if_fail (GST_IS_SWITCH (element));
|
||||||
|
|
||||||
|
gstswitch = GST_SWITCH (element);
|
||||||
|
|
||||||
|
sinkpads = gstswitch->sinkpads;
|
||||||
|
|
||||||
|
/* Walking through our pad list searching for the pad we want to release */
|
||||||
|
while (sinkpads) {
|
||||||
|
switchpad = sinkpads->data;
|
||||||
|
|
||||||
|
if (switchpad && switchpad->sinkpad == pad)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
switchpad = NULL;
|
||||||
|
|
||||||
|
sinkpads = g_list_next (sinkpads);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Releasing the found pad */
|
||||||
|
if (switchpad) {
|
||||||
|
if (!switchpad->forwarded && switchpad->data)
|
||||||
|
gst_data_unref (switchpad->data);
|
||||||
|
gst_element_remove_pad (element, pad);
|
||||||
|
gstswitch->sinkpads = g_list_remove (gstswitch->sinkpads, switchpad);
|
||||||
|
gstswitch->nb_sinkpads--;
|
||||||
|
if (gstswitch->active_sinkpad >= gstswitch->nb_sinkpads)
|
||||||
|
gstswitch->active_sinkpad = 0;
|
||||||
|
g_free (switchpad);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static GstPad*
|
static GstPad*
|
||||||
gst_switch_request_new_pad (GstElement *element,
|
gst_switch_request_new_pad (GstElement *element,
|
||||||
GstPadTemplate *templ,
|
GstPadTemplate *templ,
|
||||||
|
@ -120,24 +158,28 @@ gst_switch_poll_sinkpads (GstSwitch *gstswitch)
|
||||||
|
|
||||||
while (pads) {
|
while (pads) {
|
||||||
GstSwitchPad *switchpad = pads->data;
|
GstSwitchPad *switchpad = pads->data;
|
||||||
GstData *data = gst_pad_pull (switchpad->sinkpad);
|
GstData *data = NULL;
|
||||||
if (GST_IS_EVENT (data) &&
|
|
||||||
(GST_EVENT_TYPE (GST_EVENT (data)) == GST_EVENT_EOS)) {
|
/* If that data was not forwarded we unref it */
|
||||||
/* If that data was not forwarded we unref it */
|
if (!switchpad->forwarded && switchpad->data) {
|
||||||
if (!switchpad->forwarded && switchpad->data) {
|
|
||||||
gst_data_unref (switchpad->data);
|
gst_data_unref (switchpad->data);
|
||||||
switchpad->data = NULL;
|
switchpad->data = NULL;
|
||||||
}
|
}
|
||||||
gst_event_unref (GST_EVENT (data));
|
|
||||||
|
if (GST_PAD_IS_USABLE (switchpad->sinkpad)) {
|
||||||
|
data = gst_pad_pull (switchpad->sinkpad);
|
||||||
|
|
||||||
|
if (GST_IS_EVENT (data) &&
|
||||||
|
(GST_EVENT_TYPE (GST_EVENT (data)) == GST_EVENT_EOS)) {
|
||||||
|
gst_event_unref (GST_EVENT (data));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switchpad->data = data;
|
||||||
|
switchpad->forwarded = FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* If that data was not forwarded we unref it */
|
g_message ("not pulling from pad %s", gst_pad_get_name (switchpad->sinkpad));
|
||||||
if (!switchpad->forwarded && switchpad->data) {
|
|
||||||
gst_data_unref (switchpad->data);
|
|
||||||
switchpad->data = NULL;
|
|
||||||
}
|
|
||||||
switchpad->data = data;
|
|
||||||
switchpad->forwarded = FALSE;
|
|
||||||
}
|
}
|
||||||
pads = g_list_next (pads);
|
pads = g_list_next (pads);
|
||||||
}
|
}
|
||||||
|
@ -298,6 +340,7 @@ gst_switch_class_init (GstSwitchClass *klass)
|
||||||
gobject_class->get_property = gst_switch_get_property;
|
gobject_class->get_property = gst_switch_get_property;
|
||||||
|
|
||||||
gstelement_class->request_new_pad = gst_switch_request_new_pad;
|
gstelement_class->request_new_pad = gst_switch_request_new_pad;
|
||||||
|
gstelement_class->release_pad = gst_switch_release_pad;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================= */
|
/* ============================================================= */
|
||||||
|
|
Loading…
Reference in a new issue