From 9c9f60777aa259e7d2e920b23fb67c23ada7078c Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 7 Jan 2008 11:40:04 +0000 Subject: [PATCH] gst/playback/gstplay-enum.*: Add enums for configuration flags. Original commit message from CVS: * 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. --- ChangeLog | 31 ++++++ gst/playback/gstplay-enum.c | 30 ++++++ gst/playback/gstplay-enum.h | 28 +++++ gst/playback/gstplaybin2.c | 173 ++++++++++++++++++++++++------ gst/playback/gstplaysink.c | 252 ++++++++++++++++++++++---------------------- gst/playback/gstplaysink.h | 41 +------ 6 files changed, 363 insertions(+), 192 deletions(-) diff --git a/ChangeLog b/ChangeLog index 449a09b..ad2e526 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,34 @@ +2008-01-07 Wim Taymans + + * 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 * tests/check/pipelines/theoraenc.c: (check_buffer_is_header), diff --git a/gst/playback/gstplay-enum.c b/gst/playback/gstplay-enum.c index c10f092..fcd650f 100644 --- a/gst/playback/gstplay-enum.c +++ b/gst/playback/gstplay-enum.c @@ -20,6 +20,7 @@ #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) @@ -43,3 +44,32 @@ gst_autoplug_select_result_get_type (void) 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; +} diff --git a/gst/playback/gstplay-enum.h b/gst/playback/gstplay-enum.h index ac8c3c7..dabde5c 100644 --- a/gst/playback/gstplay-enum.h +++ b/gst/playback/gstplay-enum.h @@ -41,6 +41,34 @@ typedef enum { #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__ */ diff --git a/gst/playback/gstplaybin2.c b/gst/playback/gstplaybin2.c index ff374cc..97987e5 100644 --- a/gst/playback/gstplaybin2.c +++ b/gst/playback/gstplaybin2.c @@ -264,7 +264,6 @@ GST_DEBUG_CATEGORY_STATIC (gst_play_bin_debug); #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; @@ -276,7 +275,6 @@ struct _GstSourceSelect { 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 */ @@ -336,6 +334,27 @@ struct _GstPlayBinClass }; /* 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, @@ -343,8 +362,12 @@ enum 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, @@ -433,9 +456,22 @@ gst_play_bin_class_init (GstPlayBinClass * klass) 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)); @@ -450,18 +486,70 @@ gst_play_bin_class_init (GstPlayBinClass * klass) 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", @@ -482,6 +570,7 @@ gst_play_bin_class_init (GstPlayBinClass * klass) 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)); @@ -498,7 +587,7 @@ gst_play_bin_class_init (GstPlayBinClass * klass) 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: * @@ -527,19 +616,14 @@ init_group (GstPlayBin * playbin, GstSourceGroup * group) 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 @@ -558,6 +642,11 @@ gst_play_bin_init (GstPlayBin * playbin) 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 */ } @@ -632,6 +721,17 @@ gst_play_bin_set_property (GObject * object, guint prop_id, 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: @@ -681,6 +781,27 @@ gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value, 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: @@ -691,6 +812,8 @@ gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value, 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); @@ -881,7 +1004,6 @@ static void no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group) { GstPlayBin *playbin; - GstPlaySinkMode mode = 0; GstPadLinkReturn res; gint i; @@ -896,12 +1018,11 @@ no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group) 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 */ @@ -1214,11 +1335,6 @@ gst_play_bin_change_state (GstElement * element, GstStateChange transition) 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; @@ -1238,13 +1354,6 @@ gst_play_bin_change_state (GstElement * element, GstStateChange transition) 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; diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c index 2179855..105233f 100644 --- a/gst/playback/gstplaysink.c +++ b/gst/playback/gstplaysink.c @@ -49,6 +49,8 @@ typedef struct typedef struct { GstPlayChain chain; + GstElement *tee; + GstPad *teesrc; GstElement *conv; GstElement *resample; GstElement *volume; @@ -64,6 +66,17 @@ typedef struct 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)) @@ -74,11 +87,11 @@ struct _GstPlaySink GMutex *lock; - GstPlaySinkMode mode; - GstPlaySinkFlags flags; + GstPlayFlags flags; GstPlayChain *audiochain; GstPlayChain *videochain; + GstPlayChain *vischain; GstPad *audio_pad; gboolean audio_pad_raw; @@ -241,7 +254,7 @@ gst_play_sink_init (GstPlaySink * playsink) 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 (); } @@ -841,14 +854,17 @@ no_overlay: /* 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) @@ -878,6 +894,9 @@ 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; @@ -888,9 +907,14 @@ gen_audio_chain (GstPlaySink * playsink, gboolean raw) 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); @@ -904,7 +928,7 @@ gen_audio_chain (GstPlaySink * playsink, gboolean raw) 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"); } @@ -951,118 +975,73 @@ link_failed: } } -#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: @@ -1071,7 +1050,7 @@ 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: @@ -1080,7 +1059,7 @@ 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: @@ -1089,41 +1068,60 @@ 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); @@ -1140,7 +1138,7 @@ gst_play_sink_set_mode (GstPlaySink * playsink, GstPlaySinkMode mode) 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); @@ -1156,35 +1154,33 @@ gst_play_sink_set_mode (GstPlaySink * playsink, GstPlaySinkMode mode) 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; } @@ -1342,6 +1338,14 @@ gst_play_sink_change_state (GstElement * element, GstStateChange transition) 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; diff --git a/gst/playback/gstplaysink.h b/gst/playback/gstplaysink.h index 5c1f1e4..6373edd 100644 --- a/gst/playback/gstplaysink.h +++ b/gst/playback/gstplaysink.h @@ -22,6 +22,8 @@ #include +#include "gstplay-enum.h" + G_BEGIN_DECLS #define GST_TYPE_PLAY_SINK \ @@ -36,22 +38,6 @@ G_BEGIN_DECLS (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 @@ -71,22 +57,6 @@ typedef enum { 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; @@ -99,11 +69,10 @@ void gst_play_sink_set_video_sink (GstPlaySink * playsink, GstElemen 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 -- 2.7.4