+2008-01-07 Wim Taymans <wim.taymans@collabora.co.uk>
+
+ * gst/playback/gstplay-enum.c:
+ (register_gst_autoplug_select_result),
+ (gst_autoplug_select_result_get_type), (register_gst_play_flags),
+ (gst_play_flags_get_type):
+ * gst/playback/gstplay-enum.h:
+ Add enums for configuration flags.
+
+ * gst/playback/gstplaybin2.c: (gst_play_bin_class_init),
+ (init_group), (gst_play_bin_init), (gst_play_bin_set_property),
+ (gst_play_bin_get_property), (no_more_pads_cb),
+ (autoplug_select_cb), (gst_play_bin_change_state):
+ Merge mode with flags.
+ Add more property getters/setters, defaults and docs.
+ Add properties to get number of audio/video/text streams.
+ Create sink object in _init so that we can always rely on it being
+ there.
+
+ * gst/playback/gstplaysink.c: (gst_play_sink_init),
+ (gen_video_chain), (gen_audio_chain), (gen_vis_chain),
+ (activate_vis), (gst_play_sink_reconfigure),
+ (gst_play_sink_set_flags), (gst_play_sink_get_flags),
+ (gst_play_sink_change_state):
+ * gst/playback/gstplaysink.h:
+ Use flags to configure the sink pipelines.
+ Add tee before audio pipeline so that we can use it for visualisations.
+ Start working on integrating visualisations.
+ Remove mode, we can do everything with the flags now.
+ Add method to configue the sink pipeline.
+
2008-01-06 Tim-Philipp Müller <tim at centricular dot net>
* tests/check/pipelines/theoraenc.c: (check_buffer_is_header),
#include "gstplay-enum.h"
#define C_ENUM(v) ((gint) v)
+#define C_FLAGS(v) ((guint) v)
static void
register_gst_autoplug_select_result (GType * id)
g_once (&once, (GThreadFunc) register_gst_autoplug_select_result, &id);
return id;
}
+
+static void
+register_gst_play_flags (GType * id)
+{
+ static const GFlagsValue values[] = {
+ {C_FLAGS (GST_PLAY_FLAG_VIDEO), "Render the video stream", "video"},
+ {C_FLAGS (GST_PLAY_FLAG_AUDIO), "Render the audio stream", "audio"},
+ {C_FLAGS (GST_PLAY_FLAG_TEXT), "Render subtitles", "text"},
+ {C_FLAGS (GST_PLAY_FLAG_VIS),
+ "Render visualisation when no video is present", "vis"},
+ {C_FLAGS (GST_PLAY_FLAG_SOFT_VOLUME), "Use software volume", "soft-volume"},
+ {C_FLAGS (GST_PLAY_FLAG_NATIVE_AUDIO), "Only use native audio formats",
+ "native-audio"},
+ {C_FLAGS (GST_PLAY_FLAG_NATIVE_VIDEO), "Only use native video formats",
+ "native-video"},
+ {0, NULL, NULL}
+ };
+ *id = g_flags_register_static ("GstPlayFlags", values);
+}
+
+GType
+gst_play_flags_get_type (void)
+{
+ static GType id;
+ static GOnce once = G_ONCE_INIT;
+
+ g_once (&once, (GThreadFunc) register_gst_play_flags, &id);
+ return id;
+}
#define GST_TYPE_AUTOPLUG_SELECT_RESULT (gst_autoplug_select_result_get_type())
GType gst_autoplug_select_result_get_type (void);
+/**
+ * GstPlayFlags:
+ * @GST_PLAY_FLAG_VIDEO: Enable rendering of the video stream
+ * @GST_PLAY_FLAG_AUDIO: Enable rendering of the audio stream
+ * @GST_PLAY_FLAG_TEXT: Enable rendering of subtitles
+ * @GST_PLAY_FLAG_VIS: Enable rendering of visualisations when there is
+ * no video stream.
+ * @GST_PLAY_FLAG_SOFT_VOLUME: Use software volume
+ * @GST_PLAY_FLAG_NATIVE_AUDIO: only allow native audio formats, this omits
+ * configuration of audioconvert and audioresample.
+ * @GST_PLAY_FLAG_NATIVE_VIDEO: only allow native video formats, this omits
+ * configuration of ffmpegcolorspace and videoscale.
+ *
+ * Extra flags to configure the behaviour of the sinks.
+ */
+typedef enum {
+ GST_PLAY_FLAG_VIDEO = (1 << 0),
+ GST_PLAY_FLAG_AUDIO = (1 << 1),
+ GST_PLAY_FLAG_TEXT = (1 << 2),
+ GST_PLAY_FLAG_VIS = (1 << 3),
+ GST_PLAY_FLAG_SOFT_VOLUME = (1 << 4),
+ GST_PLAY_FLAG_NATIVE_AUDIO = (1 << 5),
+ GST_PLAY_FLAG_NATIVE_VIDEO = (1 << 6)
+} GstPlayFlags;
+
+#define GST_TYPE_PLAY_FLAGS (gst_play_flags_get_type())
+GType gst_play_flags_get_type (void);
+
G_END_DECLS
#endif /* __GST_PLAY_ENUM_H__ */
#define GST_IS_PLAY_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PLAY_BIN))
#define VOLUME_MAX_DOUBLE 10.0
-#define CONNECTION_SPEED_DEFAULT 0
typedef struct _GstPlayBin GstPlayBin;
typedef struct _GstPlayBinClass GstPlayBinClass;
{
const gchar *media; /* the media type of the selector */
GstPlaySinkType type; /* the sink pad type of the selector */
- GstPlaySinkMode mode; /* the sink pad mode of the selector */
GstElement *selector; /* the selector */
gint current; /* the currently selected stream */
};
/* props */
+#define DEFAULT_URI NULL
+#define DEFAULT_SUBURI NULL
+#define DEFAULT_STREAMINFO NULL
+#define DEFAULT_SOURCE NULL
+#define DEFAULT_FLAGS GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_TEXT | \
+ GST_PLAY_FLAG_SOFT_VOLUME
+#define DEFAULT_N_VIDEO 0
+#define DEFAULT_CURRENT_VIDEO -1
+#define DEFAULT_N_AUDIO 0
+#define DEFAULT_CURRENT_AUDIO -1
+#define DEFAULT_N_TEXT 0
+#define DEFAULT_CURRENT_TEXT -1
+#define DEFAULT_SUBTITLE_ENCODING NULL
+#define DEFAULT_AUDIO_SINK NULL
+#define DEFAULT_VIDEO_SINK NULL
+#define DEFAULT_VIS_PLUGIN NULL
+#define DEFAULT_VOLUME 1.0
+#define DEFAULT_FRAME NULL
+#define DEFAULT_FONT_DESC NULL
+#define DEFAULT_CONNECTION_SPEED 0
+
enum
{
PROP_0,
PROP_SUBURI,
PROP_STREAMINFO,
PROP_SOURCE,
+ PROP_FLAGS,
+ PROP_N_VIDEO,
PROP_CURRENT_VIDEO,
+ PROP_N_AUDIO,
PROP_CURRENT_AUDIO,
+ PROP_N_TEXT,
PROP_CURRENT_TEXT,
PROP_SUBTITLE_ENCODING,
PROP_AUDIO_SINK,
gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_play_bin_finalize);
+ /**
+ * GstPlayBin:uri
+ *
+ * Set the next URI that playbin will play. This property can be set from the
+ * about-to-finish signal to queue the next media file.
+ */
g_object_class_install_property (gobject_klass, PROP_URI,
g_param_spec_string ("uri", "URI", "URI of the media to play",
NULL, G_PARAM_READWRITE));
+
+ /**
+ * GstPlayBin:suburi
+ *
+ * Set the next subtitle URI that playbin will play. This property can be
+ * set from the about-to-finish signal to queue the next subtitle media file.
+ */
g_object_class_install_property (gobject_klass, PROP_SUBURI,
g_param_spec_string ("suburi", ".sub-URI", "Optional URI of a subtitle",
NULL, G_PARAM_READWRITE));
g_param_spec_object ("source", "Source", "Source element",
GST_TYPE_ELEMENT, G_PARAM_READABLE));
+ g_object_class_install_property (gobject_klass, PROP_FLAGS,
+ g_param_spec_flags ("flags", "Flags", "Flags to control behaviour",
+ GST_TYPE_PLAY_FLAGS, DEFAULT_FLAGS, G_PARAM_READWRITE));
+
+ /**
+ * GstPlayBin:n-video
+ *
+ * Get the total number of available video streams.
+ */
+ g_object_class_install_property (gobject_klass, PROP_N_VIDEO,
+ g_param_spec_int ("n-video", "Number Video",
+ "Total number of video streams", 0, G_MAXINT, 0, G_PARAM_READABLE));
+ /**
+ * GstPlayBin:current-video
+ *
+ * Get or set the currently playing video stream. By default the first video
+ * stream with data is played.
+ *
+ * Setting this property to -2 will disable the video stream.
+ */
g_object_class_install_property (gobject_klass, PROP_CURRENT_VIDEO,
- g_param_spec_int ("current-video", "Current video",
- "Currently playing video stream (-1 = none)",
- -1, G_MAXINT, -1, G_PARAM_READWRITE));
+ g_param_spec_int ("current-video", "Current Video",
+ "Currently playing video stream (-1 = auto, -2 = none)",
+ -2, G_MAXINT, -1, G_PARAM_READWRITE));
+ /**
+ * GstPlayBin:n-audio
+ *
+ * Get the total number of available audio streams.
+ */
+ g_object_class_install_property (gobject_klass, PROP_N_AUDIO,
+ g_param_spec_int ("n-audio", "Number Audio",
+ "Total number of audio streams", 0, G_MAXINT, 0, G_PARAM_READABLE));
+ /**
+ * GstPlayBin:current-audio
+ *
+ * Get or set the currently playing audio stream. By default the first audio
+ * stream with data is played.
+ *
+ * Setting this property to -2 will disable the audio stream.
+ */
g_object_class_install_property (gobject_klass, PROP_CURRENT_AUDIO,
g_param_spec_int ("current-audio", "Current audio",
- "Currently playing audio stream (-1 = none)",
- -1, G_MAXINT, -1, G_PARAM_READWRITE));
+ "Currently playing audio stream (-1 = none, -2 = none)",
+ -2, G_MAXINT, -1, G_PARAM_READWRITE));
+ /**
+ * GstPlayBin:n-text
+ *
+ * Get the total number of available subtitle streams.
+ */
+ g_object_class_install_property (gobject_klass, PROP_N_TEXT,
+ g_param_spec_int ("n-text", "Number Text",
+ "Total number of text streams", 0, G_MAXINT, 0, G_PARAM_READABLE));
+ /**
+ * GstPlayBin:current-text
+ *
+ * Get or set the currently playing subtitle stream. By default the first audio
+ * stream with data is played.
+ *
+ * Setting this property to -2 will disable the text stream.
+ */
g_object_class_install_property (gobject_klass, PROP_CURRENT_TEXT,
- g_param_spec_int ("current-text", "Current text",
- "Currently playing text stream (-1 = none)",
- -1, G_MAXINT, -1, G_PARAM_READWRITE));
+ g_param_spec_int ("current-text", "Current Text",
+ "Currently playing text stream (-1 = none, -2 = none)",
+ -2, G_MAXINT, -1, G_PARAM_READWRITE));
g_object_class_install_property (gobject_klass, PROP_SUBTITLE_ENCODING,
g_param_spec_string ("subtitle-encoding", "subtitle encoding",
g_param_spec_object ("vis-plugin", "Vis plugin",
"the visualization element to use (NULL = none)",
GST_TYPE_ELEMENT, G_PARAM_READWRITE));
+
g_object_class_install_property (gobject_klass, PROP_VOLUME,
g_param_spec_double ("volume", "volume", "volume",
0.0, VOLUME_MAX_DOUBLE, 1.0, G_PARAM_READWRITE));
g_object_class_install_property (gobject_klass, PROP_CONNECTION_SPEED,
g_param_spec_uint ("connection-speed", "Connection Speed",
"Network connection speed in kbps (0 = unknown)",
- 0, G_MAXUINT, CONNECTION_SPEED_DEFAULT, G_PARAM_READWRITE));
+ 0, G_MAXUINT, DEFAULT_CONNECTION_SPEED, G_PARAM_READWRITE));
/**
* GstPlayBin::about-to-finish:
*
group->playbin = playbin;
group->selector[0].media = "audio/x-raw-";
group->selector[0].type = GST_PLAY_SINK_TYPE_AUDIO_RAW;
- group->selector[0].mode = GST_PLAY_SINK_MODE_AUDIO;
group->selector[1].media = "audio/";
group->selector[1].type = GST_PLAY_SINK_TYPE_AUDIO;
- group->selector[1].mode = GST_PLAY_SINK_MODE_AUDIO;
group->selector[2].media = "video/x-raw-";
group->selector[2].type = GST_PLAY_SINK_TYPE_VIDEO_RAW;
- group->selector[2].mode = GST_PLAY_SINK_MODE_VIDEO;
group->selector[3].media = "video/";
group->selector[3].type = GST_PLAY_SINK_TYPE_VIDEO;
- group->selector[3].mode = GST_PLAY_SINK_MODE_VIDEO;
group->selector[4].media = "text/";
group->selector[4].type = GST_PLAY_SINK_TYPE_TEXT;
- group->selector[4].mode = GST_PLAY_SINK_MODE_TEXT;
}
static void
playbin->elements = gst_factory_list_get_elements (type);
gst_factory_list_debug (playbin->elements);
+ /* add sink */
+ playbin->playsink = g_object_new (GST_TYPE_PLAY_SINK, NULL);
+ gst_bin_add (GST_BIN_CAST (playbin), GST_ELEMENT_CAST (playbin->playsink));
+ gst_play_sink_set_flags (playbin->playsink, DEFAULT_FLAGS);
+
/* get the caps */
}
case PROP_SUBURI:
gst_play_bin_set_suburi (playbin, g_value_get_string (value));
break;
+ case PROP_FLAGS:
+ gst_play_sink_set_flags (playbin->playsink, g_value_get_flags (value));
+ break;
+ case PROP_CURRENT_VIDEO:
+ break;
+ case PROP_CURRENT_AUDIO:
+ break;
+ case PROP_CURRENT_TEXT:
+ break;
+ case PROP_SUBTITLE_ENCODING:
+ break;
case PROP_VIDEO_SINK:
break;
case PROP_AUDIO_SINK:
g_value_set_string (value, playbin->next_group->suburi);
GST_OBJECT_UNLOCK (playbin);
break;
+ case PROP_STREAMINFO:
+ break;
+ case PROP_SOURCE:
+ break;
+ case PROP_FLAGS:
+ g_value_set_flags (value, gst_play_sink_get_flags (playbin->playsink));
+ break;
+ case PROP_N_VIDEO:
+ break;
+ case PROP_CURRENT_VIDEO:
+ break;
+ case PROP_N_AUDIO:
+ break;
+ case PROP_CURRENT_AUDIO:
+ break;
+ case PROP_N_TEXT:
+ break;
+ case PROP_CURRENT_TEXT:
+ break;
+ case PROP_SUBTITLE_ENCODING:
+ break;
case PROP_VIDEO_SINK:
break;
case PROP_AUDIO_SINK:
break;
case PROP_FRAME:
break;
+ case PROP_FONT_DESC:
+ break;
case PROP_CONNECTION_SPEED:
GST_OBJECT_LOCK (playbin);
g_value_set_uint (value, playbin->connection_speed / 1000);
no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group)
{
GstPlayBin *playbin;
- GstPlaySinkMode mode = 0;
GstPadLinkReturn res;
gint i;
select->sinkpad =
gst_play_sink_request_pad (playbin->playsink, select->type);
res = gst_pad_link (select->srcpad, select->sinkpad);
- GST_DEBUG_OBJECT (playbin, "linking type %s: %d", select->media, res);
- mode |= select->mode;
+ GST_DEBUG_OBJECT (playbin, "linked type %s: %d", select->media, res);
}
}
/* configure the modes now */
- gst_play_sink_set_mode (playbin->playsink, mode);
+ gst_play_sink_reconfigure (playbin->playsink);
}
/* send an EOS event to all of the selectors */
switch (transition) {
case GST_STATE_CHANGE_READY_TO_PAUSED:
- if (playbin->playsink == NULL) {
- playbin->playsink = g_object_new (GST_TYPE_PLAY_SINK, NULL);
- gst_bin_add (GST_BIN_CAST (playbin),
- GST_ELEMENT_CAST (playbin->playsink));
- }
if (!setup_next_source (playbin))
goto source_failed;
break;
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
save_current_group (playbin);
- if (playbin->playsink) {
- gst_element_set_state (GST_ELEMENT_CAST (playbin->playsink),
- GST_STATE_NULL);
- gst_bin_remove (GST_BIN_CAST (playbin),
- GST_ELEMENT_CAST (playbin->playsink));
- playbin->playsink = NULL;
- }
break;
default:
break;
typedef struct
{
GstPlayChain chain;
+ GstElement *tee;
+ GstPad *teesrc;
GstElement *conv;
GstElement *resample;
GstElement *volume;
GstElement *sink;
} GstPlayVideoChain;
+typedef struct
+{
+ GstPlayChain chain;
+ GstPad *teesrc;
+ GstElement *queue;
+ GstElement *conv;
+ GstElement *resample;
+ GstElement *vis;
+ GstPad *srcpad;
+} GstPlayVisChain;
+
#define GST_PLAY_SINK_GET_LOCK(playsink) (((GstPlaySink *)playsink)->lock)
#define GST_PLAY_SINK_LOCK(playsink) g_mutex_lock (GST_PLAY_SINK_GET_LOCK (playsink))
#define GST_PLAY_SINK_UNLOCK(playsink) g_mutex_unlock (GST_PLAY_SINK_GET_LOCK (playsink))
GMutex *lock;
- GstPlaySinkMode mode;
- GstPlaySinkFlags flags;
+ GstPlayFlags flags;
GstPlayChain *audiochain;
GstPlayChain *videochain;
+ GstPlayChain *vischain;
GstPad *audio_pad;
gboolean audio_pad_raw;
playsink->textoverlay_element = NULL;
playsink->volume = 1.0;
playsink->font_desc = NULL;
- playsink->flags = GST_PLAY_SINK_FLAG_SOFT_VOLUME;
+ playsink->flags = GST_PLAY_FLAG_SOFT_VOLUME;
playsink->lock = g_mutex_new ();
}
/* make the chain that contains the elements needed to perform
* audio playback.
*
- * +-------------------------------------------------------------+
- * | abin |
- * | +---------+ +----------+ +---------+ +---------+ |
- * | |audioconv| |audioscale| | volume | |audiosink| |
- * | +-sink src-sink src-sink src-sink | |
- * | | +---------+ +----------+ +---------+ +---------+ |
- * sink-+ |
- * +-------------------------------------------------------------+
+ * We add a tee as the first element so that we can link the visualisation chain
+ * to it when requested.
+ *
+ * +-----------------------------------------------------------------------+
+ * | abin |
+ * | +-----+ +---------+ +----------+ +---------+ +---------+ |
+ * | | tee | |audioconv| |audioscale| | volume | |audiosink| |
+ * | +-sink src-sink src-sink src-sink src-sink | |
+ * | | +-----+ +---------+ +----------+ +---------+ +---------+ |
+ * sink-+ |
+ * +-----------------------------------------------------------------------+
*/
static GstPlayChain *
gen_audio_chain (GstPlaySink * playsink, gboolean raw)
gst_bin_add (bin, chain->sink);
if (raw) {
+ chain->tee = gst_element_factory_make ("tee", "atee");
+ gst_bin_add (bin, chain->tee);
+
chain->conv = gst_element_factory_make ("audioconvert", "aconv");
if (chain->conv == NULL)
goto no_audioconvert;
goto no_audioresample;
gst_bin_add (bin, chain->resample);
+ chain->teesrc = gst_element_get_request_pad (chain->tee, "src%d");
+ pad = gst_element_get_pad (chain->conv, "sink");
+ gst_pad_link (chain->teesrc, pad);
+ gst_object_unref (pad);
+
res = gst_element_link_pads (chain->conv, "src", chain->resample, "sink");
- if (playsink->flags & GST_PLAY_SINK_FLAG_SOFT_VOLUME) {
+ if (playsink->flags & GST_PLAY_FLAG_SOFT_VOLUME) {
chain->volume = gst_element_factory_make ("volume", "volume");
g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, NULL);
gst_bin_add (bin, chain->volume);
if (!res)
goto link_failed;
- pad = gst_element_get_pad (chain->conv, "sink");
+ pad = gst_element_get_pad (chain->tee, "sink");
} else {
pad = gst_element_get_pad (chain->sink, "sink");
}
}
}
-#if 0
-/* make the element (bin) that contains the elements needed to perform
- * visualisation ouput. The idea is to split the audio using tee, then
- * sending the output to the regular audio bin and the other output to
- * the vis plugin that transforms it into a video that is rendered with the
- * normal video bin. The video and audio bins are run in threads to make sure
- * they don't block eachother.
- *
- * +-----------------------------------------------------------------------+
- * | visbin |
- * | +------+ +--------+ +----------------+ |
- * | | tee | | aqueue | | abin ... | |
- * | +-sink src-sink src-sink | |
- * | | | | +--------+ +----------------+ |
- * | | | | |
- * | | | | +------+ +------------+ +------+ +-----------+ |
- * | | | | |vqueue| | audioconv | | vis | | vbin ... | |
- * | | | src-sink src-sink + samp src-sink src-sink | |
- * | | | | +------+ +------------+ +------+ +-----------+ |
- * | | | | |
- * | | +------+ |
- * sink-+ |
- * +-----------------------------------------------------------------------+
+/*
+ * +--------------------------------------------------+
+ * | visbin |
+ * | +--------+ +------------+ +-------+ |
+ * | | vqueue | | audioconv | | vis | |
+ * | +-sink src-sink + samp src-sink src-+ |
+ * | | +--------+ +------------+ +-------+ | |
+ * sink-+ +-src
+ * +--------------------------------------------------+
+ *
*/
-static GstElement *
-gen_vis_element (GstPlaySink * playsink)
+#if 0
+static GstPlayChain *
+gen_vis_chain (GstPlaySink * playsink)
{
+ GstPlayVisChain *chain;
+ GstBin *bin;
gboolean res;
- GstElement *element;
- GstElement *tee;
- GstElement *asink;
- GstElement *vsink;
- GstElement *conv;
- GstElement *resamp;
- GstElement *conv2;
- GstElement *vis;
- GstElement *vqueue, *aqueue;
- GstPad *pad, *rpad;
-
- /* errors are already posted when these fail. */
- asink = gen_audio_element (playsink);
- if (!asink)
- return NULL;
- vsink = gen_video_element (playsink);
- if (!vsink) {
- gst_object_unref (asink);
- return NULL;
- }
+ GstPad *pad;
- element = gst_bin_new ("visbin");
- tee = gst_element_factory_make ("tee", "tee");
+ chain = g_new0 (GstPlayVisChain, 1);
+ chain->chain.playsink = gst_object_ref (playsink);
- vqueue = gst_element_factory_make ("queue", "vqueue");
- aqueue = gst_element_factory_make ("queue", "aqueue");
+ chain->chain.bin = gst_bin_new ("abin");
+ bin = GST_BIN_CAST (chain->chain.bin);
+ gst_object_ref (bin);
+ gst_object_sink (bin);
- gst_bin_add (GST_BIN_CAST (element), asink);
- gst_bin_add (GST_BIN_CAST (element), vqueue);
- gst_bin_add (GST_BIN_CAST (element), aqueue);
- gst_bin_add (GST_BIN_CAST (element), vsink);
- gst_bin_add (GST_BIN_CAST (element), tee);
+ chain->queue = gst_element_factory_make ("queue", "visqueue");
+ gst_bin_add (bin, chain->queue);
- conv = gst_element_factory_make ("audioconvert", "aconv");
- if (conv == NULL)
+ chain->conv = gst_element_factory_make ("audioconvert", "aconv");
+ if (chain->conv == NULL)
goto no_audioconvert;
- gst_bin_add (GST_BIN_CAST (element), conv);
+ gst_bin_add (bin, chain->conv);
- resamp = gst_element_factory_make ("audioresample", "aresamp");
- if (resamp == NULL)
+ chain->resample = gst_element_factory_make ("audioresample", "aresample");
+ if (chain->resample == NULL)
goto no_audioresample;
- gst_bin_add (GST_BIN_CAST (element), resamp);
-
- conv2 = gst_element_factory_make ("audioconvert", "aconv2");
- if (conv2 == NULL)
- goto no_audioconvert;
- gst_bin_add (GST_BIN_CAST (element), conv2);
+ gst_bin_add (bin, chain->resample);
if (playsink->visualisation) {
- gst_object_ref (playsink->visualisation);
- vis = playsink->visualisation;
+ chain->vis = playsink->visualisation;
} else {
- vis = gst_element_factory_make ("goom", "vis");
- if (!vis)
+ chain->vis = gst_element_factory_make ("goom", "vis");
+ if (!chain->vis)
goto no_goom;
}
- gst_bin_add (GST_BIN_CAST (element), vis);
+ gst_bin_add (bin, chain->vis);
- res = gst_element_link_pads (vqueue, "src", conv, "sink");
- res &= gst_element_link_pads (conv, "src", resamp, "sink");
- res &= gst_element_link_pads (resamp, "src", conv2, "sink");
- res &= gst_element_link_pads (conv2, "src", vis, "sink");
- res &= gst_element_link_pads (vis, "src", vsink, "sink");
+ res = gst_element_link_pads (chain->queue, "src", chain->conv, "sink");
+ res &= gst_element_link_pads (chain->conv, "src", chain->resample, "sink");
+ res &= gst_element_link_pads (chain->resample, "src", chain->vis, "sink");
if (!res)
goto link_failed;
- pad = gst_element_get_pad (aqueue, "sink");
- rpad = gst_element_get_request_pad (tee, "src%d");
- gst_pad_link (rpad, pad);
- gst_object_unref (rpad);
- gst_object_unref (pad);
- gst_element_link_pads (aqueue, "src", asink, "sink");
-
- pad = gst_element_get_pad (vqueue, "sink");
- rpad = gst_element_get_request_pad (tee, "src%d");
- gst_pad_link (rpad, pad);
- gst_object_unref (rpad);
+ pad = gst_element_get_pad (chain->queue, "sink");
+ chain->chain.sinkpad = gst_ghost_pad_new ("sink", pad);
gst_object_unref (pad);
+ gst_element_add_pad (chain->chain.bin, chain->chain.sinkpad);
- pad = gst_element_get_pad (tee, "sink");
- gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad));
+ pad = gst_element_get_pad (chain->vis, "src");
+ chain->srcpad = gst_ghost_pad_new ("src", pad);
gst_object_unref (pad);
+ gst_element_add_pad (chain->chain.bin, chain->srcpad);
- return element;
+ return (GstPlayChain *) chain;
/* ERRORS */
no_audioconvert:
GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
(_("Missing element '%s' - check your GStreamer installation."),
"audioconvert"), ("possibly a liboil version mismatch?"));
- gst_object_unref (element);
+ free_chain ((GstPlayChain *) chain);
return NULL;
}
no_audioresample:
GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
(_("Missing element '%s' - check your GStreamer installation."),
"audioresample"), (NULL));
- gst_object_unref (element);
+ free_chain ((GstPlayChain *) chain);
return NULL;
}
no_goom:
GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN,
(_("Missing element '%s' - check your GStreamer installation."),
"goom"), (NULL));
- gst_object_unref (element);
+ free_chain ((GstPlayChain *) chain);
return NULL;
}
link_failed:
{
GST_ELEMENT_ERROR (playsink, CORE, PAD,
(NULL), ("Failed to configure the visualisation element."));
- gst_object_unref (element);
+ free_chain ((GstPlayChain *) chain);
return NULL;
}
}
#endif
-GstPlaySinkMode
-gst_play_sink_get_mode (GstPlaySink * playsink)
+#if 0
+static gboolean
+activate_vis (GstPlaySink * playsink, gboolean activate)
{
- GstPlaySinkMode res;
+ /* need to have an audio chain */
+ if (!playsink->audiochain || !playsink->vischain)
+ return FALSE;
- GST_PLAY_SINK_LOCK (playsink);
- res = playsink->mode;
- GST_PLAY_SINK_UNLOCK (playsink);
+ if (playsink->vischain->activated == activate)
+ return TRUE;
- return res;
+ if (activate) {
+ /* activation: Add the vis chain to the sink bin . Take a new srcpad from
+ * the tee of the audio chain and link it to the sinkpad of the vis chain.
+ */
+
+ } else {
+ /* deactivation: release the srcpad from the tee of the audio chain. Set the
+ * vis chain to NULL and remove it from the sink bin */
+
+ }
+ return TRUE;
}
+#endif
/* this function is called when all the request pads are requested and when we
* have to construct the final pipeline.
*/
gboolean
-gst_play_sink_set_mode (GstPlaySink * playsink, GstPlaySinkMode mode)
+gst_play_sink_reconfigure (GstPlaySink * playsink)
{
- GST_DEBUG_OBJECT (playsink, "setting mode to %d", mode);
+ GstPlayFlags flags;
+
+ GST_DEBUG_OBJECT (playsink, "reconfiguring");
GST_PLAY_SINK_LOCK (playsink);
- if (mode & GST_PLAY_SINK_MODE_AUDIO && playsink->audio_pad) {
+ GST_OBJECT_LOCK (playsink);
+ flags = playsink->flags;
+ GST_OBJECT_UNLOCK (playsink);
+
+ if (flags & GST_PLAY_FLAG_AUDIO && playsink->audio_pad) {
if (!playsink->audiochain)
playsink->audiochain =
gen_audio_chain (playsink, playsink->audio_pad_raw);
gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->audio_pad), NULL);
}
- if (mode & GST_PLAY_SINK_MODE_VIDEO && playsink->video_pad) {
+ if (flags & GST_PLAY_FLAG_VIDEO && playsink->video_pad) {
if (!playsink->videochain)
playsink->videochain =
gen_video_chain (playsink, playsink->video_pad_raw);
if (playsink->video_pad)
gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->video_pad), NULL);
}
-
- playsink->mode = mode;
GST_PLAY_SINK_UNLOCK (playsink);
return TRUE;
}
gboolean
-gst_play_sink_set_flags (GstPlaySink * playsink, GstPlaySinkFlags flags)
+gst_play_sink_set_flags (GstPlaySink * playsink, GstPlayFlags flags)
{
g_return_val_if_fail (GST_IS_PLAY_SINK (playsink), FALSE);
GST_OBJECT_LOCK (playsink);
playsink->flags = flags;
- GST_OBJECT_LOCK (playsink);
+ GST_OBJECT_UNLOCK (playsink);
return TRUE;
}
-GstPlaySinkFlags
+GstPlayFlags
gst_play_sink_get_flags (GstPlaySink * playsink)
{
- GstPlaySinkFlags res;
+ GstPlayFlags res;
g_return_val_if_fail (GST_IS_PLAY_SINK (playsink), 0);
GST_OBJECT_LOCK (playsink);
res = playsink->flags;
- GST_OBJECT_LOCK (playsink);
+ GST_OBJECT_UNLOCK (playsink);
return res;
}
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
/* remove sinks we added */
+ if (playsink->videochain) {
+ activate_chain (playsink->videochain, FALSE);
+ add_chain (playsink->videochain, FALSE);
+ }
+ if (playsink->audiochain) {
+ activate_chain (playsink->audiochain, FALSE);
+ add_chain (playsink->audiochain, FALSE);
+ }
break;
default:
break;
#include <gst/gst.h>
+#include "gstplay-enum.h"
+
G_BEGIN_DECLS
#define GST_TYPE_PLAY_SINK \
(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PLAY_SINK))
/**
- * GstPlaySinkMode:
- * @GST_PLAY_SINK_MODE_VIDEO:
- * @GST_PLAY_SINK_MODE_AUDIO:
- * @GST_PLAY_SINK_MODE_TEXT:
- * @GST_PLAY_SINK_MODE_VIS:
- *
- * Features to enable in the sink.
- */
-typedef enum {
- GST_PLAY_SINK_MODE_VIDEO = (1 << 0),
- GST_PLAY_SINK_MODE_AUDIO = (1 << 1),
- GST_PLAY_SINK_MODE_TEXT = (1 << 2),
- GST_PLAY_SINK_MODE_VIS = (1 << 3)
-} GstPlaySinkMode;
-
-/**
* GstPlaySinkType:
* @GST_PLAY_SINK_TYPE_AUDIO: A non-raw audio pad
* @GST_PLAY_SINK_TYPE_AUDIO_RAW: a raw audio pad
GST_PLAY_SINK_TYPE_LAST = 5
} GstPlaySinkType;
-/**
- * GstPlaySinkFlags:
- * @GST_PLAY_SINK_FLAG_SOFT_VOLUME: Use software volume in the sink
- * @GST_PLAY_SINK_FLAG_NATIVE_AUDIO: only allow native audio formats, this omits
- * configuration of audioconvert and audioresample.
- * @GST_PLAY_SINK_FLAG_NATIVE_VIDEO: only allow native video formats, this omits
- * configuration of ffmpegcolorspace and videoscale.
- *
- * Extra flags to configure the behaviour of the sinks.
- */
-typedef enum {
- GST_PLAY_SINK_FLAG_SOFT_VOLUME = (1 << 0),
- GST_PLAY_SINK_FLAG_NATIVE_AUDIO = (1 << 1),
- GST_PLAY_SINK_FLAG_NATIVE_VIDEO = (1 << 2)
-} GstPlaySinkFlags;
-
typedef struct _GstPlaySink GstPlaySink;
typedef struct _GstPlaySinkClass GstPlaySinkClass;
void gst_play_sink_set_audio_sink (GstPlaySink * playsink, GstElement * sink);
void gst_play_sink_set_vis_plugin (GstPlaySink * playsink, GstElement * vis);
-gboolean gst_play_sink_set_flags (GstPlaySink * playsink, GstPlaySinkFlags flags);
-GstPlaySinkFlags gst_play_sink_get_flags (GstPlaySink * playsink);
+gboolean gst_play_sink_set_flags (GstPlaySink * playsink, GstPlayFlags flags);
+GstPlayFlags gst_play_sink_get_flags (GstPlaySink * playsink);
-gboolean gst_play_sink_set_mode (GstPlaySink *playsink, GstPlaySinkMode mode);
-GstPlaySinkMode gst_play_sink_get_mode (GstPlaySink *playsink);
+gboolean gst_play_sink_reconfigure (GstPlaySink * playsink);
G_END_DECLS