mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
gst-libs/gst/play/gstplay.c: Reworked the pipeline from scratch. Visualization is back and switch went out as i reali...
Original commit message from CVS: 2004-01-23 Julien MOUTTE <julien@moutte.net> * gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup), (gst_play_set_location), (gst_play_seek_to_time), (gst_play_set_audio_sink), (gst_play_set_visualization), (gst_play_connect_visualization), (gst_play_get_sink_element): Reworked the pipeline from scratch. Visualization is back and switch went out as i realized it was not possible to use the way i wanted. * sys/ximage/ximagesink.c: (gst_ximagesink_imagepool_clear), (gst_ximagesink_change_state), (gst_ximagesink_dispose): Move xcontext clearing in state change from READY to NULL. So that one can clean the X ressources keeping the element. * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get), (gst_xvimagesink_imagepool_clear), (gst_xvimagesink_change_state), (gst_xvimagesink_colorbalance_set_value), (gst_xvimagesink_colorbalance_get_value), (gst_xvimagesink_set_property), (gst_xvimagesink_dispose), (gst_xvimagesink_init): Same xcontext cleaning than ximagesink in state change from READY to NULL and fixed some stupid bugs in colorbalance get/set values. Also added the following feature : when nobody tries to set some values to the colorbalance levels before the xcontext is grabbed, then when creating channels list from Xv attributes we set the internal values to the Xv defaults. This way we handle buggy Xv drivers that set default hue values far from the middle of the range (Thanks to Jon Trowbridge for pointing that issue). * sys/xvimage/xvimagesink.h: Adding a cb_changed boolean to know if colorbalance levels have been set before xcontext is grabbed.
This commit is contained in:
parent
5ea7e1a94a
commit
15289fa2dd
6 changed files with 635 additions and 470 deletions
28
ChangeLog
28
ChangeLog
|
@ -1,3 +1,31 @@
|
|||
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):
|
||||
|
|
|
@ -59,41 +59,86 @@ static GstPipelineClass *parent_class = NULL;
|
|||
static gboolean
|
||||
gst_play_pipeline_setup (GstPlay *play)
|
||||
{
|
||||
GstElement *work_thread, *video_thread, *source;
|
||||
GstElement *autoplugger, *switch_colorspace, *video_switch, *video_queue;
|
||||
GstElement *video_balance, *video_colorspace, *video_scaler, *video_sink;
|
||||
GstElement *audio_thread, *audio_queue, *audio_volume, *audio_sink;
|
||||
GstElement *audio_tee, *vis_thread, *vis_queue, *vis_element, *end_vis_queue;
|
||||
GstPad *audio_tee_pad1, *audio_tee_pad2, *vis_thread_pad, *audio_sink_pad;
|
||||
/* Threads */
|
||||
GstElement *work_thread, *audio_thread, *video_thread;
|
||||
/* Main Thread elements */
|
||||
GstElement *source, *autoplugger, *audioconvert, *volume, *tee, *vis_element;
|
||||
/* Video Thread elements */
|
||||
GstElement *video_queue, *video_cs, *video_balance, *balance_cs;
|
||||
GstElement *video_scaler, *video_sink;
|
||||
/* Audio Thread elements */
|
||||
GstElement *audio_queue, *audio_sink;
|
||||
/* Some useful pads */
|
||||
GstPad *tee_pad1, *tee_pad2;
|
||||
|
||||
g_return_val_if_fail (play != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
||||
|
||||
/* Creating main thread and its elements
|
||||
{ fakesrc ! spider ! audioconvert ! volume ! tee } */
|
||||
{
|
||||
work_thread = gst_element_factory_make ("thread", "work_thread");
|
||||
if (!GST_IS_ELEMENT (work_thread))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "work_thread", work_thread);
|
||||
gst_bin_add (GST_BIN (play), work_thread);
|
||||
|
||||
/* Placeholder for the source and autoplugger { fakesrc ! spider } */
|
||||
|
||||
/* Placeholder for datasrc */
|
||||
source = gst_element_factory_make ("fakesrc", "source");
|
||||
if (!GST_IS_ELEMENT (source))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "source", source);
|
||||
|
||||
/* Autoplugger */
|
||||
autoplugger = gst_element_factory_make ("spider", "autoplugger");
|
||||
if (!GST_IS_ELEMENT (autoplugger))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "autoplugger", autoplugger);
|
||||
|
||||
gst_bin_add_many (GST_BIN (work_thread), source, autoplugger, NULL);
|
||||
gst_element_link (source, autoplugger);
|
||||
/* Make sure we convert audio to the needed format */
|
||||
audioconvert = gst_element_factory_make ("audioconvert",
|
||||
"audioconvert");
|
||||
if (!GST_IS_ELEMENT (audioconvert))
|
||||
return FALSE;
|
||||
|
||||
/* Creating our video output bin
|
||||
{ queue ! videobalance ! colorspace ! videoscale ! fakesink } */
|
||||
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;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "audioconvert", volume);
|
||||
|
||||
/* Duplicate audio signal to audio sink and visualization thread */
|
||||
tee = gst_element_factory_make ("tee", "tee");
|
||||
if (!GST_IS_ELEMENT (tee))
|
||||
return FALSE;
|
||||
|
||||
tee_pad1 = gst_element_get_request_pad (tee, "src%d");
|
||||
tee_pad2 = gst_element_get_request_pad (tee, "src%d");
|
||||
g_hash_table_insert (play->priv->elements, "tee_pad1", tee_pad1);
|
||||
g_hash_table_insert (play->priv->elements, "tee_pad2", tee_pad2);
|
||||
g_hash_table_insert (play->priv->elements, "tee", tee);
|
||||
|
||||
gst_bin_add_many (GST_BIN (work_thread), source, autoplugger,/* audioconvert,*/
|
||||
volume, tee, NULL);
|
||||
gst_element_link_many (source, autoplugger,/* audioconvert,*/ volume, tee, NULL);
|
||||
|
||||
/* Visualization element placeholder (note: it s not added to the pipeline
|
||||
yet) */
|
||||
vis_element = gst_element_factory_make ("identity", "vis_element");
|
||||
if (!GST_IS_ELEMENT (vis_element))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "vis_element", vis_element);
|
||||
|
||||
}
|
||||
/* Creating our video output bin */
|
||||
{
|
||||
video_thread = gst_element_factory_make ("thread", "video_thread");
|
||||
if (!GST_IS_ELEMENT (video_thread))
|
||||
return FALSE;
|
||||
|
@ -101,13 +146,24 @@ gst_play_pipeline_setup (GstPlay *play)
|
|||
g_hash_table_insert (play->priv->elements, "video_thread", video_thread);
|
||||
gst_bin_add (GST_BIN (work_thread), video_thread);
|
||||
|
||||
/* Buffer queue for our video thread */
|
||||
/* Buffer queue for video data */
|
||||
video_queue = gst_element_factory_make ("queue", "video_queue");
|
||||
if (!GST_IS_ELEMENT (video_queue))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "video_queue", video_queue);
|
||||
|
||||
/* Colorspace conversion */
|
||||
video_cs = gst_element_factory_make ("ffcolorspace", "video_cs");
|
||||
if (!GST_IS_ELEMENT (video_cs)) {
|
||||
video_cs = gst_element_factory_make ("colorspace", "video_cs");
|
||||
if (!GST_IS_ELEMENT (video_cs))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "video_cs", video_cs);
|
||||
|
||||
/* Software colorbalance */
|
||||
video_balance = gst_element_factory_make ("videobalance",
|
||||
"video_balance");
|
||||
if (!GST_IS_ELEMENT (video_balance))
|
||||
|
@ -117,17 +173,14 @@ gst_play_pipeline_setup (GstPlay *play)
|
|||
video_balance);
|
||||
|
||||
/* Colorspace conversion */
|
||||
video_colorspace = gst_element_factory_make ("ffcolorspace",
|
||||
"video_colorspace");
|
||||
if (!GST_IS_ELEMENT (video_colorspace)) {
|
||||
video_colorspace = gst_element_factory_make ("colorspace",
|
||||
"video_colorspace");
|
||||
if (!GST_IS_ELEMENT (video_colorspace))
|
||||
balance_cs = gst_element_factory_make ("ffcolorspace", "balance_cs");
|
||||
if (!GST_IS_ELEMENT (balance_cs)) {
|
||||
balance_cs = gst_element_factory_make ("colorspace", "balance_cs");
|
||||
if (!GST_IS_ELEMENT (balance_cs))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "video_colorspace",
|
||||
video_colorspace);
|
||||
g_hash_table_insert (play->priv->elements, "balance_cs", balance_cs);
|
||||
|
||||
/* Software scaling of video stream */
|
||||
video_scaler = gst_element_factory_make ("videoscale", "video_scaler");
|
||||
|
@ -143,46 +196,18 @@ gst_play_pipeline_setup (GstPlay *play)
|
|||
|
||||
g_hash_table_insert (play->priv->elements, "video_sink", video_sink);
|
||||
|
||||
/* Linking, Adding, Ghosting */
|
||||
gst_element_link_many (video_queue, video_balance, video_colorspace,
|
||||
gst_bin_add_many (GST_BIN (video_thread), video_queue, video_cs,
|
||||
video_balance, balance_cs, video_scaler, video_sink, NULL);
|
||||
gst_element_link_many (video_queue, video_cs, video_balance, balance_cs,
|
||||
video_scaler, video_sink, NULL);
|
||||
gst_bin_add_many (GST_BIN (video_thread), video_queue, video_balance,
|
||||
video_colorspace, video_scaler, video_sink, NULL);
|
||||
gst_element_add_ghost_pad (video_thread,
|
||||
gst_element_get_pad (video_queue, "sink"),
|
||||
"sink");
|
||||
|
||||
/* autoplugger ! ffcolorspace ! switch */
|
||||
switch_colorspace = NULL;
|
||||
switch_colorspace = gst_element_factory_make ("ffcolorspace",
|
||||
"switch_colorspace");
|
||||
if (!GST_IS_ELEMENT (switch_colorspace)) {
|
||||
switch_colorspace = gst_element_factory_make ("colorspace",
|
||||
"switch_colorspace");
|
||||
if (!GST_IS_ELEMENT (switch_colorspace))
|
||||
return FALSE;
|
||||
gst_element_link (autoplugger, video_thread);
|
||||
}
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "switch_colorspace",
|
||||
switch_colorspace);
|
||||
|
||||
video_switch = gst_element_factory_make ("switch",
|
||||
"video_switch");
|
||||
if (!GST_IS_ELEMENT (video_switch))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "video_switch", video_switch);
|
||||
|
||||
gst_bin_add_many (GST_BIN (work_thread), switch_colorspace,
|
||||
/*video_switch,*/ NULL);
|
||||
|
||||
/* Connecting autoplugger to video switch and video switch to video output */
|
||||
gst_element_link_many (autoplugger, switch_colorspace,
|
||||
/*video_switch,*/ video_thread, NULL);
|
||||
/* gst_element_link (autoplugger, video_thread); */
|
||||
|
||||
/* Creating our audio output bin
|
||||
{ queue ! volume ! tee ! { queue ! goom } ! fakesink } */
|
||||
{ queue ! fakesink } */
|
||||
{
|
||||
audio_thread = gst_element_factory_make ("thread", "audio_thread");
|
||||
if (!GST_IS_ELEMENT (audio_thread))
|
||||
return FALSE;
|
||||
|
@ -197,85 +222,20 @@ gst_play_pipeline_setup (GstPlay *play)
|
|||
|
||||
g_hash_table_insert (play->priv->elements, "audio_queue", audio_queue);
|
||||
|
||||
/* Volume control */
|
||||
audio_volume = gst_element_factory_make ("volume", "audio_volume");
|
||||
if (!GST_IS_ELEMENT (audio_volume))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "audio_volume", audio_volume);
|
||||
|
||||
/* Duplicate audio signal to sink and visualization thread */
|
||||
audio_tee = gst_element_factory_make ("tee", "audio_tee");
|
||||
if (!GST_IS_ELEMENT (audio_tee))
|
||||
return FALSE;
|
||||
|
||||
audio_tee_pad1 = gst_element_get_request_pad (audio_tee, "src%d");
|
||||
audio_tee_pad2 = gst_element_get_request_pad (audio_tee, "src%d");
|
||||
g_hash_table_insert (play->priv->elements, "audio_tee_pad1",
|
||||
audio_tee_pad1);
|
||||
g_hash_table_insert (play->priv->elements, "audio_tee_pad2",
|
||||
audio_tee_pad2);
|
||||
g_hash_table_insert (play->priv->elements, "audio_tee", audio_tee);
|
||||
|
||||
/* Placeholder for future audio sink bin */
|
||||
audio_sink = gst_element_factory_make ("fakesink", "audio_sink");
|
||||
if (!GST_IS_ELEMENT (audio_sink))
|
||||
return FALSE;
|
||||
|
||||
audio_sink_pad = gst_element_get_pad (audio_sink, "sink");
|
||||
g_hash_table_insert (play->priv->elements, "audio_sink_pad",
|
||||
audio_sink_pad);
|
||||
g_hash_table_insert (play->priv->elements, "audio_sink", audio_sink);
|
||||
|
||||
/* Visualization thread */
|
||||
vis_thread = gst_element_factory_make ("thread", "vis_thread");
|
||||
if (!GST_IS_ELEMENT (vis_thread))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "vis_thread", vis_thread);
|
||||
|
||||
/* Buffer queue for our visualization thread */
|
||||
vis_queue = gst_element_factory_make ("queue", "vis_queue");
|
||||
if (!GST_IS_ELEMENT (vis_queue))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "vis_queue", vis_queue);
|
||||
|
||||
vis_element = gst_element_factory_make ("identity", "vis_element");
|
||||
if (!GST_IS_ELEMENT (vis_element))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "vis_element", vis_element);
|
||||
|
||||
end_vis_queue = gst_element_factory_make ("queue", "end_vis_queue");
|
||||
if (!GST_IS_ELEMENT (end_vis_queue))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "end_vis_queue",
|
||||
end_vis_queue);
|
||||
|
||||
/* Adding, Linking, Ghosting in visualization */
|
||||
gst_bin_add_many (GST_BIN (vis_thread), vis_queue, vis_element,
|
||||
end_vis_queue, NULL);
|
||||
gst_element_link_many (vis_queue, vis_element, end_vis_queue, NULL);
|
||||
vis_thread_pad = gst_element_add_ghost_pad (vis_thread,
|
||||
gst_element_get_pad (vis_queue, "sink"),
|
||||
"sink");
|
||||
g_hash_table_insert (play->priv->elements, "vis_thread_pad",
|
||||
vis_thread_pad);
|
||||
|
||||
|
||||
/* Linking, Adding, Ghosting in audio */
|
||||
gst_element_link_many (audio_queue, audio_volume, audio_tee, NULL);
|
||||
gst_pad_link (audio_tee_pad1, audio_sink_pad);
|
||||
gst_bin_add_many (GST_BIN (audio_thread), audio_queue, audio_volume,
|
||||
audio_tee, vis_thread, audio_sink, NULL);
|
||||
gst_bin_add_many (GST_BIN (audio_thread), audio_queue, audio_sink, NULL);
|
||||
gst_element_link (audio_queue, audio_sink);
|
||||
gst_element_add_ghost_pad (audio_thread,
|
||||
gst_element_get_pad (audio_queue, "sink"),
|
||||
"sink");
|
||||
|
||||
/* Connecting audio output to autoplugger */
|
||||
gst_element_link (autoplugger, audio_thread);
|
||||
gst_pad_link (tee_pad2, gst_element_get_pad (audio_queue, "sink"));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -505,7 +465,7 @@ gboolean
|
|||
gst_play_set_location (GstPlay *play, const char *location)
|
||||
{
|
||||
GstElement *work_thread, *source, *autoplugger;
|
||||
GstElement *switch_colorspace, *audio_thread;
|
||||
GstElement *audioconvert, *video_thread;
|
||||
|
||||
g_return_val_if_fail (play != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
||||
|
@ -521,25 +481,24 @@ gst_play_set_location (GstPlay *play, const char *location)
|
|||
work_thread = g_hash_table_lookup (play->priv->elements, "work_thread");
|
||||
if (!GST_IS_ELEMENT (work_thread))
|
||||
return FALSE;
|
||||
switch_colorspace = g_hash_table_lookup (play->priv->elements,
|
||||
"switch_colorspace");
|
||||
if (!GST_IS_ELEMENT (switch_colorspace))
|
||||
return FALSE;
|
||||
audio_thread = g_hash_table_lookup (play->priv->elements, "audio_thread");
|
||||
if (!GST_IS_ELEMENT (audio_thread))
|
||||
return FALSE;
|
||||
source = g_hash_table_lookup (play->priv->elements, "source");
|
||||
if (!GST_IS_ELEMENT (source))
|
||||
return FALSE;
|
||||
autoplugger = g_hash_table_lookup (play->priv->elements, "autoplugger");
|
||||
if (!GST_IS_ELEMENT (autoplugger))
|
||||
return FALSE;
|
||||
audioconvert = g_hash_table_lookup (play->priv->elements, "audioconvert");
|
||||
if (!GST_IS_ELEMENT (audioconvert))
|
||||
return FALSE;
|
||||
video_thread = g_hash_table_lookup (play->priv->elements, "video_thread");
|
||||
if (!GST_IS_ELEMENT (video_thread))
|
||||
return FALSE;
|
||||
|
||||
/* Spider can autoplugg only once. We remove the actual one and put a new
|
||||
autoplugger */
|
||||
gst_element_unlink (source, autoplugger);
|
||||
gst_element_unlink (autoplugger, switch_colorspace);
|
||||
gst_element_unlink (autoplugger, audio_thread);
|
||||
gst_element_unlink (autoplugger, video_thread);
|
||||
gst_element_unlink (autoplugger, audioconvert);
|
||||
gst_bin_remove (GST_BIN (work_thread), autoplugger);
|
||||
|
||||
autoplugger = gst_element_factory_make ("spider", "autoplugger");
|
||||
|
@ -548,8 +507,8 @@ gst_play_set_location (GstPlay *play, const char *location)
|
|||
|
||||
gst_bin_add (GST_BIN (work_thread), autoplugger);
|
||||
gst_element_link (source, autoplugger);
|
||||
gst_element_link (autoplugger, switch_colorspace);
|
||||
gst_element_link (autoplugger, audio_thread);
|
||||
gst_element_link (autoplugger, video_thread);
|
||||
gst_element_link (autoplugger, audioconvert);
|
||||
|
||||
g_hash_table_replace (play->priv->elements, "autoplugger", autoplugger);
|
||||
|
||||
|
@ -618,8 +577,9 @@ gst_play_seek_to_time (GstPlay * play, gint64 time_nanos)
|
|||
}
|
||||
|
||||
if (s) {
|
||||
GstClock *clock = gst_bin_get_clock (GST_BIN (play));
|
||||
play->priv->time_nanos = gst_clock_get_time (clock);
|
||||
GstClockTime time;
|
||||
time = gst_element_get_time (audio_sink_element);
|
||||
play->priv->time_nanos = GST_CLOCK_TIME_IS_VALID (time) ? time : 0;
|
||||
g_signal_emit (G_OBJECT (play), gst_play_signals[TIME_TICK],
|
||||
0,play->priv->time_nanos);
|
||||
}
|
||||
|
@ -745,8 +705,7 @@ gst_play_set_video_sink (GstPlay *play, GstElement *video_sink)
|
|||
gboolean
|
||||
gst_play_set_audio_sink (GstPlay *play, GstElement *audio_sink)
|
||||
{
|
||||
GstElement *old_audio_sink, *audio_thread, *audio_sink_element;
|
||||
GstPad *audio_tee_pad1, *audio_sink_pad, *old_audio_sink_pad;
|
||||
GstElement *old_audio_sink, *audio_thread, *audio_queue, *audio_sink_element;
|
||||
|
||||
g_return_val_if_fail (play != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
||||
|
@ -761,31 +720,21 @@ gst_play_set_audio_sink (GstPlay *play, GstElement *audio_sink)
|
|||
old_audio_sink = g_hash_table_lookup (play->priv->elements, "audio_sink");
|
||||
if (!GST_IS_ELEMENT (old_audio_sink))
|
||||
return FALSE;
|
||||
old_audio_sink_pad = g_hash_table_lookup (play->priv->elements,
|
||||
"audio_sink_pad");
|
||||
if (!GST_IS_PAD (old_audio_sink_pad))
|
||||
return FALSE;
|
||||
audio_thread = g_hash_table_lookup (play->priv->elements, "audio_thread");
|
||||
if (!GST_IS_ELEMENT (audio_thread))
|
||||
return FALSE;
|
||||
audio_tee_pad1 = g_hash_table_lookup (play->priv->elements,
|
||||
"audio_tee_pad1");
|
||||
if (!GST_IS_PAD (audio_tee_pad1))
|
||||
return FALSE;
|
||||
audio_sink_pad = gst_element_get_pad (audio_sink, "sink");
|
||||
if (!GST_IS_PAD (audio_sink_pad))
|
||||
audio_queue = g_hash_table_lookup (play->priv->elements, "audio_queue");
|
||||
if (!GST_IS_ELEMENT (audio_queue))
|
||||
return FALSE;
|
||||
|
||||
/* Unlinking old audiosink, removing it from pipeline, putting the new one
|
||||
and linking it */
|
||||
gst_pad_unlink (audio_tee_pad1, old_audio_sink_pad);
|
||||
gst_element_unlink (audio_queue, old_audio_sink);
|
||||
gst_bin_remove (GST_BIN (audio_thread), old_audio_sink);
|
||||
gst_bin_add (GST_BIN (audio_thread), audio_sink);
|
||||
gst_pad_link (audio_tee_pad1, audio_sink_pad);
|
||||
gst_element_link (audio_queue, audio_sink);
|
||||
|
||||
g_hash_table_replace (play->priv->elements, "audio_sink", audio_sink);
|
||||
g_hash_table_replace (play->priv->elements, "audio_sink_pad",
|
||||
audio_sink_pad);
|
||||
|
||||
audio_sink_element = gst_play_get_sink_element (play, audio_sink,
|
||||
GST_PLAY_SINK_TYPE_AUDIO);
|
||||
|
@ -811,7 +760,8 @@ gst_play_set_audio_sink (GstPlay *play, GstElement *audio_sink)
|
|||
gboolean
|
||||
gst_play_set_visualization (GstPlay *play, GstElement *vis_element)
|
||||
{
|
||||
GstElement *old_vis_element, *vis_thread, *vis_queue, *end_vis_queue;
|
||||
GstElement *work_thread, *old_vis_element, *video_thread;
|
||||
GstPad *tee_pad1;
|
||||
gboolean was_playing = FALSE;
|
||||
|
||||
g_return_val_if_fail (play != NULL, FALSE);
|
||||
|
@ -819,34 +769,50 @@ gst_play_set_visualization (GstPlay *play, GstElement *vis_element)
|
|||
g_return_val_if_fail (vis_element != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_IS_ELEMENT (vis_element), FALSE);
|
||||
|
||||
/* We bring back the pipeline to READY */
|
||||
if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
|
||||
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
|
||||
was_playing = TRUE;
|
||||
}
|
||||
|
||||
/* Getting needed objects */
|
||||
vis_thread = g_hash_table_lookup (play->priv->elements, "vis_thread");
|
||||
if (!GST_IS_ELEMENT (vis_thread))
|
||||
work_thread = g_hash_table_lookup (play->priv->elements, "work_thread");
|
||||
if (!GST_IS_ELEMENT (work_thread))
|
||||
return FALSE;
|
||||
old_vis_element = g_hash_table_lookup (play->priv->elements,
|
||||
"vis_element");
|
||||
if (!GST_IS_ELEMENT (old_vis_element))
|
||||
return FALSE;
|
||||
vis_queue = g_hash_table_lookup (play->priv->elements, "vis_queue");
|
||||
if (!GST_IS_ELEMENT (vis_queue))
|
||||
tee_pad1 = g_hash_table_lookup (play->priv->elements, "tee_pad1");
|
||||
if (!GST_IS_PAD (tee_pad1))
|
||||
return FALSE;
|
||||
end_vis_queue = g_hash_table_lookup (play->priv->elements, "end_vis_queue");
|
||||
if (!GST_IS_ELEMENT (end_vis_queue))
|
||||
video_thread = g_hash_table_lookup (play->priv->elements, "video_thread");
|
||||
if (!GST_IS_ELEMENT (video_thread))
|
||||
return FALSE;
|
||||
|
||||
/* Let's check if the current vis element has a managing bin. If yes that
|
||||
means the element is inside the pipeline and need to be unlinked and
|
||||
removed. We also need to pause the pipeline if it is currently playing. */
|
||||
if (gst_element_get_managing_bin (old_vis_element)) {
|
||||
GstPad *vis_element_pad;
|
||||
|
||||
/* We bring back the pipeline to PAUSED */
|
||||
if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
|
||||
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
|
||||
was_playing = TRUE;
|
||||
}
|
||||
|
||||
/* Unlinking, removing the old element then adding and linking the new one */
|
||||
gst_element_unlink (vis_queue, old_vis_element);
|
||||
gst_element_unlink (old_vis_element, end_vis_queue);
|
||||
gst_bin_remove (GST_BIN (vis_thread), old_vis_element);
|
||||
gst_bin_add (GST_BIN (vis_thread), vis_element);
|
||||
gst_element_link (vis_queue, vis_element);
|
||||
gst_element_link (vis_element, end_vis_queue);
|
||||
/* Unlinking, removing the old element then adding and linking the new one */
|
||||
vis_element_pad = gst_element_get_pad (old_vis_element, "sink");
|
||||
if (GST_IS_PAD (vis_element_pad))
|
||||
gst_pad_unlink (tee_pad1, vis_element_pad);
|
||||
gst_element_unlink (old_vis_element, video_thread);
|
||||
gst_bin_remove (GST_BIN (work_thread), old_vis_element);
|
||||
gst_bin_add (GST_BIN (work_thread), vis_element);
|
||||
vis_element_pad = gst_element_get_pad (vis_element, "sink");
|
||||
if (GST_IS_PAD (vis_element_pad))
|
||||
gst_pad_link (tee_pad1, vis_element_pad);
|
||||
gst_element_link (vis_element, video_thread);
|
||||
}
|
||||
else {
|
||||
gst_object_unref (GST_OBJECT (old_vis_element));
|
||||
}
|
||||
|
||||
g_hash_table_replace (play->priv->elements, "vis_element", vis_element);
|
||||
|
||||
if (was_playing)
|
||||
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PLAYING);
|
||||
|
@ -867,39 +833,121 @@ gst_play_set_visualization (GstPlay *play, GstElement *vis_element)
|
|||
gboolean
|
||||
gst_play_connect_visualization (GstPlay * play, gboolean connect)
|
||||
{
|
||||
GstPad *audio_tee_pad2, *vis_thread_pad;
|
||||
gboolean connected = FALSE, was_playing = FALSE;
|
||||
GstElement *work_thread, *vis_element, *autoplugger, *video_thread;
|
||||
GstElement *audioconvert, *source;
|
||||
GstPad *tee_pad1, *vis_element_pad;
|
||||
|
||||
g_return_val_if_fail (play != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
||||
|
||||
vis_thread_pad = g_hash_table_lookup (play->priv->elements,
|
||||
"vis_thread_pad");
|
||||
if (!GST_IS_PAD (vis_thread_pad))
|
||||
/* Getting needed objects */
|
||||
work_thread = g_hash_table_lookup (play->priv->elements, "work_thread");
|
||||
if (!GST_IS_ELEMENT (work_thread))
|
||||
return FALSE;
|
||||
audio_tee_pad2 = g_hash_table_lookup (play->priv->elements,
|
||||
"audio_tee_pad2");
|
||||
if (!GST_IS_PAD (audio_tee_pad2))
|
||||
vis_element = g_hash_table_lookup (play->priv->elements, "vis_element");
|
||||
if (!GST_IS_ELEMENT (vis_element))
|
||||
return FALSE;
|
||||
tee_pad1 = g_hash_table_lookup (play->priv->elements, "tee_pad1");
|
||||
if (!GST_IS_PAD (tee_pad1))
|
||||
return FALSE;
|
||||
video_thread = g_hash_table_lookup (play->priv->elements, "video_thread");
|
||||
if (!GST_IS_ELEMENT (video_thread))
|
||||
return FALSE;
|
||||
autoplugger = g_hash_table_lookup (play->priv->elements, "autoplugger");
|
||||
if (!GST_IS_ELEMENT (autoplugger))
|
||||
return FALSE;
|
||||
source = g_hash_table_lookup (play->priv->elements, "source");
|
||||
if (!GST_IS_ELEMENT (source))
|
||||
return FALSE;
|
||||
audioconvert = g_hash_table_lookup (play->priv->elements, "audioconvert");
|
||||
if (!GST_IS_ELEMENT (audioconvert))
|
||||
return FALSE;
|
||||
|
||||
if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
|
||||
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
|
||||
was_playing = TRUE;
|
||||
}
|
||||
|
||||
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 (was_playing)
|
||||
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PLAYING);
|
||||
/* 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);
|
||||
|
||||
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 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;
|
||||
|
||||
/* Adding and connecting a new autoplugger */
|
||||
gst_bin_add (GST_BIN (work_thread), autoplugger);
|
||||
gst_element_link (source, autoplugger);
|
||||
gst_element_link (autoplugger, audioconvert);
|
||||
|
||||
g_hash_table_replace (play->priv->elements, "autoplugger", autoplugger);
|
||||
|
||||
/* Otherwise we add the element to the bin and link it to video_thread */
|
||||
gst_bin_add (GST_BIN (work_thread), vis_element);
|
||||
vis_element_pad = gst_element_get_pad (vis_element, "sink");
|
||||
if (GST_IS_PAD (vis_element_pad))
|
||||
gst_pad_link (tee_pad1, vis_element_pad);
|
||||
|
||||
filtered_caps = gst_caps_from_string ("video/x-raw-rgb, "
|
||||
"framerate = 30.0; "
|
||||
"video/x-raw-yuv, "
|
||||
"framerate = 30.0");
|
||||
|
||||
if (!gst_element_link_filtered (vis_element, video_thread, filtered_caps))
|
||||
g_message ("failed linking filtered vis with video thread");
|
||||
|
||||
gst_caps_free (filtered_caps);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -916,7 +964,7 @@ gst_play_connect_visualization (GstPlay * play, gboolean connect)
|
|||
*/
|
||||
GstElement *
|
||||
gst_play_get_sink_element (GstPlay *play,
|
||||
GstElement *element, GstPlaySinkType sink_type)
|
||||
GstElement *element, GstPlaySinkType sink_type)
|
||||
{
|
||||
GList *elements = NULL;
|
||||
const GList *pads = NULL;
|
||||
|
|
|
@ -59,41 +59,86 @@ static GstPipelineClass *parent_class = NULL;
|
|||
static gboolean
|
||||
gst_play_pipeline_setup (GstPlay *play)
|
||||
{
|
||||
GstElement *work_thread, *video_thread, *source;
|
||||
GstElement *autoplugger, *switch_colorspace, *video_switch, *video_queue;
|
||||
GstElement *video_balance, *video_colorspace, *video_scaler, *video_sink;
|
||||
GstElement *audio_thread, *audio_queue, *audio_volume, *audio_sink;
|
||||
GstElement *audio_tee, *vis_thread, *vis_queue, *vis_element, *end_vis_queue;
|
||||
GstPad *audio_tee_pad1, *audio_tee_pad2, *vis_thread_pad, *audio_sink_pad;
|
||||
/* Threads */
|
||||
GstElement *work_thread, *audio_thread, *video_thread;
|
||||
/* Main Thread elements */
|
||||
GstElement *source, *autoplugger, *audioconvert, *volume, *tee, *vis_element;
|
||||
/* Video Thread elements */
|
||||
GstElement *video_queue, *video_cs, *video_balance, *balance_cs;
|
||||
GstElement *video_scaler, *video_sink;
|
||||
/* Audio Thread elements */
|
||||
GstElement *audio_queue, *audio_sink;
|
||||
/* Some useful pads */
|
||||
GstPad *tee_pad1, *tee_pad2;
|
||||
|
||||
g_return_val_if_fail (play != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
||||
|
||||
/* Creating main thread and its elements
|
||||
{ fakesrc ! spider ! audioconvert ! volume ! tee } */
|
||||
{
|
||||
work_thread = gst_element_factory_make ("thread", "work_thread");
|
||||
if (!GST_IS_ELEMENT (work_thread))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "work_thread", work_thread);
|
||||
gst_bin_add (GST_BIN (play), work_thread);
|
||||
|
||||
/* Placeholder for the source and autoplugger { fakesrc ! spider } */
|
||||
|
||||
/* Placeholder for datasrc */
|
||||
source = gst_element_factory_make ("fakesrc", "source");
|
||||
if (!GST_IS_ELEMENT (source))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "source", source);
|
||||
|
||||
/* Autoplugger */
|
||||
autoplugger = gst_element_factory_make ("spider", "autoplugger");
|
||||
if (!GST_IS_ELEMENT (autoplugger))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "autoplugger", autoplugger);
|
||||
|
||||
gst_bin_add_many (GST_BIN (work_thread), source, autoplugger, NULL);
|
||||
gst_element_link (source, autoplugger);
|
||||
/* Make sure we convert audio to the needed format */
|
||||
audioconvert = gst_element_factory_make ("audioconvert",
|
||||
"audioconvert");
|
||||
if (!GST_IS_ELEMENT (audioconvert))
|
||||
return FALSE;
|
||||
|
||||
/* Creating our video output bin
|
||||
{ queue ! videobalance ! colorspace ! videoscale ! fakesink } */
|
||||
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;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "audioconvert", volume);
|
||||
|
||||
/* Duplicate audio signal to audio sink and visualization thread */
|
||||
tee = gst_element_factory_make ("tee", "tee");
|
||||
if (!GST_IS_ELEMENT (tee))
|
||||
return FALSE;
|
||||
|
||||
tee_pad1 = gst_element_get_request_pad (tee, "src%d");
|
||||
tee_pad2 = gst_element_get_request_pad (tee, "src%d");
|
||||
g_hash_table_insert (play->priv->elements, "tee_pad1", tee_pad1);
|
||||
g_hash_table_insert (play->priv->elements, "tee_pad2", tee_pad2);
|
||||
g_hash_table_insert (play->priv->elements, "tee", tee);
|
||||
|
||||
gst_bin_add_many (GST_BIN (work_thread), source, autoplugger,/* audioconvert,*/
|
||||
volume, tee, NULL);
|
||||
gst_element_link_many (source, autoplugger,/* audioconvert,*/ volume, tee, NULL);
|
||||
|
||||
/* Visualization element placeholder (note: it s not added to the pipeline
|
||||
yet) */
|
||||
vis_element = gst_element_factory_make ("identity", "vis_element");
|
||||
if (!GST_IS_ELEMENT (vis_element))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "vis_element", vis_element);
|
||||
|
||||
}
|
||||
/* Creating our video output bin */
|
||||
{
|
||||
video_thread = gst_element_factory_make ("thread", "video_thread");
|
||||
if (!GST_IS_ELEMENT (video_thread))
|
||||
return FALSE;
|
||||
|
@ -101,13 +146,24 @@ gst_play_pipeline_setup (GstPlay *play)
|
|||
g_hash_table_insert (play->priv->elements, "video_thread", video_thread);
|
||||
gst_bin_add (GST_BIN (work_thread), video_thread);
|
||||
|
||||
/* Buffer queue for our video thread */
|
||||
/* Buffer queue for video data */
|
||||
video_queue = gst_element_factory_make ("queue", "video_queue");
|
||||
if (!GST_IS_ELEMENT (video_queue))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "video_queue", video_queue);
|
||||
|
||||
/* Colorspace conversion */
|
||||
video_cs = gst_element_factory_make ("ffcolorspace", "video_cs");
|
||||
if (!GST_IS_ELEMENT (video_cs)) {
|
||||
video_cs = gst_element_factory_make ("colorspace", "video_cs");
|
||||
if (!GST_IS_ELEMENT (video_cs))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "video_cs", video_cs);
|
||||
|
||||
/* Software colorbalance */
|
||||
video_balance = gst_element_factory_make ("videobalance",
|
||||
"video_balance");
|
||||
if (!GST_IS_ELEMENT (video_balance))
|
||||
|
@ -117,17 +173,14 @@ gst_play_pipeline_setup (GstPlay *play)
|
|||
video_balance);
|
||||
|
||||
/* Colorspace conversion */
|
||||
video_colorspace = gst_element_factory_make ("ffcolorspace",
|
||||
"video_colorspace");
|
||||
if (!GST_IS_ELEMENT (video_colorspace)) {
|
||||
video_colorspace = gst_element_factory_make ("colorspace",
|
||||
"video_colorspace");
|
||||
if (!GST_IS_ELEMENT (video_colorspace))
|
||||
balance_cs = gst_element_factory_make ("ffcolorspace", "balance_cs");
|
||||
if (!GST_IS_ELEMENT (balance_cs)) {
|
||||
balance_cs = gst_element_factory_make ("colorspace", "balance_cs");
|
||||
if (!GST_IS_ELEMENT (balance_cs))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "video_colorspace",
|
||||
video_colorspace);
|
||||
g_hash_table_insert (play->priv->elements, "balance_cs", balance_cs);
|
||||
|
||||
/* Software scaling of video stream */
|
||||
video_scaler = gst_element_factory_make ("videoscale", "video_scaler");
|
||||
|
@ -143,46 +196,18 @@ gst_play_pipeline_setup (GstPlay *play)
|
|||
|
||||
g_hash_table_insert (play->priv->elements, "video_sink", video_sink);
|
||||
|
||||
/* Linking, Adding, Ghosting */
|
||||
gst_element_link_many (video_queue, video_balance, video_colorspace,
|
||||
gst_bin_add_many (GST_BIN (video_thread), video_queue, video_cs,
|
||||
video_balance, balance_cs, video_scaler, video_sink, NULL);
|
||||
gst_element_link_many (video_queue, video_cs, video_balance, balance_cs,
|
||||
video_scaler, video_sink, NULL);
|
||||
gst_bin_add_many (GST_BIN (video_thread), video_queue, video_balance,
|
||||
video_colorspace, video_scaler, video_sink, NULL);
|
||||
gst_element_add_ghost_pad (video_thread,
|
||||
gst_element_get_pad (video_queue, "sink"),
|
||||
"sink");
|
||||
|
||||
/* autoplugger ! ffcolorspace ! switch */
|
||||
switch_colorspace = NULL;
|
||||
switch_colorspace = gst_element_factory_make ("ffcolorspace",
|
||||
"switch_colorspace");
|
||||
if (!GST_IS_ELEMENT (switch_colorspace)) {
|
||||
switch_colorspace = gst_element_factory_make ("colorspace",
|
||||
"switch_colorspace");
|
||||
if (!GST_IS_ELEMENT (switch_colorspace))
|
||||
return FALSE;
|
||||
gst_element_link (autoplugger, video_thread);
|
||||
}
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "switch_colorspace",
|
||||
switch_colorspace);
|
||||
|
||||
video_switch = gst_element_factory_make ("switch",
|
||||
"video_switch");
|
||||
if (!GST_IS_ELEMENT (video_switch))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "video_switch", video_switch);
|
||||
|
||||
gst_bin_add_many (GST_BIN (work_thread), switch_colorspace,
|
||||
/*video_switch,*/ NULL);
|
||||
|
||||
/* Connecting autoplugger to video switch and video switch to video output */
|
||||
gst_element_link_many (autoplugger, switch_colorspace,
|
||||
/*video_switch,*/ video_thread, NULL);
|
||||
/* gst_element_link (autoplugger, video_thread); */
|
||||
|
||||
/* Creating our audio output bin
|
||||
{ queue ! volume ! tee ! { queue ! goom } ! fakesink } */
|
||||
{ queue ! fakesink } */
|
||||
{
|
||||
audio_thread = gst_element_factory_make ("thread", "audio_thread");
|
||||
if (!GST_IS_ELEMENT (audio_thread))
|
||||
return FALSE;
|
||||
|
@ -197,85 +222,20 @@ gst_play_pipeline_setup (GstPlay *play)
|
|||
|
||||
g_hash_table_insert (play->priv->elements, "audio_queue", audio_queue);
|
||||
|
||||
/* Volume control */
|
||||
audio_volume = gst_element_factory_make ("volume", "audio_volume");
|
||||
if (!GST_IS_ELEMENT (audio_volume))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "audio_volume", audio_volume);
|
||||
|
||||
/* Duplicate audio signal to sink and visualization thread */
|
||||
audio_tee = gst_element_factory_make ("tee", "audio_tee");
|
||||
if (!GST_IS_ELEMENT (audio_tee))
|
||||
return FALSE;
|
||||
|
||||
audio_tee_pad1 = gst_element_get_request_pad (audio_tee, "src%d");
|
||||
audio_tee_pad2 = gst_element_get_request_pad (audio_tee, "src%d");
|
||||
g_hash_table_insert (play->priv->elements, "audio_tee_pad1",
|
||||
audio_tee_pad1);
|
||||
g_hash_table_insert (play->priv->elements, "audio_tee_pad2",
|
||||
audio_tee_pad2);
|
||||
g_hash_table_insert (play->priv->elements, "audio_tee", audio_tee);
|
||||
|
||||
/* Placeholder for future audio sink bin */
|
||||
audio_sink = gst_element_factory_make ("fakesink", "audio_sink");
|
||||
if (!GST_IS_ELEMENT (audio_sink))
|
||||
return FALSE;
|
||||
|
||||
audio_sink_pad = gst_element_get_pad (audio_sink, "sink");
|
||||
g_hash_table_insert (play->priv->elements, "audio_sink_pad",
|
||||
audio_sink_pad);
|
||||
g_hash_table_insert (play->priv->elements, "audio_sink", audio_sink);
|
||||
|
||||
/* Visualization thread */
|
||||
vis_thread = gst_element_factory_make ("thread", "vis_thread");
|
||||
if (!GST_IS_ELEMENT (vis_thread))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "vis_thread", vis_thread);
|
||||
|
||||
/* Buffer queue for our visualization thread */
|
||||
vis_queue = gst_element_factory_make ("queue", "vis_queue");
|
||||
if (!GST_IS_ELEMENT (vis_queue))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "vis_queue", vis_queue);
|
||||
|
||||
vis_element = gst_element_factory_make ("identity", "vis_element");
|
||||
if (!GST_IS_ELEMENT (vis_element))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "vis_element", vis_element);
|
||||
|
||||
end_vis_queue = gst_element_factory_make ("queue", "end_vis_queue");
|
||||
if (!GST_IS_ELEMENT (end_vis_queue))
|
||||
return FALSE;
|
||||
|
||||
g_hash_table_insert (play->priv->elements, "end_vis_queue",
|
||||
end_vis_queue);
|
||||
|
||||
/* Adding, Linking, Ghosting in visualization */
|
||||
gst_bin_add_many (GST_BIN (vis_thread), vis_queue, vis_element,
|
||||
end_vis_queue, NULL);
|
||||
gst_element_link_many (vis_queue, vis_element, end_vis_queue, NULL);
|
||||
vis_thread_pad = gst_element_add_ghost_pad (vis_thread,
|
||||
gst_element_get_pad (vis_queue, "sink"),
|
||||
"sink");
|
||||
g_hash_table_insert (play->priv->elements, "vis_thread_pad",
|
||||
vis_thread_pad);
|
||||
|
||||
|
||||
/* Linking, Adding, Ghosting in audio */
|
||||
gst_element_link_many (audio_queue, audio_volume, audio_tee, NULL);
|
||||
gst_pad_link (audio_tee_pad1, audio_sink_pad);
|
||||
gst_bin_add_many (GST_BIN (audio_thread), audio_queue, audio_volume,
|
||||
audio_tee, vis_thread, audio_sink, NULL);
|
||||
gst_bin_add_many (GST_BIN (audio_thread), audio_queue, audio_sink, NULL);
|
||||
gst_element_link (audio_queue, audio_sink);
|
||||
gst_element_add_ghost_pad (audio_thread,
|
||||
gst_element_get_pad (audio_queue, "sink"),
|
||||
"sink");
|
||||
|
||||
/* Connecting audio output to autoplugger */
|
||||
gst_element_link (autoplugger, audio_thread);
|
||||
gst_pad_link (tee_pad2, gst_element_get_pad (audio_queue, "sink"));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -505,7 +465,7 @@ gboolean
|
|||
gst_play_set_location (GstPlay *play, const char *location)
|
||||
{
|
||||
GstElement *work_thread, *source, *autoplugger;
|
||||
GstElement *switch_colorspace, *audio_thread;
|
||||
GstElement *audioconvert, *video_thread;
|
||||
|
||||
g_return_val_if_fail (play != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
||||
|
@ -521,25 +481,24 @@ gst_play_set_location (GstPlay *play, const char *location)
|
|||
work_thread = g_hash_table_lookup (play->priv->elements, "work_thread");
|
||||
if (!GST_IS_ELEMENT (work_thread))
|
||||
return FALSE;
|
||||
switch_colorspace = g_hash_table_lookup (play->priv->elements,
|
||||
"switch_colorspace");
|
||||
if (!GST_IS_ELEMENT (switch_colorspace))
|
||||
return FALSE;
|
||||
audio_thread = g_hash_table_lookup (play->priv->elements, "audio_thread");
|
||||
if (!GST_IS_ELEMENT (audio_thread))
|
||||
return FALSE;
|
||||
source = g_hash_table_lookup (play->priv->elements, "source");
|
||||
if (!GST_IS_ELEMENT (source))
|
||||
return FALSE;
|
||||
autoplugger = g_hash_table_lookup (play->priv->elements, "autoplugger");
|
||||
if (!GST_IS_ELEMENT (autoplugger))
|
||||
return FALSE;
|
||||
audioconvert = g_hash_table_lookup (play->priv->elements, "audioconvert");
|
||||
if (!GST_IS_ELEMENT (audioconvert))
|
||||
return FALSE;
|
||||
video_thread = g_hash_table_lookup (play->priv->elements, "video_thread");
|
||||
if (!GST_IS_ELEMENT (video_thread))
|
||||
return FALSE;
|
||||
|
||||
/* Spider can autoplugg only once. We remove the actual one and put a new
|
||||
autoplugger */
|
||||
gst_element_unlink (source, autoplugger);
|
||||
gst_element_unlink (autoplugger, switch_colorspace);
|
||||
gst_element_unlink (autoplugger, audio_thread);
|
||||
gst_element_unlink (autoplugger, video_thread);
|
||||
gst_element_unlink (autoplugger, audioconvert);
|
||||
gst_bin_remove (GST_BIN (work_thread), autoplugger);
|
||||
|
||||
autoplugger = gst_element_factory_make ("spider", "autoplugger");
|
||||
|
@ -548,8 +507,8 @@ gst_play_set_location (GstPlay *play, const char *location)
|
|||
|
||||
gst_bin_add (GST_BIN (work_thread), autoplugger);
|
||||
gst_element_link (source, autoplugger);
|
||||
gst_element_link (autoplugger, switch_colorspace);
|
||||
gst_element_link (autoplugger, audio_thread);
|
||||
gst_element_link (autoplugger, video_thread);
|
||||
gst_element_link (autoplugger, audioconvert);
|
||||
|
||||
g_hash_table_replace (play->priv->elements, "autoplugger", autoplugger);
|
||||
|
||||
|
@ -618,8 +577,9 @@ gst_play_seek_to_time (GstPlay * play, gint64 time_nanos)
|
|||
}
|
||||
|
||||
if (s) {
|
||||
GstClock *clock = gst_bin_get_clock (GST_BIN (play));
|
||||
play->priv->time_nanos = gst_clock_get_time (clock);
|
||||
GstClockTime time;
|
||||
time = gst_element_get_time (audio_sink_element);
|
||||
play->priv->time_nanos = GST_CLOCK_TIME_IS_VALID (time) ? time : 0;
|
||||
g_signal_emit (G_OBJECT (play), gst_play_signals[TIME_TICK],
|
||||
0,play->priv->time_nanos);
|
||||
}
|
||||
|
@ -745,8 +705,7 @@ gst_play_set_video_sink (GstPlay *play, GstElement *video_sink)
|
|||
gboolean
|
||||
gst_play_set_audio_sink (GstPlay *play, GstElement *audio_sink)
|
||||
{
|
||||
GstElement *old_audio_sink, *audio_thread, *audio_sink_element;
|
||||
GstPad *audio_tee_pad1, *audio_sink_pad, *old_audio_sink_pad;
|
||||
GstElement *old_audio_sink, *audio_thread, *audio_queue, *audio_sink_element;
|
||||
|
||||
g_return_val_if_fail (play != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
||||
|
@ -761,31 +720,21 @@ gst_play_set_audio_sink (GstPlay *play, GstElement *audio_sink)
|
|||
old_audio_sink = g_hash_table_lookup (play->priv->elements, "audio_sink");
|
||||
if (!GST_IS_ELEMENT (old_audio_sink))
|
||||
return FALSE;
|
||||
old_audio_sink_pad = g_hash_table_lookup (play->priv->elements,
|
||||
"audio_sink_pad");
|
||||
if (!GST_IS_PAD (old_audio_sink_pad))
|
||||
return FALSE;
|
||||
audio_thread = g_hash_table_lookup (play->priv->elements, "audio_thread");
|
||||
if (!GST_IS_ELEMENT (audio_thread))
|
||||
return FALSE;
|
||||
audio_tee_pad1 = g_hash_table_lookup (play->priv->elements,
|
||||
"audio_tee_pad1");
|
||||
if (!GST_IS_PAD (audio_tee_pad1))
|
||||
return FALSE;
|
||||
audio_sink_pad = gst_element_get_pad (audio_sink, "sink");
|
||||
if (!GST_IS_PAD (audio_sink_pad))
|
||||
audio_queue = g_hash_table_lookup (play->priv->elements, "audio_queue");
|
||||
if (!GST_IS_ELEMENT (audio_queue))
|
||||
return FALSE;
|
||||
|
||||
/* Unlinking old audiosink, removing it from pipeline, putting the new one
|
||||
and linking it */
|
||||
gst_pad_unlink (audio_tee_pad1, old_audio_sink_pad);
|
||||
gst_element_unlink (audio_queue, old_audio_sink);
|
||||
gst_bin_remove (GST_BIN (audio_thread), old_audio_sink);
|
||||
gst_bin_add (GST_BIN (audio_thread), audio_sink);
|
||||
gst_pad_link (audio_tee_pad1, audio_sink_pad);
|
||||
gst_element_link (audio_queue, audio_sink);
|
||||
|
||||
g_hash_table_replace (play->priv->elements, "audio_sink", audio_sink);
|
||||
g_hash_table_replace (play->priv->elements, "audio_sink_pad",
|
||||
audio_sink_pad);
|
||||
|
||||
audio_sink_element = gst_play_get_sink_element (play, audio_sink,
|
||||
GST_PLAY_SINK_TYPE_AUDIO);
|
||||
|
@ -811,7 +760,8 @@ gst_play_set_audio_sink (GstPlay *play, GstElement *audio_sink)
|
|||
gboolean
|
||||
gst_play_set_visualization (GstPlay *play, GstElement *vis_element)
|
||||
{
|
||||
GstElement *old_vis_element, *vis_thread, *vis_queue, *end_vis_queue;
|
||||
GstElement *work_thread, *old_vis_element, *video_thread;
|
||||
GstPad *tee_pad1;
|
||||
gboolean was_playing = FALSE;
|
||||
|
||||
g_return_val_if_fail (play != NULL, FALSE);
|
||||
|
@ -819,34 +769,50 @@ gst_play_set_visualization (GstPlay *play, GstElement *vis_element)
|
|||
g_return_val_if_fail (vis_element != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_IS_ELEMENT (vis_element), FALSE);
|
||||
|
||||
/* We bring back the pipeline to READY */
|
||||
if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
|
||||
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
|
||||
was_playing = TRUE;
|
||||
}
|
||||
|
||||
/* Getting needed objects */
|
||||
vis_thread = g_hash_table_lookup (play->priv->elements, "vis_thread");
|
||||
if (!GST_IS_ELEMENT (vis_thread))
|
||||
work_thread = g_hash_table_lookup (play->priv->elements, "work_thread");
|
||||
if (!GST_IS_ELEMENT (work_thread))
|
||||
return FALSE;
|
||||
old_vis_element = g_hash_table_lookup (play->priv->elements,
|
||||
"vis_element");
|
||||
if (!GST_IS_ELEMENT (old_vis_element))
|
||||
return FALSE;
|
||||
vis_queue = g_hash_table_lookup (play->priv->elements, "vis_queue");
|
||||
if (!GST_IS_ELEMENT (vis_queue))
|
||||
tee_pad1 = g_hash_table_lookup (play->priv->elements, "tee_pad1");
|
||||
if (!GST_IS_PAD (tee_pad1))
|
||||
return FALSE;
|
||||
end_vis_queue = g_hash_table_lookup (play->priv->elements, "end_vis_queue");
|
||||
if (!GST_IS_ELEMENT (end_vis_queue))
|
||||
video_thread = g_hash_table_lookup (play->priv->elements, "video_thread");
|
||||
if (!GST_IS_ELEMENT (video_thread))
|
||||
return FALSE;
|
||||
|
||||
/* Let's check if the current vis element has a managing bin. If yes that
|
||||
means the element is inside the pipeline and need to be unlinked and
|
||||
removed. We also need to pause the pipeline if it is currently playing. */
|
||||
if (gst_element_get_managing_bin (old_vis_element)) {
|
||||
GstPad *vis_element_pad;
|
||||
|
||||
/* We bring back the pipeline to PAUSED */
|
||||
if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
|
||||
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
|
||||
was_playing = TRUE;
|
||||
}
|
||||
|
||||
/* Unlinking, removing the old element then adding and linking the new one */
|
||||
gst_element_unlink (vis_queue, old_vis_element);
|
||||
gst_element_unlink (old_vis_element, end_vis_queue);
|
||||
gst_bin_remove (GST_BIN (vis_thread), old_vis_element);
|
||||
gst_bin_add (GST_BIN (vis_thread), vis_element);
|
||||
gst_element_link (vis_queue, vis_element);
|
||||
gst_element_link (vis_element, end_vis_queue);
|
||||
/* Unlinking, removing the old element then adding and linking the new one */
|
||||
vis_element_pad = gst_element_get_pad (old_vis_element, "sink");
|
||||
if (GST_IS_PAD (vis_element_pad))
|
||||
gst_pad_unlink (tee_pad1, vis_element_pad);
|
||||
gst_element_unlink (old_vis_element, video_thread);
|
||||
gst_bin_remove (GST_BIN (work_thread), old_vis_element);
|
||||
gst_bin_add (GST_BIN (work_thread), vis_element);
|
||||
vis_element_pad = gst_element_get_pad (vis_element, "sink");
|
||||
if (GST_IS_PAD (vis_element_pad))
|
||||
gst_pad_link (tee_pad1, vis_element_pad);
|
||||
gst_element_link (vis_element, video_thread);
|
||||
}
|
||||
else {
|
||||
gst_object_unref (GST_OBJECT (old_vis_element));
|
||||
}
|
||||
|
||||
g_hash_table_replace (play->priv->elements, "vis_element", vis_element);
|
||||
|
||||
if (was_playing)
|
||||
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PLAYING);
|
||||
|
@ -867,39 +833,121 @@ gst_play_set_visualization (GstPlay *play, GstElement *vis_element)
|
|||
gboolean
|
||||
gst_play_connect_visualization (GstPlay * play, gboolean connect)
|
||||
{
|
||||
GstPad *audio_tee_pad2, *vis_thread_pad;
|
||||
gboolean connected = FALSE, was_playing = FALSE;
|
||||
GstElement *work_thread, *vis_element, *autoplugger, *video_thread;
|
||||
GstElement *audioconvert, *source;
|
||||
GstPad *tee_pad1, *vis_element_pad;
|
||||
|
||||
g_return_val_if_fail (play != NULL, FALSE);
|
||||
g_return_val_if_fail (GST_IS_PLAY (play), FALSE);
|
||||
|
||||
vis_thread_pad = g_hash_table_lookup (play->priv->elements,
|
||||
"vis_thread_pad");
|
||||
if (!GST_IS_PAD (vis_thread_pad))
|
||||
/* Getting needed objects */
|
||||
work_thread = g_hash_table_lookup (play->priv->elements, "work_thread");
|
||||
if (!GST_IS_ELEMENT (work_thread))
|
||||
return FALSE;
|
||||
audio_tee_pad2 = g_hash_table_lookup (play->priv->elements,
|
||||
"audio_tee_pad2");
|
||||
if (!GST_IS_PAD (audio_tee_pad2))
|
||||
vis_element = g_hash_table_lookup (play->priv->elements, "vis_element");
|
||||
if (!GST_IS_ELEMENT (vis_element))
|
||||
return FALSE;
|
||||
tee_pad1 = g_hash_table_lookup (play->priv->elements, "tee_pad1");
|
||||
if (!GST_IS_PAD (tee_pad1))
|
||||
return FALSE;
|
||||
video_thread = g_hash_table_lookup (play->priv->elements, "video_thread");
|
||||
if (!GST_IS_ELEMENT (video_thread))
|
||||
return FALSE;
|
||||
autoplugger = g_hash_table_lookup (play->priv->elements, "autoplugger");
|
||||
if (!GST_IS_ELEMENT (autoplugger))
|
||||
return FALSE;
|
||||
source = g_hash_table_lookup (play->priv->elements, "source");
|
||||
if (!GST_IS_ELEMENT (source))
|
||||
return FALSE;
|
||||
audioconvert = g_hash_table_lookup (play->priv->elements, "audioconvert");
|
||||
if (!GST_IS_ELEMENT (audioconvert))
|
||||
return FALSE;
|
||||
|
||||
if (GST_STATE (GST_ELEMENT (play)) == GST_STATE_PLAYING) {
|
||||
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PAUSED);
|
||||
was_playing = TRUE;
|
||||
}
|
||||
|
||||
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 (was_playing)
|
||||
gst_element_set_state (GST_ELEMENT (play), GST_STATE_PLAYING);
|
||||
/* 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);
|
||||
|
||||
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 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;
|
||||
|
||||
/* Adding and connecting a new autoplugger */
|
||||
gst_bin_add (GST_BIN (work_thread), autoplugger);
|
||||
gst_element_link (source, autoplugger);
|
||||
gst_element_link (autoplugger, audioconvert);
|
||||
|
||||
g_hash_table_replace (play->priv->elements, "autoplugger", autoplugger);
|
||||
|
||||
/* Otherwise we add the element to the bin and link it to video_thread */
|
||||
gst_bin_add (GST_BIN (work_thread), vis_element);
|
||||
vis_element_pad = gst_element_get_pad (vis_element, "sink");
|
||||
if (GST_IS_PAD (vis_element_pad))
|
||||
gst_pad_link (tee_pad1, vis_element_pad);
|
||||
|
||||
filtered_caps = gst_caps_from_string ("video/x-raw-rgb, "
|
||||
"framerate = 30.0; "
|
||||
"video/x-raw-yuv, "
|
||||
"framerate = 30.0");
|
||||
|
||||
if (!gst_element_link_filtered (vis_element, video_thread, filtered_caps))
|
||||
g_message ("failed linking filtered vis with video thread");
|
||||
|
||||
gst_caps_free (filtered_caps);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -916,7 +964,7 @@ gst_play_connect_visualization (GstPlay * play, gboolean connect)
|
|||
*/
|
||||
GstElement *
|
||||
gst_play_get_sink_element (GstPlay *play,
|
||||
GstElement *element, GstPlaySinkType sink_type)
|
||||
GstElement *element, GstPlaySinkType sink_type)
|
||||
{
|
||||
GList *elements = NULL;
|
||||
const GList *pads = NULL;
|
||||
|
|
|
@ -548,6 +548,22 @@ gst_ximagesink_xcontext_clear (GstXImageSink *ximagesink)
|
|||
ximagesink->xcontext = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ximagesink_imagepool_clear (GstXImageSink *ximagesink)
|
||||
{
|
||||
g_mutex_lock(ximagesink->pool_lock);
|
||||
|
||||
while (ximagesink->image_pool)
|
||||
{
|
||||
GstXImage *ximage = ximagesink->image_pool->data;
|
||||
ximagesink->image_pool = g_slist_delete_link (ximagesink->image_pool,
|
||||
ximagesink->image_pool);
|
||||
gst_ximagesink_ximage_destroy (ximagesink, ximage);
|
||||
}
|
||||
|
||||
g_mutex_unlock(ximagesink->pool_lock);
|
||||
}
|
||||
|
||||
/* Element stuff */
|
||||
|
||||
static GstCaps *
|
||||
|
@ -693,6 +709,26 @@ gst_ximagesink_change_state (GstElement *element)
|
|||
GST_VIDEOSINK_HEIGHT (ximagesink) = 0;
|
||||
break;
|
||||
case GST_STATE_READY_TO_NULL:
|
||||
if (ximagesink->ximage)
|
||||
{
|
||||
gst_ximagesink_ximage_destroy (ximagesink, ximagesink->ximage);
|
||||
ximagesink->ximage = NULL;
|
||||
}
|
||||
|
||||
if (ximagesink->image_pool)
|
||||
gst_ximagesink_imagepool_clear (ximagesink);
|
||||
|
||||
if (ximagesink->xwindow)
|
||||
{
|
||||
gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow);
|
||||
ximagesink->xwindow = NULL;
|
||||
}
|
||||
|
||||
if (ximagesink->xcontext)
|
||||
{
|
||||
gst_ximagesink_xcontext_clear (ximagesink);
|
||||
ximagesink->xcontext = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -851,22 +887,6 @@ gst_ximagesink_buffer_alloc (GstPad *pad, guint64 offset, guint size)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_ximagesink_imagepool_clear (GstXImageSink *ximagesink)
|
||||
{
|
||||
g_mutex_lock(ximagesink->pool_lock);
|
||||
|
||||
while (ximagesink->image_pool)
|
||||
{
|
||||
GstXImage *ximage = ximagesink->image_pool->data;
|
||||
ximagesink->image_pool = g_slist_delete_link (ximagesink->image_pool,
|
||||
ximagesink->image_pool);
|
||||
gst_ximagesink_ximage_destroy (ximagesink, ximage);
|
||||
}
|
||||
|
||||
g_mutex_unlock(ximagesink->pool_lock);
|
||||
}
|
||||
|
||||
/* Interfaces stuff */
|
||||
|
||||
static gboolean
|
||||
|
@ -1129,25 +1149,7 @@ gst_ximagesink_dispose (GObject *object)
|
|||
g_free (ximagesink->display_name);
|
||||
ximagesink->display_name = NULL;
|
||||
}
|
||||
|
||||
if (ximagesink->ximage)
|
||||
{
|
||||
gst_ximagesink_ximage_destroy (ximagesink, ximagesink->ximage);
|
||||
ximagesink->ximage = NULL;
|
||||
}
|
||||
|
||||
if (ximagesink->image_pool)
|
||||
gst_ximagesink_imagepool_clear (ximagesink);
|
||||
|
||||
if (ximagesink->xwindow)
|
||||
{
|
||||
gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow);
|
||||
ximagesink->xwindow = NULL;
|
||||
}
|
||||
|
||||
if (ximagesink->xcontext)
|
||||
gst_ximagesink_xcontext_clear (ximagesink);
|
||||
|
||||
|
||||
g_mutex_free (ximagesink->x_lock);
|
||||
g_mutex_free (ximagesink->pool_lock);
|
||||
|
||||
|
|
|
@ -733,6 +733,27 @@ gst_xvimagesink_xcontext_get (GstXvImageSink *xvimagesink)
|
|||
|
||||
xcontext->channels_list = g_list_append (xcontext->channels_list,
|
||||
channel);
|
||||
|
||||
/* If the colorbalance settings have not been touched we get Xv values
|
||||
as defaults and update our internal variables */
|
||||
if (!xvimagesink->cb_changed) {
|
||||
gint val;
|
||||
XvGetPortAttribute (xcontext->disp, xcontext->xv_port_id,
|
||||
XInternAtom (xcontext->disp, channel->label, 1),
|
||||
&val);
|
||||
/* Normalize val to [-1000, 1000] */
|
||||
val = -1000 + 2000 * (val - channel->min_value) /
|
||||
(channel->max_value - channel->min_value);
|
||||
|
||||
if (!g_ascii_strcasecmp (channels[i], "XV_HUE"))
|
||||
xvimagesink->hue = val;
|
||||
else if (!g_ascii_strcasecmp (channels[i], "XV_SATURATION"))
|
||||
xvimagesink->saturation = val;
|
||||
else if (!g_ascii_strcasecmp (channels[i], "XV_BRIGHTNESS"))
|
||||
xvimagesink->brightness = val;
|
||||
else if (!g_ascii_strcasecmp (channels[i], "XV_CONTRAST"))
|
||||
xvimagesink->contrast = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -793,6 +814,22 @@ gst_xvimagesink_xcontext_clear (GstXvImageSink *xvimagesink)
|
|||
xvimagesink->xcontext = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_xvimagesink_imagepool_clear (GstXvImageSink *xvimagesink)
|
||||
{
|
||||
g_mutex_lock(xvimagesink->pool_lock);
|
||||
|
||||
while (xvimagesink->image_pool)
|
||||
{
|
||||
GstXvImage *xvimage = xvimagesink->image_pool->data;
|
||||
xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool,
|
||||
xvimagesink->image_pool);
|
||||
gst_xvimagesink_xvimage_destroy (xvimagesink, xvimage);
|
||||
}
|
||||
|
||||
g_mutex_unlock(xvimagesink->pool_lock);
|
||||
}
|
||||
|
||||
/* Element stuff */
|
||||
|
||||
static GstCaps *
|
||||
|
@ -981,6 +1018,26 @@ gst_xvimagesink_change_state (GstElement *element)
|
|||
GST_VIDEOSINK_HEIGHT (xvimagesink) = 0;
|
||||
break;
|
||||
case GST_STATE_READY_TO_NULL:
|
||||
if (xvimagesink->xvimage)
|
||||
{
|
||||
gst_xvimagesink_xvimage_destroy (xvimagesink, xvimagesink->xvimage);
|
||||
xvimagesink->xvimage = NULL;
|
||||
}
|
||||
|
||||
if (xvimagesink->image_pool)
|
||||
gst_xvimagesink_imagepool_clear (xvimagesink);
|
||||
|
||||
if (xvimagesink->xwindow)
|
||||
{
|
||||
gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow);
|
||||
xvimagesink->xwindow = NULL;
|
||||
}
|
||||
|
||||
if (xvimagesink->xcontext)
|
||||
{
|
||||
gst_xvimagesink_xcontext_clear (xvimagesink);
|
||||
xvimagesink->xcontext = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1140,22 +1197,6 @@ gst_xvimagesink_buffer_alloc (GstPad *pad, guint64 offset, guint size)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_xvimagesink_imagepool_clear (GstXvImageSink *xvimagesink)
|
||||
{
|
||||
g_mutex_lock(xvimagesink->pool_lock);
|
||||
|
||||
while (xvimagesink->image_pool)
|
||||
{
|
||||
GstXvImage *xvimage = xvimagesink->image_pool->data;
|
||||
xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool,
|
||||
xvimagesink->image_pool);
|
||||
gst_xvimagesink_xvimage_destroy (xvimagesink, xvimage);
|
||||
}
|
||||
|
||||
g_mutex_unlock(xvimagesink->pool_lock);
|
||||
}
|
||||
|
||||
/* Interfaces stuff */
|
||||
|
||||
static gboolean
|
||||
|
@ -1343,6 +1384,12 @@ gst_xvimagesink_colorbalance_set_value (GstColorBalance *balance,
|
|||
g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
|
||||
g_return_if_fail (channel->label != NULL);
|
||||
|
||||
xvimagesink->cb_changed = TRUE;
|
||||
|
||||
/* Normalize val to [-1000, 1000] */
|
||||
value = -1000 + 2000 * (value - channel->min_value) /
|
||||
(channel->max_value - channel->min_value);
|
||||
|
||||
if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0)
|
||||
{
|
||||
xvimagesink->hue = value;
|
||||
|
@ -1400,6 +1447,10 @@ gst_xvimagesink_colorbalance_get_value (GstColorBalance *balance,
|
|||
g_warning ("got an unknown channel %s", channel->label);
|
||||
}
|
||||
|
||||
/* Normalize val to [channel->min_value, channel->max_value] */
|
||||
value = channel->min_value + (channel->max_value - channel->min_value) *
|
||||
(value + 1000) / 2000;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -1432,18 +1483,22 @@ gst_xvimagesink_set_property (GObject *object, guint prop_id,
|
|||
{
|
||||
case ARG_HUE:
|
||||
xvimagesink->hue = g_value_get_int (value);
|
||||
xvimagesink->cb_changed = TRUE;
|
||||
gst_xvimagesink_update_colorbalance (xvimagesink);
|
||||
break;
|
||||
case ARG_CONTRAST:
|
||||
xvimagesink->contrast = g_value_get_int (value);
|
||||
xvimagesink->cb_changed = TRUE;
|
||||
gst_xvimagesink_update_colorbalance (xvimagesink);
|
||||
break;
|
||||
case ARG_BRIGHTNESS:
|
||||
xvimagesink->brightness = g_value_get_int (value);
|
||||
xvimagesink->cb_changed = TRUE;
|
||||
gst_xvimagesink_update_colorbalance (xvimagesink);
|
||||
break;
|
||||
case ARG_SATURATION:
|
||||
xvimagesink->saturation = g_value_get_int (value);
|
||||
xvimagesink->cb_changed = TRUE;
|
||||
gst_xvimagesink_update_colorbalance (xvimagesink);
|
||||
break;
|
||||
case ARG_DISPLAY:
|
||||
|
@ -1510,25 +1565,7 @@ gst_xvimagesink_dispose (GObject *object)
|
|||
g_free (xvimagesink->display_name);
|
||||
xvimagesink->display_name = NULL;
|
||||
}
|
||||
|
||||
if (xvimagesink->xvimage)
|
||||
{
|
||||
gst_xvimagesink_xvimage_destroy (xvimagesink, xvimagesink->xvimage);
|
||||
xvimagesink->xvimage = NULL;
|
||||
}
|
||||
|
||||
if (xvimagesink->image_pool)
|
||||
gst_xvimagesink_imagepool_clear (xvimagesink);
|
||||
|
||||
if (xvimagesink->xwindow)
|
||||
{
|
||||
gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow);
|
||||
xvimagesink->xwindow = NULL;
|
||||
}
|
||||
|
||||
if (xvimagesink->xcontext)
|
||||
gst_xvimagesink_xcontext_clear (xvimagesink);
|
||||
|
||||
|
||||
g_mutex_free (xvimagesink->x_lock);
|
||||
g_mutex_free (xvimagesink->pool_lock);
|
||||
|
||||
|
@ -1563,6 +1600,7 @@ gst_xvimagesink_init (GstXvImageSink *xvimagesink)
|
|||
|
||||
xvimagesink->hue = xvimagesink->saturation = 0;
|
||||
xvimagesink->contrast = xvimagesink->brightness = 0;
|
||||
xvimagesink->cb_changed = FALSE;
|
||||
|
||||
xvimagesink->framerate = 0;
|
||||
|
||||
|
|
|
@ -134,6 +134,7 @@ struct _GstXvImageSink {
|
|||
gint contrast;
|
||||
gint hue;
|
||||
gint saturation;
|
||||
gboolean cb_changed;
|
||||
|
||||
GMutex *x_lock;
|
||||
|
||||
|
|
Loading…
Reference in a new issue