gst/playback/gstplaybin2.c: Enable vis setting.
Original commit message from CVS: * gst/playback/gstplaybin2.c: (gst_play_bin_set_property): Enable vis setting. * gst/playback/gstplaysink.c: (gst_play_sink_init), (gst_play_sink_dispose), (gst_play_sink_vis_unblocked), (gst_play_sink_vis_blocked), (gst_play_sink_set_vis_plugin), (gen_vis_chain): Implement vis switching while playing.
This commit is contained in:
parent
3fb3c580b1
commit
472162d1b1
11
ChangeLog
11
ChangeLog
@ -1,3 +1,14 @@
|
|||||||
|
2008-02-29 Wim Taymans <wim.taymans@collabora.co.uk>
|
||||||
|
|
||||||
|
* gst/playback/gstplaybin2.c: (gst_play_bin_set_property):
|
||||||
|
Enable vis setting.
|
||||||
|
|
||||||
|
* gst/playback/gstplaysink.c: (gst_play_sink_init),
|
||||||
|
(gst_play_sink_dispose), (gst_play_sink_vis_unblocked),
|
||||||
|
(gst_play_sink_vis_blocked), (gst_play_sink_set_vis_plugin),
|
||||||
|
(gen_vis_chain):
|
||||||
|
Implement vis switching while playing.
|
||||||
|
|
||||||
2008-02-28 David Schleef <ds@schleef.org>
|
2008-02-28 David Schleef <ds@schleef.org>
|
||||||
|
|
||||||
* gst-libs/gst/riff/riff-media.c: Add Dirac mapping
|
* gst-libs/gst/riff/riff-media.c: Add Dirac mapping
|
||||||
|
@ -1157,6 +1157,8 @@ gst_play_bin_set_property (GObject * object, guint prop_id,
|
|||||||
case PROP_AUDIO_SINK:
|
case PROP_AUDIO_SINK:
|
||||||
break;
|
break;
|
||||||
case PROP_VIS_PLUGIN:
|
case PROP_VIS_PLUGIN:
|
||||||
|
gst_play_sink_set_vis_plugin (playbin->playsink,
|
||||||
|
g_value_get_object (value));
|
||||||
break;
|
break;
|
||||||
case PROP_VOLUME:
|
case PROP_VOLUME:
|
||||||
gst_play_sink_set_volume (playbin->playsink, g_value_get_double (value));
|
gst_play_sink_set_volume (playbin->playsink, g_value_get_double (value));
|
||||||
|
@ -72,8 +72,12 @@ typedef struct
|
|||||||
GstElement *queue;
|
GstElement *queue;
|
||||||
GstElement *conv;
|
GstElement *conv;
|
||||||
GstElement *resample;
|
GstElement *resample;
|
||||||
|
GstPad *blockpad; /* srcpad of resample, used for switching the vis */
|
||||||
|
GstPad *vissinkpad; /* visualisation sinkpad, */
|
||||||
GstElement *vis;
|
GstElement *vis;
|
||||||
GstPad *srcpad;
|
GstPad *vissrcpad; /* visualisation srcpad, */
|
||||||
|
GstPad *srcpad; /* outgoing srcpad, used to connect to the next
|
||||||
|
* chain */
|
||||||
} GstPlayVisChain;
|
} GstPlayVisChain;
|
||||||
|
|
||||||
#define GST_PLAY_SINK_GET_LOCK(playsink) (((GstPlaySink *)playsink)->lock)
|
#define GST_PLAY_SINK_GET_LOCK(playsink) (((GstPlaySink *)playsink)->lock)
|
||||||
@ -115,9 +119,6 @@ struct _GstPlaySink
|
|||||||
|
|
||||||
/* internal elements */
|
/* internal elements */
|
||||||
GstElement *textoverlay_element;
|
GstElement *textoverlay_element;
|
||||||
|
|
||||||
GstElement *pending_visualisation;
|
|
||||||
GstElement *fakesink;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstPlaySinkClass
|
struct _GstPlaySinkClass
|
||||||
@ -256,7 +257,6 @@ gst_play_sink_init (GstPlaySink * playsink)
|
|||||||
playsink->video_sink = NULL;
|
playsink->video_sink = NULL;
|
||||||
playsink->audio_sink = NULL;
|
playsink->audio_sink = NULL;
|
||||||
playsink->visualisation = NULL;
|
playsink->visualisation = NULL;
|
||||||
playsink->pending_visualisation = NULL;
|
|
||||||
playsink->textoverlay_element = NULL;
|
playsink->textoverlay_element = NULL;
|
||||||
playsink->volume = 1.0;
|
playsink->volume = 1.0;
|
||||||
playsink->font_desc = NULL;
|
playsink->font_desc = NULL;
|
||||||
@ -287,11 +287,6 @@ gst_play_sink_dispose (GObject * object)
|
|||||||
gst_object_unref (playsink->visualisation);
|
gst_object_unref (playsink->visualisation);
|
||||||
playsink->visualisation = NULL;
|
playsink->visualisation = NULL;
|
||||||
}
|
}
|
||||||
if (playsink->pending_visualisation != NULL) {
|
|
||||||
gst_element_set_state (playsink->pending_visualisation, GST_STATE_NULL);
|
|
||||||
gst_object_unref (playsink->pending_visualisation);
|
|
||||||
playsink->pending_visualisation = NULL;
|
|
||||||
}
|
|
||||||
if (playsink->textoverlay_element != NULL) {
|
if (playsink->textoverlay_element != NULL) {
|
||||||
gst_object_unref (playsink->textoverlay_element);
|
gst_object_unref (playsink->textoverlay_element);
|
||||||
playsink->textoverlay_element = NULL;
|
playsink->textoverlay_element = NULL;
|
||||||
@ -314,125 +309,6 @@ gst_play_sink_finalize (GObject * object)
|
|||||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gst_play_sink_vis_unblocked (GstPad * tee_pad, gboolean blocked,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
GstPlaySink *playsink = GST_PLAY_SINK (user_data);
|
|
||||||
|
|
||||||
if (playsink->pending_visualisation)
|
|
||||||
gst_pad_set_blocked_async (tee_pad, FALSE, gst_play_sink_vis_unblocked,
|
|
||||||
playsink);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_play_sink_vis_blocked (GstPad * tee_pad, gboolean blocked,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
GstPlaySink *playsink = GST_PLAY_SINK (user_data);
|
|
||||||
GstBin *vis_bin = NULL;
|
|
||||||
GstPad *vis_sink_pad = NULL, *vis_src_pad = NULL, *vqueue_pad = NULL;
|
|
||||||
GstState bin_state;
|
|
||||||
GstElement *pending_visualisation;
|
|
||||||
|
|
||||||
GST_OBJECT_LOCK (playsink);
|
|
||||||
pending_visualisation = playsink->pending_visualisation;
|
|
||||||
playsink->pending_visualisation = NULL;
|
|
||||||
GST_OBJECT_UNLOCK (playsink);
|
|
||||||
|
|
||||||
/* We want to disable visualisation */
|
|
||||||
if (!GST_IS_ELEMENT (pending_visualisation)) {
|
|
||||||
/* Set visualisation element to READY */
|
|
||||||
gst_element_set_state (playsink->visualisation, GST_STATE_READY);
|
|
||||||
goto beach;
|
|
||||||
}
|
|
||||||
|
|
||||||
vis_bin =
|
|
||||||
GST_BIN_CAST (gst_object_get_parent (GST_OBJECT_CAST (playsink->
|
|
||||||
visualisation)));
|
|
||||||
|
|
||||||
if (!GST_IS_BIN (vis_bin) || !GST_IS_PAD (tee_pad)) {
|
|
||||||
goto beach;
|
|
||||||
}
|
|
||||||
|
|
||||||
vis_src_pad = gst_element_get_pad (playsink->visualisation, "src");
|
|
||||||
vis_sink_pad = gst_pad_get_peer (tee_pad);
|
|
||||||
|
|
||||||
/* Can be fakesink */
|
|
||||||
if (GST_IS_PAD (vis_src_pad)) {
|
|
||||||
vqueue_pad = gst_pad_get_peer (vis_src_pad);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!GST_IS_PAD (vis_sink_pad)) {
|
|
||||||
goto beach;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check the bin's state */
|
|
||||||
GST_OBJECT_LOCK (vis_bin);
|
|
||||||
bin_state = GST_STATE (vis_bin);
|
|
||||||
GST_OBJECT_UNLOCK (vis_bin);
|
|
||||||
|
|
||||||
/* Unlink */
|
|
||||||
gst_pad_unlink (tee_pad, vis_sink_pad);
|
|
||||||
gst_object_unref (vis_sink_pad);
|
|
||||||
vis_sink_pad = NULL;
|
|
||||||
|
|
||||||
if (GST_IS_PAD (vqueue_pad)) {
|
|
||||||
gst_pad_unlink (vis_src_pad, vqueue_pad);
|
|
||||||
gst_object_unref (vis_src_pad);
|
|
||||||
vis_src_pad = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove from vis_bin */
|
|
||||||
gst_bin_remove (vis_bin, playsink->visualisation);
|
|
||||||
/* Set state to NULL */
|
|
||||||
gst_element_set_state (playsink->visualisation, GST_STATE_NULL);
|
|
||||||
/* And loose our ref */
|
|
||||||
gst_object_unref (playsink->visualisation);
|
|
||||||
|
|
||||||
if (pending_visualisation) {
|
|
||||||
/* Ref this new visualisation element before adding to the bin */
|
|
||||||
gst_object_ref (pending_visualisation);
|
|
||||||
/* Add the new one */
|
|
||||||
gst_bin_add (vis_bin, pending_visualisation);
|
|
||||||
/* Synchronizing state */
|
|
||||||
gst_element_set_state (pending_visualisation, bin_state);
|
|
||||||
|
|
||||||
vis_sink_pad = gst_element_get_pad (pending_visualisation, "sink");
|
|
||||||
vis_src_pad = gst_element_get_pad (pending_visualisation, "src");
|
|
||||||
|
|
||||||
if (!GST_IS_PAD (vis_sink_pad) || !GST_IS_PAD (vis_src_pad)) {
|
|
||||||
goto beach;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Link */
|
|
||||||
gst_pad_link (tee_pad, vis_sink_pad);
|
|
||||||
gst_pad_link (vis_src_pad, vqueue_pad);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We are done */
|
|
||||||
gst_object_unref (playsink->visualisation);
|
|
||||||
playsink->visualisation = pending_visualisation;
|
|
||||||
|
|
||||||
beach:
|
|
||||||
if (vis_sink_pad) {
|
|
||||||
gst_object_unref (vis_sink_pad);
|
|
||||||
}
|
|
||||||
if (vis_src_pad) {
|
|
||||||
gst_object_unref (vis_src_pad);
|
|
||||||
}
|
|
||||||
if (vqueue_pad) {
|
|
||||||
gst_object_unref (vqueue_pad);
|
|
||||||
}
|
|
||||||
if (vis_bin) {
|
|
||||||
gst_object_unref (vis_bin);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unblock the pad */
|
|
||||||
gst_pad_set_blocked_async (tee_pad, FALSE, gst_play_sink_vis_unblocked,
|
|
||||||
playsink);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
gst_play_sink_set_video_sink (GstPlaySink * playsink, GstElement * sink)
|
gst_play_sink_set_video_sink (GstPlaySink * playsink, GstElement * sink)
|
||||||
{
|
{
|
||||||
@ -463,66 +339,89 @@ gst_play_sink_set_audio_sink (GstPlaySink * playsink, GstElement * sink)
|
|||||||
GST_OBJECT_UNLOCK (playsink);
|
GST_OBJECT_UNLOCK (playsink);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
gst_play_sink_set_vis_plugin (GstPlaySink * playsink,
|
gst_play_sink_vis_unblocked (GstPad * tee_pad, gboolean blocked,
|
||||||
GstElement * pending_visualisation)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
/* Take ownership */
|
GstPlaySink *playsink;
|
||||||
if (pending_visualisation) {
|
|
||||||
gst_object_ref (pending_visualisation);
|
|
||||||
gst_object_sink (pending_visualisation);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Do we already have a visualisation change pending? If yes, change the
|
playsink = GST_PLAY_SINK (user_data);
|
||||||
* pending vis with the new one. */
|
/* nothing to do here, we need a dummy callback here to make the async call
|
||||||
GST_OBJECT_LOCK (playsink);
|
* non-blocking. */
|
||||||
if (playsink->pending_visualisation) {
|
GST_DEBUG_OBJECT (playsink, "vis pad unblocked");
|
||||||
gst_object_unref (playsink->pending_visualisation);
|
}
|
||||||
playsink->pending_visualisation = pending_visualisation;
|
|
||||||
GST_OBJECT_UNLOCK (playsink);
|
|
||||||
} else {
|
|
||||||
GST_OBJECT_UNLOCK (playsink);
|
|
||||||
/* Was there a visualisation already set ? */
|
|
||||||
if (playsink->visualisation != NULL) {
|
|
||||||
GstBin *vis_bin = NULL;
|
|
||||||
|
|
||||||
vis_bin =
|
static void
|
||||||
GST_BIN_CAST (gst_object_get_parent (GST_OBJECT_CAST (playsink->
|
gst_play_sink_vis_blocked (GstPad * tee_pad, gboolean blocked,
|
||||||
visualisation)));
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GstPlaySink *playsink;
|
||||||
|
GstPlayVisChain *chain;
|
||||||
|
|
||||||
/* Check if the visualisation is already in a bin */
|
playsink = GST_PLAY_SINK (user_data);
|
||||||
if (GST_IS_BIN (vis_bin)) {
|
|
||||||
GstPad *vis_sink_pad = NULL, *tee_pad = NULL;
|
|
||||||
|
|
||||||
/* Now get tee pad and block it async */
|
GST_PLAY_SINK_LOCK (playsink);
|
||||||
vis_sink_pad = gst_element_get_pad (playsink->visualisation, "sink");
|
GST_DEBUG_OBJECT (playsink, "vis pad blocked");
|
||||||
if (!GST_IS_PAD (vis_sink_pad)) {
|
/* now try to change the plugin in the running vis chain */
|
||||||
goto beach;
|
if (!(chain = (GstPlayVisChain *) playsink->vischain))
|
||||||
}
|
goto done;
|
||||||
tee_pad = gst_pad_get_peer (vis_sink_pad);
|
|
||||||
if (!GST_IS_PAD (tee_pad)) {
|
|
||||||
goto beach;
|
|
||||||
}
|
|
||||||
|
|
||||||
playsink->pending_visualisation = pending_visualisation;
|
/* unlink the old plugin and unghost the pad */
|
||||||
/* Block with callback */
|
gst_pad_unlink (chain->blockpad, chain->vissinkpad);
|
||||||
gst_pad_set_blocked_async (tee_pad, TRUE, gst_play_sink_vis_blocked,
|
gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (chain->srcpad), NULL);
|
||||||
playsink);
|
|
||||||
beach:
|
/* set the old plugin to NULL and remove */
|
||||||
if (vis_sink_pad) {
|
gst_element_set_state (chain->vis, GST_STATE_NULL);
|
||||||
gst_object_unref (vis_sink_pad);
|
gst_bin_remove (GST_BIN_CAST (chain->chain.bin), chain->vis);
|
||||||
}
|
|
||||||
if (tee_pad) {
|
/* add new plugin and set state to playing */
|
||||||
gst_object_unref (tee_pad);
|
chain->vis = gst_object_ref (playsink->visualisation);
|
||||||
}
|
gst_bin_add (GST_BIN_CAST (chain->chain.bin), chain->vis);
|
||||||
gst_object_unref (vis_bin);
|
gst_element_set_state (chain->vis, GST_STATE_PLAYING);
|
||||||
} else {
|
|
||||||
playsink->visualisation = pending_visualisation;
|
/* get pads */
|
||||||
}
|
chain->vissinkpad = gst_element_get_pad (chain->vis, "sink");
|
||||||
} else {
|
chain->vissrcpad = gst_element_get_pad (chain->vis, "src");
|
||||||
playsink->visualisation = pending_visualisation;
|
|
||||||
}
|
/* link pads */
|
||||||
}
|
gst_pad_link (chain->blockpad, chain->vissinkpad);
|
||||||
|
gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (chain->srcpad),
|
||||||
|
chain->vissrcpad);
|
||||||
|
|
||||||
|
done:
|
||||||
|
/* Unblock the pad */
|
||||||
|
gst_pad_set_blocked_async (tee_pad, FALSE, gst_play_sink_vis_unblocked,
|
||||||
|
playsink);
|
||||||
|
GST_PLAY_SINK_UNLOCK (playsink);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_play_sink_set_vis_plugin (GstPlaySink * playsink, GstElement * vis)
|
||||||
|
{
|
||||||
|
GstPlayVisChain *chain;
|
||||||
|
|
||||||
|
GST_PLAY_SINK_LOCK (playsink);
|
||||||
|
/* first store the new vis */
|
||||||
|
if (playsink->visualisation)
|
||||||
|
gst_object_unref (playsink->visualisation);
|
||||||
|
playsink->visualisation = gst_object_ref (vis);
|
||||||
|
|
||||||
|
/* now try to change the plugin in the running vis chain, if we have no chain,
|
||||||
|
* we don't bother, any future vis chain will be created with the new vis
|
||||||
|
* plugin. */
|
||||||
|
if (!(chain = (GstPlayVisChain *) playsink->vischain))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* block the pad, the next time the callback is called we can change the
|
||||||
|
* visualisation. It's possible that this never happens or that the pad was
|
||||||
|
* already blocked. */
|
||||||
|
GST_DEBUG_OBJECT (playsink, "blocking vis pad");
|
||||||
|
gst_pad_set_blocked_async (chain->blockpad, TRUE, gst_play_sink_vis_blocked,
|
||||||
|
playsink);
|
||||||
|
done:
|
||||||
|
GST_PLAY_SINK_UNLOCK (playsink);
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1120,14 +1019,14 @@ link_failed:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* +----------------------------------------------------+
|
* +-------------------------------------------------------------------+
|
||||||
* | visbin |
|
* | visbin |
|
||||||
* | +----------+ +------------+ +-------+ |
|
* | +----------+ +------------+ +----------+ +-------+ |
|
||||||
* | | visqueue | | audioconv | | vis | |
|
* | | visqueue | | audioconv | | audiores | | vis | |
|
||||||
* | +-sink src-sink + samp src-sink src-+ |
|
* | +-sink src-sink + samp src-sink src-sink src-+ |
|
||||||
* | | +----------+ +------------+ +-------+ | |
|
* | | +----------+ +------------+ +----------+ +-------+ | |
|
||||||
* sink-+ +-src
|
* sink-+ +-src
|
||||||
* +----------------------------------------------------+
|
* +-------------------------------------------------------------------+
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static GstPlayChain *
|
static GstPlayChain *
|
||||||
@ -1161,8 +1060,12 @@ gen_vis_chain (GstPlaySink * playsink)
|
|||||||
goto no_audioresample;
|
goto no_audioresample;
|
||||||
gst_bin_add (bin, chain->resample);
|
gst_bin_add (bin, chain->resample);
|
||||||
|
|
||||||
|
/* this pad will be used for blocking the dataflow and switching the vis
|
||||||
|
* plugin */
|
||||||
|
chain->blockpad = gst_element_get_pad (chain->resample, "src");
|
||||||
|
|
||||||
if (playsink->visualisation) {
|
if (playsink->visualisation) {
|
||||||
chain->vis = playsink->visualisation;
|
chain->vis = gst_object_ref (playsink->visualisation);
|
||||||
} else {
|
} else {
|
||||||
chain->vis = gst_element_factory_make ("goom", "vis");
|
chain->vis = gst_element_factory_make ("goom", "vis");
|
||||||
if (!chain->vis)
|
if (!chain->vis)
|
||||||
@ -1176,14 +1079,15 @@ gen_vis_chain (GstPlaySink * playsink)
|
|||||||
if (!res)
|
if (!res)
|
||||||
goto link_failed;
|
goto link_failed;
|
||||||
|
|
||||||
|
chain->vissinkpad = gst_element_get_pad (chain->vis, "sink");
|
||||||
|
chain->vissrcpad = gst_element_get_pad (chain->vis, "src");
|
||||||
|
|
||||||
pad = gst_element_get_pad (chain->queue, "sink");
|
pad = gst_element_get_pad (chain->queue, "sink");
|
||||||
chain->chain.sinkpad = gst_ghost_pad_new ("sink", pad);
|
chain->chain.sinkpad = gst_ghost_pad_new ("sink", pad);
|
||||||
gst_object_unref (pad);
|
gst_object_unref (pad);
|
||||||
gst_element_add_pad (chain->chain.bin, chain->chain.sinkpad);
|
gst_element_add_pad (chain->chain.bin, chain->chain.sinkpad);
|
||||||
|
|
||||||
pad = gst_element_get_pad (chain->vis, "src");
|
chain->srcpad = gst_ghost_pad_new ("src", chain->vissrcpad);
|
||||||
chain->srcpad = gst_ghost_pad_new ("src", pad);
|
|
||||||
gst_object_unref (pad);
|
|
||||||
gst_element_add_pad (chain->chain.bin, chain->srcpad);
|
gst_element_add_pad (chain->chain.bin, chain->srcpad);
|
||||||
|
|
||||||
return (GstPlayChain *) chain;
|
return (GstPlayChain *) chain;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user