2 * Copyright (C) <2007> Wim Taymans <wim.taymans@gmail.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * SECTION:element-playbin2
23 * Playbin2 provides a stand-alone everything-in-one abstraction for an
24 * audio and/or video player.
26 * At this stage, playbin2 is considered UNSTABLE. The API provided in the
27 * signals and properties may yet change in the near future. When playbin2
28 * is stable, it will probably replace #playbin
30 * It can handle both audio and video files and features
33 * automatic file type recognition and based on that automatic
34 * selection and usage of the right audio/video/subtitle demuxers/decoders
37 * visualisations for audio files
40 * subtitle support for video files. Subtitles can be store in external
44 * stream selection between different video/audio/subtitles streams
47 * meta info (tag) extraction
50 * easy access to the last video frame
53 * buffering when playing streams over a network
56 * volume control with mute option
61 * <title>Usage</title>
63 * A playbin element can be created just like any other element using
64 * gst_element_factory_make(). The file/URI to play should be set via the #GstPlayBin2:uri
65 * property. This must be an absolute URI, relative file paths are not allowed.
66 * Example URIs are file:///home/joe/movie.avi or http://www.joedoe.com/foo.ogg
68 * Playbin is a #GstPipeline. It will notify the application of everything
69 * that's happening (errors, end of stream, tags found, state changes, etc.)
70 * by posting messages on its #GstBus. The application needs to watch the
73 * Playback can be initiated by setting the element to PLAYING state using
74 * gst_element_set_state(). Note that the state change will take place in
75 * the background in a separate thread, when the function returns playback
76 * is probably not happening yet and any errors might not have occured yet.
77 * Applications using playbin should ideally be written to deal with things
78 * completely asynchroneous.
80 * When playback has finished (an EOS message has been received on the bus)
81 * or an error has occured (an ERROR message has been received on the bus) or
82 * the user wants to play a different track, playbin should be set back to
83 * READY or NULL state, then the #GstPlayBin2:uri property should be set to the
84 * new location and then playbin be set to PLAYING state again.
86 * Seeking can be done using gst_element_seek_simple() or gst_element_seek()
87 * on the playbin element. Again, the seek will not be executed
88 * instantaneously, but will be done in a background thread. When the seek
89 * call returns the seek will most likely still be in process. An application
90 * may wait for the seek to finish (or fail) using gst_element_get_state() with
91 * -1 as the timeout, but this will block the user interface and is not
94 * Applications may query the current position and duration of the stream
95 * via gst_element_query_position() and gst_element_query_duration() and
96 * setting the format passed to GST_FORMAT_TIME. If the query was successful,
97 * the duration or position will have been returned in units of nanoseconds.
101 * <title>Advanced Usage: specifying the audio and video sink</title>
103 * By default, if no audio sink or video sink has been specified via the
104 * #GstPlayBin2:audio-sink or #GstPlayBin2:video-sink property, playbin will use the autoaudiosink
105 * and autovideosink elements to find the first-best available output method.
106 * This should work in most cases, but is not always desirable. Often either
107 * the user or application might want to specify more explicitly what to use
108 * for audio and video output.
110 * If the application wants more control over how audio or video should be
111 * output, it may create the audio/video sink elements itself (for example
112 * using gst_element_factory_make()) and provide them to playbin using the
113 * #GstPlayBin2:audio-sink or #GstPlayBin2:video-sink property.
115 * GNOME-based applications, for example, will usually want to create
116 * gconfaudiosink and gconfvideosink elements and make playbin use those,
117 * so that output happens to whatever the user has configured in the GNOME
118 * Multimedia System Selector confinguration dialog.
120 * The sink elements do not necessarily need to be ready-made sinks. It is
121 * possible to create container elements that look like a sink to playbin,
122 * but in reality contain a number of custom elements linked together. This
123 * can be achieved by creating a #GstBin and putting elements in there and
124 * linking them, and then creating a sink #GstGhostPad for the bin and pointing
125 * it to the sink pad of the first element within the bin. This can be used
126 * for a number of purposes, for example to force output to a particular
127 * format or to modify or observe the data before it is output.
129 * It is also possible to 'suppress' audio and/or video output by using
130 * 'fakesink' elements (or capture it from there using the fakesink element's
131 * "handoff" signal, which, nota bene, is fired from the streaming thread!).
135 * <title>Retrieving Tags and Other Meta Data</title>
137 * Most of the common meta data (artist, title, etc.) can be retrieved by
138 * watching for TAG messages on the pipeline's bus (see above).
140 * Other more specific meta information like width/height/framerate of video
141 * streams or samplerate/number of channels of audio streams can be obtained
142 * from the negotiated caps on the sink pads of the sinks.
146 * <title>Buffering</title>
147 * Playbin handles buffering automatically for the most part, but applications
148 * need to handle parts of the buffering process as well. Whenever playbin is
149 * buffering, it will post BUFFERING messages on the bus with a percentage
150 * value that shows the progress of the buffering process. Applications need
151 * to set playbin to PLAYING or PAUSED state in response to these messages.
152 * They may also want to convey the buffering progress to the user in some
153 * way. Here is how to extract the percentage information from the message
154 * (requires GStreamer >= 0.10.11):
156 * switch (GST_MESSAGE_TYPE (msg)) {
157 * case GST_MESSAGE_BUFFERING: {
159 * gst_message_parse_buffering (msg, &percent);
160 * g_print ("Buffering (%%u percent done)", percent);
166 * Note that applications should keep/set the pipeline in the PAUSED state when
167 * a BUFFERING message is received with a buffer percent value < 100 and set
168 * the pipeline back to PLAYING state when a BUFFERING message with a value
169 * of 100 percent is received (if PLAYING is the desired state, that is).
172 * <title>Embedding the video window in your application</title>
173 * By default, playbin (or rather the video sinks used) will create their own
174 * window. Applications will usually want to force output to a window of their
175 * own, however. This can be done using the #GstXOverlay interface, which most
176 * video sinks implement. See the documentation there for more details.
179 * <title>Specifying which CD/DVD device to use</title>
180 * The device to use for CDs/DVDs needs to be set on the source element
181 * playbin creates before it is opened. The only way to do this at the moment
182 * is to connect to playbin's "notify::source" signal, which will be emitted
183 * by playbin when it has created the source element for a particular URI.
184 * In the signal callback you can check if the source element has a "device"
185 * property and set it appropriately. In future ways might be added to specify
186 * the device as part of the URI, but at the time of writing this is not
190 * <title>Examples</title>
192 * gst-launch -v playbin uri=file:///path/to/somefile.avi
193 * ]| This will play back the given AVI video file, given that the video and
194 * audio decoders required to decode the content are installed. Since no
195 * special audio sink or video sink is supplied (not possible via gst-launch),
196 * playbin will try to find a suitable audio and video sink automatically
197 * using the autoaudiosink and autovideosink elements.
199 * gst-launch -v playbin uri=cdda://4
200 * ]| This will play back track 4 on an audio CD in your disc drive (assuming
201 * the drive is detected automatically by the plugin).
203 * gst-launch -v playbin uri=dvd://1
204 * ]| This will play back title 1 of a DVD in your disc drive (assuming
205 * the drive is detected automatically by the plugin).
216 #include <gst/gst-i18n-plugin.h>
217 #include <gst/pbutils/pbutils.h>
219 #include "gstplay-enum.h"
220 #include "gstplay-marshal.h"
221 #include "gstplaysink.h"
222 #include "gstfactorylists.h"
223 #include "gstscreenshot.h"
225 GST_DEBUG_CATEGORY_STATIC (gst_play_bin_debug);
226 #define GST_CAT_DEFAULT gst_play_bin_debug
228 #define GST_TYPE_PLAY_BIN (gst_play_bin_get_type())
229 #define GST_PLAY_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PLAY_BIN,GstPlayBin))
230 #define GST_PLAY_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PLAY_BIN,GstPlayBinClass))
231 #define GST_IS_PLAY_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PLAY_BIN))
232 #define GST_IS_PLAY_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PLAY_BIN))
234 #define VOLUME_MAX_DOUBLE 10.0
236 typedef struct _GstPlayBin GstPlayBin;
237 typedef struct _GstPlayBinClass GstPlayBinClass;
238 typedef struct _GstSourceGroup GstSourceGroup;
239 typedef struct _GstSourceSelect GstSourceSelect;
241 /* has the info for a selector and provides the link to the sink */
242 struct _GstSourceSelect
244 const gchar *media; /* the media type of the selector */
245 GstPlaySinkType type; /* the sink pad type of the selector */
247 GstElement *selector; /* the selector */
249 GstPad *srcpad; /* the source pad of the selector */
250 GstPad *sinkpad; /* the sinkpad of the sink when the selector is linked */
253 #define GST_SOURCE_GROUP_GET_LOCK(group) (((GstSourceGroup*)(group))->lock)
254 #define GST_SOURCE_GROUP_GET_COND(group) (((GstSourceGroup*)(group))->cond)
255 #define GST_SOURCE_GROUP_LOCK(group) (g_mutex_lock (GST_SOURCE_GROUP_GET_LOCK(group)))
256 #define GST_SOURCE_GROUP_UNLOCK(group) (g_mutex_unlock (GST_SOURCE_GROUP_GET_LOCK(group)))
257 #define GST_SOURCE_GROUP_WAIT(group) (g_cond_wait \
258 (GST_SOURCE_GROUP_GET_COND (group),GST_SOURCE_GROUP_GET_LOCK(group)))
259 #define GST_SOURCE_GROUP_BROADCAST(group) (g_cond_broadcast \
260 (GST_SOURCE_GROUP_GET_COND (group)))
262 /* a structure to hold the objects for decoding a uri and the subtitle uri
264 struct _GstSourceGroup
271 gboolean valid; /* the group has valid info to start playback */
272 gboolean active; /* the group is active */
277 GValueArray *streaminfo;
280 GPtrArray *video_channels; /* links to selector pads */
281 GPtrArray *audio_channels; /* links to selector pads */
282 GPtrArray *text_channels; /* links to selector pads */
284 /* uridecodebins for uri and subtitle uri */
285 GstElement *uridecodebin;
286 GstElement *suburidecodebin;
290 gulong pad_removed_id;
291 gulong no_more_pads_id;
292 gulong notify_source_id;
294 gulong autoplug_factories_id;
295 gulong autoplug_select_id;
297 gulong sub_pad_added_id;
298 gulong sub_pad_removed_id;
299 gulong sub_no_more_pads_id;
301 /* selectors for different streams */
302 GstSourceSelect selector[GST_PLAY_SINK_TYPE_LAST];
305 #define GST_PLAY_BIN_GET_LOCK(bin) (((GstPlayBin*)(bin))->lock)
306 #define GST_PLAY_BIN_LOCK(bin) (g_mutex_lock (GST_PLAY_BIN_GET_LOCK(bin)))
307 #define GST_PLAY_BIN_UNLOCK(bin) (g_mutex_unlock (GST_PLAY_BIN_GET_LOCK(bin)))
309 /* lock to protect dynamic callbacks, like no-more-pads */
310 #define GST_PLAY_BIN_DYN_LOCK(bin) g_mutex_lock ((bin)->dyn_lock)
311 #define GST_PLAY_BIN_DYN_UNLOCK(bin) g_mutex_unlock ((bin)->dyn_lock)
313 /* lock for shutdown */
314 #define GST_PLAY_BIN_SHUTDOWN_LOCK(bin,label) \
316 if (G_UNLIKELY (g_atomic_int_get (&bin->shutdown))) \
318 GST_PLAY_BIN_DYN_LOCK (bin); \
319 if (G_UNLIKELY (g_atomic_int_get (&bin->shutdown))) { \
320 GST_PLAY_BIN_DYN_UNLOCK (bin); \
325 /* unlock for shutdown */
326 #define GST_PLAY_BIN_SHUTDOWN_UNLOCK(bin) \
327 GST_PLAY_BIN_DYN_UNLOCK (bin); \
332 * playbin element structure
338 GMutex *lock; /* to protect group switching */
340 /* the groups, we use a double buffer to switch between current and next */
341 GstSourceGroup groups[2]; /* array with group info */
342 GstSourceGroup *curr_group; /* pointer to the currently playing group */
343 GstSourceGroup *next_group; /* pointer to the next group */
345 gboolean about_to_finish; /* the about-to-finish signal is emitted */
348 guint connection_speed; /* connection speed in bits/sec (0 = unknown) */
349 gint current_video; /* the currently selected stream */
350 gint current_audio; /* the currently selected stream */
351 gint current_text; /* the currently selected stream */
352 gchar *encoding; /* subtitle encoding */
354 guint64 buffer_duration; /* When buffering, the max buffer duration (ns) */
355 guint buffer_size; /* When buffering, the max buffer size (bytes) */
358 GstPlaySink *playsink;
360 /* the last activated source */
363 /* lock protecting dynamic adding/removing */
365 /* if we are shutting down or not */
368 GValueArray *elements; /* factories we can use for selecting elements */
371 struct _GstPlayBinClass
373 GstPipelineClass parent_class;
375 /* notify app that the current uri finished decoding and it is possible to
376 * queue a new one for gapless playback */
377 void (*about_to_finish) (GstPlayBin * playbin);
379 /* notify app that number of audio/video/text streams changed */
380 void (*video_changed) (GstPlayBin * playbin);
381 void (*audio_changed) (GstPlayBin * playbin);
382 void (*text_changed) (GstPlayBin * playbin);
384 /* get audio/video/text tags for a stream */
385 GstTagList *(*get_video_tags) (GstPlayBin * playbin, gint stream);
386 GstTagList *(*get_audio_tags) (GstPlayBin * playbin, gint stream);
387 GstTagList *(*get_text_tags) (GstPlayBin * playbin, gint stream);
389 /* get the last video frame and convert it to the given caps */
390 GstBuffer *(*convert_frame) (GstPlayBin * playbin, GstCaps * caps);
392 /* get audio/video/text pad for a stream */
393 GstPad *(*get_video_pad) (GstPlayBin * playbin, gint stream);
394 GstPad *(*get_audio_pad) (GstPlayBin * playbin, gint stream);
395 GstPad *(*get_text_pad) (GstPlayBin * playbin, gint stream);
399 #define DEFAULT_URI NULL
400 #define DEFAULT_SUBURI NULL
401 #define DEFAULT_SOURCE NULL
402 #define DEFAULT_FLAGS GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_TEXT | \
403 GST_PLAY_FLAG_SOFT_VOLUME
404 #define DEFAULT_N_VIDEO 0
405 #define DEFAULT_CURRENT_VIDEO -1
406 #define DEFAULT_N_AUDIO 0
407 #define DEFAULT_CURRENT_AUDIO -1
408 #define DEFAULT_N_TEXT 0
409 #define DEFAULT_CURRENT_TEXT -1
410 #define DEFAULT_SUBTITLE_ENCODING NULL
411 #define DEFAULT_AUDIO_SINK NULL
412 #define DEFAULT_VIDEO_SINK NULL
413 #define DEFAULT_VIS_PLUGIN NULL
414 #define DEFAULT_VOLUME 1.0
415 #define DEFAULT_MUTE FALSE
416 #define DEFAULT_FRAME NULL
417 #define DEFAULT_FONT_DESC NULL
418 #define DEFAULT_CONNECTION_SPEED 0
419 #define DEFAULT_BUFFER_DURATION -1
420 #define DEFAULT_BUFFER_SIZE -1
435 PROP_SUBTITLE_ENCODING,
443 PROP_CONNECTION_SPEED,
451 SIGNAL_ABOUT_TO_FINISH,
452 SIGNAL_CONVERT_FRAME,
453 SIGNAL_VIDEO_CHANGED,
454 SIGNAL_AUDIO_CHANGED,
456 SIGNAL_GET_VIDEO_TAGS,
457 SIGNAL_GET_AUDIO_TAGS,
458 SIGNAL_GET_TEXT_TAGS,
459 SIGNAL_GET_VIDEO_PAD,
460 SIGNAL_GET_AUDIO_PAD,
465 static void gst_play_bin_class_init (GstPlayBinClass * klass);
466 static void gst_play_bin_init (GstPlayBin * playbin);
467 static void gst_play_bin_finalize (GObject * object);
469 static void gst_play_bin_set_property (GObject * object, guint prop_id,
470 const GValue * value, GParamSpec * spec);
471 static void gst_play_bin_get_property (GObject * object, guint prop_id,
472 GValue * value, GParamSpec * spec);
474 static GstStateChangeReturn gst_play_bin_change_state (GstElement * element,
475 GstStateChange transition);
477 static void gst_play_bin_handle_message (GstBin * bin, GstMessage * message);
479 static GstTagList *gst_play_bin_get_video_tags (GstPlayBin * playbin,
481 static GstTagList *gst_play_bin_get_audio_tags (GstPlayBin * playbin,
483 static GstTagList *gst_play_bin_get_text_tags (GstPlayBin * playbin,
486 static GstBuffer *gst_play_bin_convert_frame (GstPlayBin * playbin,
489 static GstPad *gst_play_bin_get_video_pad (GstPlayBin * playbin, gint stream);
490 static GstPad *gst_play_bin_get_audio_pad (GstPlayBin * playbin, gint stream);
491 static GstPad *gst_play_bin_get_text_pad (GstPlayBin * playbin, gint stream);
493 static gboolean setup_next_source (GstPlayBin * playbin);
495 static GstElementClass *parent_class;
497 static guint gst_play_bin_signals[LAST_SIGNAL] = { 0 };
499 static const GstElementDetails gst_play_bin_details =
500 GST_ELEMENT_DETAILS ("Player Bin 2",
501 "Generic/Bin/Player",
502 "Autoplug and play media from an uri",
503 "Wim Taymans <wim.taymans@gmail.com>");
506 gst_play_marshal_BUFFER__BOXED (GClosure * closure,
507 GValue * return_value G_GNUC_UNUSED,
508 guint n_param_values,
509 const GValue * param_values,
510 gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data)
512 typedef GstBuffer *(*GMarshalFunc_OBJECT__BOXED) (gpointer data1,
513 gpointer arg_1, gpointer data2);
514 register GMarshalFunc_OBJECT__BOXED callback;
515 register GCClosure *cc = (GCClosure *) closure;
516 register gpointer data1, data2;
519 g_return_if_fail (return_value != NULL);
520 g_return_if_fail (n_param_values == 2);
522 if (G_CCLOSURE_SWAP_DATA (closure)) {
523 data1 = closure->data;
524 data2 = g_value_peek_pointer (param_values + 0);
526 data1 = g_value_peek_pointer (param_values + 0);
527 data2 = closure->data;
530 (GMarshalFunc_OBJECT__BOXED) (marshal_data ? marshal_data : cc->callback);
532 v_return = callback (data1, g_value_get_boxed (param_values + 1), data2);
534 gst_value_take_buffer (return_value, v_return);
538 gst_play_bin_get_type (void)
540 static GType gst_play_bin_type = 0;
542 if (!gst_play_bin_type) {
543 static const GTypeInfo gst_play_bin_info = {
544 sizeof (GstPlayBinClass),
547 (GClassInitFunc) gst_play_bin_class_init,
552 (GInstanceInitFunc) gst_play_bin_init,
556 gst_play_bin_type = g_type_register_static (GST_TYPE_PIPELINE,
557 "GstPlayBin2", &gst_play_bin_info, 0);
560 return gst_play_bin_type;
564 gst_play_bin_class_init (GstPlayBinClass * klass)
566 GObjectClass *gobject_klass;
567 GstElementClass *gstelement_klass;
568 GstBinClass *gstbin_klass;
570 gobject_klass = (GObjectClass *) klass;
571 gstelement_klass = (GstElementClass *) klass;
572 gstbin_klass = (GstBinClass *) klass;
574 parent_class = g_type_class_peek_parent (klass);
576 gobject_klass->set_property = gst_play_bin_set_property;
577 gobject_klass->get_property = gst_play_bin_get_property;
579 gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_play_bin_finalize);
584 * Set the next URI that playbin will play. This property can be set from the
585 * about-to-finish signal to queue the next media file.
587 g_object_class_install_property (gobject_klass, PROP_URI,
588 g_param_spec_string ("uri", "URI", "URI of the media to play",
589 NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
594 * Set the next subtitle URI that playbin will play. This property can be
595 * set from the about-to-finish signal to queue the next subtitle media file.
597 g_object_class_install_property (gobject_klass, PROP_SUBURI,
598 g_param_spec_string ("suburi", ".sub-URI", "Optional URI of a subtitle",
599 NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
601 g_object_class_install_property (gobject_klass, PROP_SOURCE,
602 g_param_spec_object ("source", "Source", "Source element",
603 GST_TYPE_ELEMENT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
608 * Control the behaviour of playbin.
610 g_object_class_install_property (gobject_klass, PROP_FLAGS,
611 g_param_spec_flags ("flags", "Flags", "Flags to control behaviour",
612 GST_TYPE_PLAY_FLAGS, DEFAULT_FLAGS,
613 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
616 * GstPlayBin2:n-video
618 * Get the total number of available video streams.
620 g_object_class_install_property (gobject_klass, PROP_N_VIDEO,
621 g_param_spec_int ("n-video", "Number Video",
622 "Total number of video streams", 0, G_MAXINT, 0,
623 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
625 * GstPlayBin2:current-video
627 * Get or set the currently playing video stream. By default the first video
628 * stream with data is played.
630 g_object_class_install_property (gobject_klass, PROP_CURRENT_VIDEO,
631 g_param_spec_int ("current-video", "Current Video",
632 "Currently playing video stream (-1 = auto)",
633 -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
635 * GstPlayBin2:n-audio
637 * Get the total number of available audio streams.
639 g_object_class_install_property (gobject_klass, PROP_N_AUDIO,
640 g_param_spec_int ("n-audio", "Number Audio",
641 "Total number of audio streams", 0, G_MAXINT, 0,
642 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
644 * GstPlayBin2:current-audio
646 * Get or set the currently playing audio stream. By default the first audio
647 * stream with data is played.
649 g_object_class_install_property (gobject_klass, PROP_CURRENT_AUDIO,
650 g_param_spec_int ("current-audio", "Current audio",
651 "Currently playing audio stream (-1 = auto)",
652 -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
656 * Get the total number of available subtitle streams.
658 g_object_class_install_property (gobject_klass, PROP_N_TEXT,
659 g_param_spec_int ("n-text", "Number Text",
660 "Total number of text streams", 0, G_MAXINT, 0,
661 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
663 * GstPlayBin2:current-text:
665 * Get or set the currently playing subtitle stream. By default the first
666 * subtitle stream with data is played.
668 g_object_class_install_property (gobject_klass, PROP_CURRENT_TEXT,
669 g_param_spec_int ("current-text", "Current Text",
670 "Currently playing text stream (-1 = auto)",
671 -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
673 g_object_class_install_property (gobject_klass, PROP_SUBTITLE_ENCODING,
674 g_param_spec_string ("subtitle-encoding", "subtitle encoding",
675 "Encoding to assume if input subtitles are not in UTF-8 encoding. "
676 "If not set, the GST_SUBTITLE_ENCODING environment variable will "
677 "be checked for an encoding to use. If that is not set either, "
678 "ISO-8859-15 will be assumed.", NULL,
679 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
681 g_object_class_install_property (gobject_klass, PROP_VIDEO_SINK,
682 g_param_spec_object ("video-sink", "Video Sink",
683 "the video output element to use (NULL = default sink)",
684 GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
685 g_object_class_install_property (gobject_klass, PROP_AUDIO_SINK,
686 g_param_spec_object ("audio-sink", "Audio Sink",
687 "the audio output element to use (NULL = default sink)",
688 GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
689 g_object_class_install_property (gobject_klass, PROP_VIS_PLUGIN,
690 g_param_spec_object ("vis-plugin", "Vis plugin",
691 "the visualization element to use (NULL = default)",
692 GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
694 g_object_class_install_property (gobject_klass, PROP_VOLUME,
695 g_param_spec_double ("volume", "Volume", "The audio volume",
696 0.0, VOLUME_MAX_DOUBLE, 1.0,
697 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
698 g_object_class_install_property (gobject_klass, PROP_MUTE,
699 g_param_spec_boolean ("mute", "Mute",
700 "Mute the audio channel without changing the volume", FALSE,
701 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
705 * @playbin: a #GstPlayBin2
707 * Get the currently rendered or prerolled frame in the sink.
708 * The #GstCaps on the buffer will describe the format of the buffer.
710 g_object_class_install_property (gobject_klass, PROP_FRAME,
711 gst_param_spec_mini_object ("frame", "Frame",
712 "The last frame (NULL = no video available)",
713 GST_TYPE_BUFFER, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
714 g_object_class_install_property (gobject_klass, PROP_FONT_DESC,
715 g_param_spec_string ("subtitle-font-desc",
716 "Subtitle font description",
717 "Pango font description of font "
718 "to be used for subtitle rendering", NULL,
719 G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
721 g_object_class_install_property (gobject_klass, PROP_CONNECTION_SPEED,
722 g_param_spec_uint ("connection-speed", "Connection Speed",
723 "Network connection speed in kbps (0 = unknown)",
724 0, G_MAXUINT, DEFAULT_CONNECTION_SPEED,
725 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
727 g_object_class_install_property (gobject_klass, PROP_BUFFER_SIZE,
728 g_param_spec_int ("buffer-size", "Buffer size (bytes)",
729 "Buffer size when buffering network streams",
730 -1, G_MAXINT, DEFAULT_BUFFER_SIZE,
731 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
732 g_object_class_install_property (gobject_klass, PROP_BUFFER_DURATION,
733 g_param_spec_int64 ("buffer-duration", "Buffer duration (ns)",
734 "Buffer duration when buffering network streams",
735 -1, G_MAXINT64, DEFAULT_BUFFER_DURATION,
736 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
739 * GstPlayBin2::about-to-finish
740 * @playbin: a #GstPlayBin2
742 * This signal is emitted when the current uri is about to finish. You can
743 * set the uri and suburi to make sure that playback continues.
745 gst_play_bin_signals[SIGNAL_ABOUT_TO_FINISH] =
746 g_signal_new ("about-to-finish", G_TYPE_FROM_CLASS (klass),
748 G_STRUCT_OFFSET (GstPlayBinClass, about_to_finish), NULL, NULL,
749 gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
752 * GstPlayBin2::video-changed
753 * @playbin: a #GstPlayBin2
755 * This signal is emitted whenever the number or order of the video
756 * streams has changed. The application will most likely want to select
757 * a new video stream.
759 gst_play_bin_signals[SIGNAL_VIDEO_CHANGED] =
760 g_signal_new ("video-changed", G_TYPE_FROM_CLASS (klass),
762 G_STRUCT_OFFSET (GstPlayBinClass, video_changed), NULL, NULL,
763 gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
765 * GstPlayBin2::audio-changed
766 * @playbin: a #GstPlayBin2
768 * This signal is emitted whenever the number or order of the audio
769 * streams has changed. The application will most likely want to select
770 * a new audio stream.
772 gst_play_bin_signals[SIGNAL_AUDIO_CHANGED] =
773 g_signal_new ("audio-changed", G_TYPE_FROM_CLASS (klass),
775 G_STRUCT_OFFSET (GstPlayBinClass, audio_changed), NULL, NULL,
776 gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
778 * GstPlayBin2::text-changed
779 * @playbin: a #GstPlayBin2
781 * This signal is emitted whenever the number or order of the text
782 * streams has changed. The application will most likely want to select
785 gst_play_bin_signals[SIGNAL_TEXT_CHANGED] =
786 g_signal_new ("text-changed", G_TYPE_FROM_CLASS (klass),
788 G_STRUCT_OFFSET (GstPlayBinClass, text_changed), NULL, NULL,
789 gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
792 * GstPlayBin2::get-video-tags
793 * @playbin: a #GstPlayBin2
794 * @stream: a video stream number
796 * Action signal to retrieve the tags of a specific video stream number.
797 * This information can be used to select a stream.
799 * Returns: a GstTagList with tags or NULL when the stream number does not
802 gst_play_bin_signals[SIGNAL_GET_VIDEO_TAGS] =
803 g_signal_new ("get-video-tags", G_TYPE_FROM_CLASS (klass),
804 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
805 G_STRUCT_OFFSET (GstPlayBinClass, get_video_tags), NULL, NULL,
806 gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
808 * GstPlayBin2::get-audio-tags
809 * @playbin: a #GstPlayBin2
810 * @stream: an audio stream number
812 * Action signal to retrieve the tags of a specific audio stream number.
813 * This information can be used to select a stream.
815 * Returns: a GstTagList with tags or NULL when the stream number does not
818 gst_play_bin_signals[SIGNAL_GET_AUDIO_TAGS] =
819 g_signal_new ("get-audio-tags", G_TYPE_FROM_CLASS (klass),
820 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
821 G_STRUCT_OFFSET (GstPlayBinClass, get_audio_tags), NULL, NULL,
822 gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
824 * GstPlayBin2::get-text-tags
825 * @playbin: a #GstPlayBin2
826 * @stream: a text stream number
828 * Action signal to retrieve the tags of a specific text stream number.
829 * This information can be used to select a stream.
831 * Returns: a GstTagList with tags or NULL when the stream number does not
834 gst_play_bin_signals[SIGNAL_GET_TEXT_TAGS] =
835 g_signal_new ("get-text-tags", G_TYPE_FROM_CLASS (klass),
836 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
837 G_STRUCT_OFFSET (GstPlayBinClass, get_text_tags), NULL, NULL,
838 gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT);
840 * GstPlayBin2::convert-frame
841 * @playbin: a #GstPlayBin2
842 * @caps: the target format of the frame
844 * Action signal to retrieve the currently playing video frame in the format
845 * specified by @caps.
846 * If @caps is %NULL, no conversion will be performed and this function is
847 * equivalent to the #GstPlayBin::frame property.
849 * Returns: a #GstBuffer of the current video frame converted to #caps.
850 * The caps on the buffer will describe the final layout of the buffer data.
851 * %NULL is returned when no current buffer can be retrieved or when the
854 gst_play_bin_signals[SIGNAL_CONVERT_FRAME] =
855 g_signal_new ("convert-frame", G_TYPE_FROM_CLASS (klass),
856 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
857 G_STRUCT_OFFSET (GstPlayBinClass, convert_frame), NULL, NULL,
858 gst_play_marshal_BUFFER__BOXED, GST_TYPE_BUFFER, 1, GST_TYPE_CAPS);
861 * GstPlayBin2::get-video-pad
862 * @playbin: a #GstPlayBin2
863 * @stream: a video stream number
865 * Action signal to retrieve the stream-selector sinkpad for a specific
867 * This pad can be used for notifications of caps changes, stream-specific
870 * Returns: a #GstPad, or NULL when the stream number does not exist.
872 gst_play_bin_signals[SIGNAL_GET_VIDEO_PAD] =
873 g_signal_new ("get-video-pad", G_TYPE_FROM_CLASS (klass),
874 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
875 G_STRUCT_OFFSET (GstPlayBinClass, get_video_pad), NULL, NULL,
876 gst_play_marshal_OBJECT__INT, GST_TYPE_PAD, 1, G_TYPE_INT);
878 * GstPlayBin2::get-audio-pad
879 * @playbin: a #GstPlayBin2
880 * @stream: an audio stream number
882 * Action signal to retrieve the stream-selector sinkpad for a specific
884 * This pad can be used for notifications of caps changes, stream-specific
887 * Returns: a #GstPad, or NULL when the stream number does not exist.
889 gst_play_bin_signals[SIGNAL_GET_AUDIO_PAD] =
890 g_signal_new ("get-audio-pad", G_TYPE_FROM_CLASS (klass),
891 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
892 G_STRUCT_OFFSET (GstPlayBinClass, get_audio_pad), NULL, NULL,
893 gst_play_marshal_OBJECT__INT, GST_TYPE_PAD, 1, G_TYPE_INT);
895 * GstPlayBin2::get-text-pad
896 * @playbin: a #GstPlayBin2
897 * @stream: a text stream number
899 * Action signal to retrieve the stream-selector sinkpad for a specific
901 * This pad can be used for notifications of caps changes, stream-specific
904 * Returns: a #GstPad, or NULL when the stream number does not exist.
906 gst_play_bin_signals[SIGNAL_GET_TEXT_PAD] =
907 g_signal_new ("get-text-pad", G_TYPE_FROM_CLASS (klass),
908 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
909 G_STRUCT_OFFSET (GstPlayBinClass, get_text_pad), NULL, NULL,
910 gst_play_marshal_OBJECT__INT, GST_TYPE_PAD, 1, G_TYPE_INT);
912 klass->get_video_tags = gst_play_bin_get_video_tags;
913 klass->get_audio_tags = gst_play_bin_get_audio_tags;
914 klass->get_text_tags = gst_play_bin_get_text_tags;
916 klass->convert_frame = gst_play_bin_convert_frame;
918 klass->get_video_pad = gst_play_bin_get_video_pad;
919 klass->get_audio_pad = gst_play_bin_get_audio_pad;
920 klass->get_text_pad = gst_play_bin_get_text_pad;
922 gst_element_class_set_details (gstelement_klass, &gst_play_bin_details);
924 gstelement_klass->change_state =
925 GST_DEBUG_FUNCPTR (gst_play_bin_change_state);
927 gstbin_klass->handle_message =
928 GST_DEBUG_FUNCPTR (gst_play_bin_handle_message);
932 init_group (GstPlayBin * playbin, GstSourceGroup * group)
934 /* store the array for the different channels */
935 group->video_channels = g_ptr_array_new ();
936 group->audio_channels = g_ptr_array_new ();
937 group->text_channels = g_ptr_array_new ();
938 group->lock = g_mutex_new ();
939 group->cond = g_cond_new ();
941 group->playbin = playbin;
942 group->selector[0].media = "audio/x-raw-";
943 group->selector[0].type = GST_PLAY_SINK_TYPE_AUDIO_RAW;
944 group->selector[0].channels = group->audio_channels;
945 group->selector[1].media = "audio/";
946 group->selector[1].type = GST_PLAY_SINK_TYPE_AUDIO;
947 group->selector[1].channels = group->audio_channels;
948 group->selector[2].media = "video/x-raw-";
949 group->selector[2].type = GST_PLAY_SINK_TYPE_VIDEO_RAW;
950 group->selector[2].channels = group->video_channels;
951 group->selector[3].media = "video/";
952 group->selector[3].type = GST_PLAY_SINK_TYPE_VIDEO;
953 group->selector[3].channels = group->video_channels;
954 group->selector[4].media = "text/";
955 group->selector[4].type = GST_PLAY_SINK_TYPE_TEXT;
956 group->selector[4].channels = group->text_channels;
960 free_group (GstPlayBin * playbin, GstSourceGroup * group)
963 g_ptr_array_free (group->video_channels, TRUE);
964 g_ptr_array_free (group->audio_channels, TRUE);
965 g_ptr_array_free (group->text_channels, TRUE);
966 g_mutex_free (group->lock);
967 g_cond_free (group->cond);
971 gst_play_bin_init (GstPlayBin * playbin)
973 GstFactoryListType type;
975 playbin->lock = g_mutex_new ();
976 playbin->dyn_lock = g_mutex_new ();
979 playbin->curr_group = &playbin->groups[0];
980 playbin->next_group = &playbin->groups[1];
981 init_group (playbin, &playbin->groups[0]);
982 init_group (playbin, &playbin->groups[1]);
984 /* first filter out the interesting element factories */
985 type = GST_FACTORY_LIST_DECODER | GST_FACTORY_LIST_SINK;
986 playbin->elements = gst_factory_list_get_elements (type);
987 gst_factory_list_debug (playbin->elements);
990 playbin->playsink = g_object_new (GST_TYPE_PLAY_SINK, NULL);
991 gst_bin_add (GST_BIN_CAST (playbin), GST_ELEMENT_CAST (playbin->playsink));
992 gst_play_sink_set_flags (playbin->playsink, DEFAULT_FLAGS);
994 playbin->encoding = g_strdup (DEFAULT_SUBTITLE_ENCODING);
996 playbin->current_video = DEFAULT_CURRENT_VIDEO;
997 playbin->current_audio = DEFAULT_CURRENT_AUDIO;
998 playbin->current_text = DEFAULT_CURRENT_TEXT;
1000 playbin->buffer_duration = DEFAULT_BUFFER_DURATION;
1001 playbin->buffer_size = DEFAULT_BUFFER_SIZE;
1005 gst_play_bin_finalize (GObject * object)
1007 GstPlayBin *playbin;
1009 playbin = GST_PLAY_BIN (object);
1011 free_group (playbin, &playbin->groups[0]);
1012 free_group (playbin, &playbin->groups[1]);
1014 if (playbin->source)
1015 gst_object_unref (playbin->source);
1017 g_value_array_free (playbin->elements);
1018 g_free (playbin->encoding);
1019 g_mutex_free (playbin->lock);
1020 g_mutex_free (playbin->dyn_lock);
1022 G_OBJECT_CLASS (parent_class)->finalize (object);
1026 gst_play_bin_set_uri (GstPlayBin * playbin, const gchar * uri)
1028 GstSourceGroup *group;
1031 g_warning ("cannot set NULL uri");
1035 GST_PLAY_BIN_LOCK (playbin);
1036 group = playbin->next_group;
1038 GST_SOURCE_GROUP_LOCK (group);
1039 /* store the uri in the next group we will play */
1040 g_free (group->uri);
1041 group->uri = g_strdup (uri);
1042 group->valid = TRUE;
1043 GST_SOURCE_GROUP_UNLOCK (group);
1045 GST_DEBUG ("set new uri to %s", uri);
1046 GST_PLAY_BIN_UNLOCK (playbin);
1050 gst_play_bin_set_suburi (GstPlayBin * playbin, const gchar * suburi)
1052 GstSourceGroup *group;
1054 GST_PLAY_BIN_LOCK (playbin);
1055 group = playbin->next_group;
1057 GST_SOURCE_GROUP_LOCK (group);
1058 g_free (group->suburi);
1059 group->suburi = g_strdup (suburi);
1060 GST_SOURCE_GROUP_UNLOCK (group);
1062 GST_DEBUG ("setting new .sub uri to %s", suburi);
1064 GST_PLAY_BIN_UNLOCK (playbin);
1067 /* get the currently playing group or if nothing is playing, the next
1068 * group. Must be called with the PLAY_BIN_LOCK. */
1069 static GstSourceGroup *
1070 get_group (GstPlayBin * playbin)
1072 GstSourceGroup *result;
1074 if (!(result = playbin->curr_group))
1075 result = playbin->next_group;
1081 gst_play_bin_get_video_pad (GstPlayBin * playbin, gint stream)
1083 GstPad *sinkpad = NULL;
1084 GstSourceGroup *group;
1086 GST_PLAY_BIN_LOCK (playbin);
1087 group = get_group (playbin);
1088 if (stream < group->video_channels->len) {
1089 sinkpad = g_ptr_array_index (group->video_channels, stream);
1090 gst_object_ref (sinkpad);
1092 GST_PLAY_BIN_UNLOCK (playbin);
1098 gst_play_bin_get_audio_pad (GstPlayBin * playbin, gint stream)
1100 GstPad *sinkpad = NULL;
1101 GstSourceGroup *group;
1103 GST_PLAY_BIN_LOCK (playbin);
1104 group = get_group (playbin);
1105 if (stream < group->audio_channels->len) {
1106 sinkpad = g_ptr_array_index (group->audio_channels, stream);
1107 gst_object_ref (sinkpad);
1109 GST_PLAY_BIN_UNLOCK (playbin);
1115 gst_play_bin_get_text_pad (GstPlayBin * playbin, gint stream)
1117 GstPad *sinkpad = NULL;
1118 GstSourceGroup *group;
1120 GST_PLAY_BIN_LOCK (playbin);
1121 group = get_group (playbin);
1122 if (stream < group->text_channels->len) {
1123 sinkpad = g_ptr_array_index (group->text_channels, stream);
1124 gst_object_ref (sinkpad);
1126 GST_PLAY_BIN_UNLOCK (playbin);
1133 get_tags (GstPlayBin * playbin, GPtrArray * channels, gint stream)
1138 if (!channels || stream >= channels->len)
1141 sinkpad = g_ptr_array_index (channels, stream);
1142 g_object_get (sinkpad, "tags", &result, NULL);
1148 gst_play_bin_get_video_tags (GstPlayBin * playbin, gint stream)
1151 GstSourceGroup *group;
1153 GST_PLAY_BIN_LOCK (playbin);
1154 group = get_group (playbin);
1155 result = get_tags (playbin, group->video_channels, stream);
1156 GST_PLAY_BIN_UNLOCK (playbin);
1162 gst_play_bin_get_audio_tags (GstPlayBin * playbin, gint stream)
1165 GstSourceGroup *group;
1167 GST_PLAY_BIN_LOCK (playbin);
1168 group = get_group (playbin);
1169 result = get_tags (playbin, group->audio_channels, stream);
1170 GST_PLAY_BIN_UNLOCK (playbin);
1176 gst_play_bin_get_text_tags (GstPlayBin * playbin, gint stream)
1179 GstSourceGroup *group;
1181 GST_PLAY_BIN_LOCK (playbin);
1182 group = get_group (playbin);
1183 result = get_tags (playbin, group->text_channels, stream);
1184 GST_PLAY_BIN_UNLOCK (playbin);
1190 gst_play_bin_convert_frame (GstPlayBin * playbin, GstCaps * caps)
1194 result = gst_play_sink_get_last_frame (playbin->playsink);
1195 if (result != NULL && caps != NULL) {
1198 temp = gst_play_frame_conv_convert (result, caps);
1199 gst_buffer_unref (result);
1205 /* Returns current stream number, or -1 if none has been selected yet */
1207 get_current_stream_number (GstPlayBin * playbin, GPtrArray * channels)
1209 /* Internal API cleanup would make this easier... */
1211 GstPad *pad, *current;
1212 GstObject *selector = NULL;
1215 for (i = 0; i < channels->len; i++) {
1216 pad = g_ptr_array_index (channels, i);
1217 if ((selector = gst_pad_get_parent (pad))) {
1218 g_object_get (selector, "active-pad", ¤t, NULL);
1220 if (pad == current) {
1221 gst_object_unref (current);
1227 gst_object_unref (current);
1232 gst_object_unref (selector);
1238 gst_play_bin_set_current_video_stream (GstPlayBin * playbin, gint stream)
1240 GstSourceGroup *group;
1241 GPtrArray *channels;
1244 GST_PLAY_BIN_LOCK (playbin);
1245 group = get_group (playbin);
1246 if (!(channels = group->video_channels))
1249 if (stream == -1 || channels->len < stream) {
1252 /* take channel from selected stream */
1253 sinkpad = g_ptr_array_index (channels, stream);
1257 gst_object_ref (sinkpad);
1258 GST_PLAY_BIN_UNLOCK (playbin);
1261 GstObject *selector;
1263 if ((selector = gst_pad_get_parent (sinkpad))) {
1264 /* activate the selected pad */
1265 g_object_set (selector, "active-pad", sinkpad, NULL);
1266 gst_object_unref (selector);
1268 gst_object_unref (sinkpad);
1274 GST_PLAY_BIN_UNLOCK (playbin);
1280 gst_play_bin_set_current_audio_stream (GstPlayBin * playbin, gint stream)
1282 GstSourceGroup *group;
1283 GPtrArray *channels;
1286 GST_PLAY_BIN_LOCK (playbin);
1287 group = get_group (playbin);
1288 if (!(channels = group->audio_channels))
1291 if (stream == -1 || channels->len < stream) {
1294 /* take channel from selected stream */
1295 sinkpad = g_ptr_array_index (channels, stream);
1299 gst_object_ref (sinkpad);
1300 GST_PLAY_BIN_UNLOCK (playbin);
1303 GstObject *selector;
1305 if ((selector = gst_pad_get_parent (sinkpad))) {
1306 /* activate the selected pad */
1307 g_object_set (selector, "active-pad", sinkpad, NULL);
1308 gst_object_unref (selector);
1310 gst_object_unref (sinkpad);
1316 GST_PLAY_BIN_UNLOCK (playbin);
1322 gst_play_bin_set_current_text_stream (GstPlayBin * playbin, gint stream)
1324 GstSourceGroup *group;
1325 GPtrArray *channels;
1328 GST_PLAY_BIN_LOCK (playbin);
1329 group = get_group (playbin);
1330 if (!(channels = group->text_channels))
1333 if (stream == -1 || channels->len < stream) {
1336 /* take channel from selected stream */
1337 sinkpad = g_ptr_array_index (channels, stream);
1341 gst_object_ref (sinkpad);
1342 GST_PLAY_BIN_UNLOCK (playbin);
1345 GstObject *selector;
1347 if ((selector = gst_pad_get_parent (sinkpad))) {
1348 /* activate the selected pad */
1349 g_object_set (selector, "active-pad", sinkpad, NULL);
1350 gst_object_unref (selector);
1352 gst_object_unref (sinkpad);
1358 GST_PLAY_BIN_UNLOCK (playbin);
1364 gst_play_bin_set_encoding (GstPlayBin * playbin, const gchar * encoding)
1368 GST_PLAY_BIN_LOCK (playbin);
1369 g_free (playbin->encoding);
1370 playbin->encoding = g_strdup (encoding);
1372 /* set subtitles on all current and next decodebins. */
1373 if ((elem = playbin->groups[0].uridecodebin))
1374 g_object_set (G_OBJECT (elem), "subtitle-encoding", encoding, NULL);
1375 if ((elem = playbin->groups[0].suburidecodebin))
1376 g_object_set (G_OBJECT (elem), "subtitle-encoding", encoding, NULL);
1377 if ((elem = playbin->groups[1].uridecodebin))
1378 g_object_set (G_OBJECT (elem), "subtitle-encoding", encoding, NULL);
1379 if ((elem = playbin->groups[1].suburidecodebin))
1380 g_object_set (G_OBJECT (elem), "subtitle-encoding", encoding, NULL);
1381 GST_PLAY_BIN_UNLOCK (playbin);
1385 gst_play_bin_set_property (GObject * object, guint prop_id,
1386 const GValue * value, GParamSpec * pspec)
1388 GstPlayBin *playbin;
1390 playbin = GST_PLAY_BIN (object);
1394 gst_play_bin_set_uri (playbin, g_value_get_string (value));
1397 gst_play_bin_set_suburi (playbin, g_value_get_string (value));
1400 gst_play_sink_set_flags (playbin->playsink, g_value_get_flags (value));
1401 gst_play_sink_reconfigure (playbin->playsink);
1403 case PROP_CURRENT_VIDEO:
1404 gst_play_bin_set_current_video_stream (playbin, g_value_get_int (value));
1406 case PROP_CURRENT_AUDIO:
1407 gst_play_bin_set_current_audio_stream (playbin, g_value_get_int (value));
1409 case PROP_CURRENT_TEXT:
1410 gst_play_bin_set_current_text_stream (playbin, g_value_get_int (value));
1412 case PROP_SUBTITLE_ENCODING:
1413 gst_play_bin_set_encoding (playbin, g_value_get_string (value));
1415 case PROP_VIDEO_SINK:
1416 gst_play_sink_set_video_sink (playbin->playsink,
1417 g_value_get_object (value));
1419 case PROP_AUDIO_SINK:
1420 gst_play_sink_set_audio_sink (playbin->playsink,
1421 g_value_get_object (value));
1423 case PROP_VIS_PLUGIN:
1424 gst_play_sink_set_vis_plugin (playbin->playsink,
1425 g_value_get_object (value));
1428 gst_play_sink_set_volume (playbin->playsink, g_value_get_double (value));
1431 gst_play_sink_set_mute (playbin->playsink, g_value_get_boolean (value));
1433 case PROP_FONT_DESC:
1434 gst_play_sink_set_font_desc (playbin->playsink,
1435 g_value_get_string (value));
1437 case PROP_CONNECTION_SPEED:
1438 GST_PLAY_BIN_LOCK (playbin);
1439 playbin->connection_speed = g_value_get_uint (value) * 1000;
1440 GST_PLAY_BIN_UNLOCK (playbin);
1442 case PROP_BUFFER_SIZE:
1443 playbin->buffer_size = g_value_get_int (value);
1445 case PROP_BUFFER_DURATION:
1446 playbin->buffer_duration = g_value_get_int64 (value);
1449 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1455 gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value,
1458 GstPlayBin *playbin;
1460 playbin = GST_PLAY_BIN (object);
1465 GstSourceGroup *group;
1467 GST_PLAY_BIN_LOCK (playbin);
1468 group = get_group (playbin);
1469 g_value_set_string (value, group->uri);
1470 GST_PLAY_BIN_UNLOCK (playbin);
1475 GstSourceGroup *group;
1477 GST_PLAY_BIN_LOCK (playbin);
1478 group = get_group (playbin);
1479 g_value_set_string (value, group->suburi);
1480 GST_PLAY_BIN_UNLOCK (playbin);
1485 GST_OBJECT_LOCK (playbin);
1486 g_value_set_object (value, playbin->source);
1487 GST_OBJECT_UNLOCK (playbin);
1491 g_value_set_flags (value, gst_play_sink_get_flags (playbin->playsink));
1495 GstSourceGroup *group;
1498 GST_PLAY_BIN_LOCK (playbin);
1499 group = get_group (playbin);
1500 n_video = (group->video_channels ? group->video_channels->len : 0);
1501 g_value_set_int (value, n_video);
1502 GST_PLAY_BIN_UNLOCK (playbin);
1505 case PROP_CURRENT_VIDEO:
1506 GST_PLAY_BIN_LOCK (playbin);
1507 g_value_set_int (value, playbin->current_video);
1508 GST_PLAY_BIN_UNLOCK (playbin);
1512 GstSourceGroup *group;
1515 GST_PLAY_BIN_LOCK (playbin);
1516 group = get_group (playbin);
1517 n_audio = (group->audio_channels ? group->audio_channels->len : 0);
1518 g_value_set_int (value, n_audio);
1519 GST_PLAY_BIN_UNLOCK (playbin);
1522 case PROP_CURRENT_AUDIO:
1523 GST_PLAY_BIN_LOCK (playbin);
1524 g_value_set_int (value, playbin->current_audio);
1525 GST_PLAY_BIN_UNLOCK (playbin);
1529 GstSourceGroup *group;
1532 GST_PLAY_BIN_LOCK (playbin);
1533 group = get_group (playbin);
1534 n_text = (group->text_channels ? group->text_channels->len : 0);
1535 g_value_set_int (value, n_text);
1536 GST_PLAY_BIN_UNLOCK (playbin);
1539 case PROP_CURRENT_TEXT:
1540 GST_PLAY_BIN_LOCK (playbin);
1541 g_value_set_int (value, playbin->current_text);
1542 GST_PLAY_BIN_UNLOCK (playbin);
1544 case PROP_SUBTITLE_ENCODING:
1545 GST_PLAY_BIN_LOCK (playbin);
1546 g_value_set_string (value, playbin->encoding);
1547 GST_PLAY_BIN_UNLOCK (playbin);
1549 case PROP_VIDEO_SINK:
1550 g_value_set_object (value,
1551 gst_play_sink_get_video_sink (playbin->playsink));
1553 case PROP_AUDIO_SINK:
1554 g_value_set_object (value,
1555 gst_play_sink_get_audio_sink (playbin->playsink));
1557 case PROP_VIS_PLUGIN:
1558 g_value_set_object (value,
1559 gst_play_sink_get_vis_plugin (playbin->playsink));
1562 g_value_set_double (value, gst_play_sink_get_volume (playbin->playsink));
1565 g_value_set_boolean (value, gst_play_sink_get_mute (playbin->playsink));
1568 gst_value_take_buffer (value, gst_play_bin_convert_frame (playbin, NULL));
1570 case PROP_FONT_DESC:
1571 g_value_take_string (value,
1572 gst_play_sink_get_font_desc (playbin->playsink));
1574 case PROP_CONNECTION_SPEED:
1575 GST_PLAY_BIN_LOCK (playbin);
1576 g_value_set_uint (value, playbin->connection_speed / 1000);
1577 GST_PLAY_BIN_UNLOCK (playbin);
1579 case PROP_BUFFER_SIZE:
1580 GST_OBJECT_LOCK (playbin);
1581 g_value_set_int (value, playbin->buffer_size);
1582 GST_OBJECT_UNLOCK (playbin);
1584 case PROP_BUFFER_DURATION:
1585 GST_OBJECT_LOCK (playbin);
1586 g_value_set_int64 (value, playbin->buffer_duration);
1587 GST_OBJECT_UNLOCK (playbin);
1590 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1595 /* mime types we are not handling on purpose right now, don't post a
1596 * missing-plugin message for these */
1597 static const gchar *blacklisted_mimes[] = {
1598 "video/x-dvd-subpicture", NULL
1602 gst_play_bin_handle_message (GstBin * bin, GstMessage * msg)
1604 if (gst_is_missing_plugin_message (msg)) {
1608 detail = gst_missing_plugin_message_get_installer_detail (msg);
1609 for (i = 0; detail != NULL && blacklisted_mimes[i] != NULL; ++i) {
1610 if (strstr (detail, "|decoder-") && strstr (detail, blacklisted_mimes[i])) {
1611 GST_LOG_OBJECT (bin, "suppressing message %" GST_PTR_FORMAT, msg);
1612 gst_message_unref (msg);
1619 GST_BIN_CLASS (parent_class)->handle_message (bin, msg);
1623 selector_active_pad_changed (GObject * selector, GParamSpec * pspec,
1624 GstPlayBin * playbin)
1627 GstSourceGroup *group;
1628 GstSourceSelect *select = NULL;
1631 GST_PLAY_BIN_LOCK (playbin);
1632 group = get_group (playbin);
1634 for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
1635 if (selector == G_OBJECT (group->selector[i].selector)) {
1636 select = &group->selector[i];
1640 /* We got a pad-change after our group got switched out; no need to notify */
1642 GST_PLAY_BIN_UNLOCK (playbin);
1646 switch (select->type) {
1647 case GST_PLAY_SINK_TYPE_VIDEO:
1648 case GST_PLAY_SINK_TYPE_VIDEO_RAW:
1649 property = "current-video";
1650 playbin->current_video = get_current_stream_number (playbin,
1651 group->video_channels);
1653 case GST_PLAY_SINK_TYPE_AUDIO:
1654 case GST_PLAY_SINK_TYPE_AUDIO_RAW:
1655 property = "current-audio";
1656 playbin->current_audio = get_current_stream_number (playbin,
1657 group->audio_channels);
1659 case GST_PLAY_SINK_TYPE_TEXT:
1660 property = "current-text";
1661 playbin->current_text = get_current_stream_number (playbin,
1662 group->text_channels);
1667 GST_PLAY_BIN_UNLOCK (playbin);
1670 g_object_notify (G_OBJECT (playbin), property);
1674 selector_blocked (GstPad * pad, gboolean blocked, gpointer user_data)
1677 GST_DEBUG_OBJECT (pad, "blocked callback, blocked: %d", blocked);
1680 /* this function is called when a new pad is added to decodebin. We check the
1681 * type of the pad and add it to the selector element of the group.
1684 pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
1686 GstPlayBin *playbin;
1688 const GstStructure *s;
1691 GstPadLinkReturn res;
1692 GstSourceSelect *select = NULL;
1694 gboolean changed = FALSE;
1696 playbin = group->playbin;
1698 caps = gst_pad_get_caps (pad);
1699 s = gst_caps_get_structure (caps, 0);
1700 name = gst_structure_get_name (s);
1702 GST_DEBUG_OBJECT (playbin,
1703 "pad %s:%s with caps %" GST_PTR_FORMAT " added in group %p",
1704 GST_DEBUG_PAD_NAME (pad), caps, group);
1706 /* major type of the pad, this determines the selector to use */
1707 for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
1708 if (g_str_has_prefix (name, group->selector[i].media)) {
1709 select = &group->selector[i];
1713 /* no selector found for the media type, don't bother linking it to a
1714 * selector. This will leave the pad unlinked and thus ignored. */
1718 GST_SOURCE_GROUP_LOCK (group);
1719 if (select->selector == NULL) {
1720 /* no selector, create one */
1721 GST_DEBUG_OBJECT (playbin, "creating new selector");
1722 select->selector = gst_element_factory_make ("input-selector", NULL);
1723 if (select->selector == NULL)
1726 g_signal_connect (select->selector, "notify::active-pad",
1727 G_CALLBACK (selector_active_pad_changed), playbin);
1729 GST_DEBUG_OBJECT (playbin, "adding new selector %p", select->selector);
1730 gst_bin_add (GST_BIN_CAST (playbin), select->selector);
1731 gst_element_set_state (select->selector, GST_STATE_PAUSED);
1733 /* save source pad */
1734 select->srcpad = gst_element_get_static_pad (select->selector, "src");
1735 /* block the selector srcpad. It's possible that multiple decodebins start
1736 * pushing data into the selectors before we have a chance to collect all
1737 * streams and connect the sinks, resulting in not-linked errors. After we
1738 * configured the sinks we will unblock them all. */
1739 gst_pad_set_blocked_async (select->srcpad, TRUE, selector_blocked, NULL);
1742 /* get sinkpad for the new stream */
1743 if ((sinkpad = gst_element_get_request_pad (select->selector, "sink%d"))) {
1744 GST_DEBUG_OBJECT (playbin, "got pad %s:%s from selector",
1745 GST_DEBUG_PAD_NAME (sinkpad));
1747 /* store the selector for the pad */
1748 g_object_set_data (G_OBJECT (sinkpad), "playbin2.select", select);
1750 /* store the pad in the array */
1751 GST_DEBUG_OBJECT (playbin, "pad %p added to array", sinkpad);
1752 g_ptr_array_add (select->channels, sinkpad);
1754 res = gst_pad_link (pad, sinkpad);
1755 if (GST_PAD_LINK_FAILED (res))
1758 /* store selector pad so we can release it */
1759 g_object_set_data (G_OBJECT (pad), "playbin2.sinkpad", sinkpad);
1763 GST_DEBUG_OBJECT (playbin, "linked pad %s:%s to selector %p",
1764 GST_DEBUG_PAD_NAME (pad), select->selector);
1765 GST_SOURCE_GROUP_UNLOCK (group);
1769 switch (select->type) {
1770 case GST_PLAY_SINK_TYPE_VIDEO:
1771 case GST_PLAY_SINK_TYPE_VIDEO_RAW:
1772 signal = SIGNAL_VIDEO_CHANGED;
1774 case GST_PLAY_SINK_TYPE_AUDIO:
1775 case GST_PLAY_SINK_TYPE_AUDIO_RAW:
1776 signal = SIGNAL_AUDIO_CHANGED;
1778 case GST_PLAY_SINK_TYPE_TEXT:
1779 signal = SIGNAL_TEXT_CHANGED;
1786 g_signal_emit (G_OBJECT (playbin), gst_play_bin_signals[signal], 0, NULL);
1790 gst_caps_unref (caps);
1796 GST_ERROR_OBJECT (playbin, "unknown type %s for pad %s:%s",
1797 name, GST_DEBUG_PAD_NAME (pad));
1802 GST_SOURCE_GROUP_UNLOCK (group);
1804 gst_element_post_message (GST_ELEMENT_CAST (playbin),
1805 gst_missing_element_message_new (GST_ELEMENT_CAST (playbin),
1807 GST_ELEMENT_ERROR (playbin, CORE, MISSING_PLUGIN,
1808 (_("Missing element '%s' - check your GStreamer installation."),
1809 "input-selector"), (NULL));
1814 GST_ERROR_OBJECT (playbin,
1815 "failed to link pad %s:%s to selector, reason %d",
1816 GST_DEBUG_PAD_NAME (pad), res);
1817 GST_SOURCE_GROUP_UNLOCK (group);
1822 /* called when a pad is removed from the uridecodebin. We unlink the pad from
1823 * the selector. This will make the selector select a new pad. */
1825 pad_removed_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group)
1827 GstPlayBin *playbin;
1829 GstElement *selector;
1830 GstSourceSelect *select;
1832 playbin = group->playbin;
1834 GST_DEBUG_OBJECT (playbin,
1835 "pad %s:%s removed from group %p", GST_DEBUG_PAD_NAME (pad), group);
1837 GST_SOURCE_GROUP_LOCK (group);
1838 /* get the selector sinkpad */
1839 if (!(peer = g_object_get_data (G_OBJECT (pad), "playbin2.sinkpad")))
1842 if ((select = g_object_get_data (G_OBJECT (peer), "playbin2.select"))) {
1843 /* remove the pad from the array */
1844 g_ptr_array_remove (select->channels, peer);
1845 GST_DEBUG_OBJECT (playbin, "pad %p removed from array", peer);
1848 /* unlink the pad now (can fail, the pad is unlinked before it's removed) */
1849 gst_pad_unlink (pad, peer);
1851 /* get selector, this can be NULL when the element is removing the pads
1852 * because it's being disposed. */
1853 selector = GST_ELEMENT_CAST (gst_pad_get_parent (peer));
1855 gst_object_unref (peer);
1859 /* release the pad to the selector, this will make the selector choose a new
1861 gst_element_release_request_pad (selector, peer);
1862 gst_object_unref (peer);
1864 gst_object_unref (selector);
1865 GST_SOURCE_GROUP_UNLOCK (group);
1872 GST_DEBUG_OBJECT (playbin, "pad not linked");
1873 GST_SOURCE_GROUP_UNLOCK (group);
1878 GST_DEBUG_OBJECT (playbin, "selector not found");
1879 GST_SOURCE_GROUP_UNLOCK (group);
1884 /* we get called when all pads are available and we must connect the sinks to
1886 * The main purpose of the code is to see if we have video/audio and subtitles
1887 * and pick the right pipelines to display them.
1889 * The selectors installed on the group tell us about the presence of
1890 * audio/video and subtitle streams. This allows us to see if we need
1891 * visualisation, video or/and audio.
1894 no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group)
1896 GstPlayBin *playbin;
1897 GstPadLinkReturn res;
1901 playbin = group->playbin;
1903 GST_DEBUG_OBJECT (playbin, "no more pads in group %p", group);
1905 GST_PLAY_BIN_SHUTDOWN_LOCK (playbin, shutdown);
1907 GST_SOURCE_GROUP_LOCK (group);
1908 for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
1909 GstSourceSelect *select = &group->selector[i];
1911 /* check if the specific media type was detected and thus has a selector
1912 * created for it. If there is the media type, get a sinkpad from the sink
1913 * and link it. We only do this if we have not yet requested the sinkpad
1915 if (select->selector && select->sinkpad == NULL) {
1916 GST_DEBUG_OBJECT (playbin, "requesting new sink pad %d", select->type);
1918 gst_play_sink_request_pad (playbin->playsink, select->type);
1919 res = gst_pad_link (select->srcpad, select->sinkpad);
1920 GST_DEBUG_OBJECT (playbin, "linked type %s, result: %d", select->media,
1922 if (res != GST_PAD_LINK_OK) {
1923 GST_ELEMENT_ERROR (playbin, CORE, PAD,
1924 ("Internal playbin error."),
1925 ("Failed to link selector to sink. Error %d", res));
1929 GST_DEBUG_OBJECT (playbin, "pending %d > %d", group->pending,
1930 group->pending - 1);
1932 if (group->pending > 0)
1935 if (group->pending == 0) {
1936 /* we are the last group to complete, we will configure the output and then
1937 * signal the other waiters. */
1938 GST_LOG_OBJECT (playbin, "last group complete");
1941 GST_LOG_OBJECT (playbin, "have more pending groups");
1943 /* check if there are more decodebins to wait for */
1944 while (group->pending) {
1945 GST_DEBUG_OBJECT (playbin, "%d pending in group %p, waiting",
1946 group->pending, group);
1947 /* FIXME, unlock when shutting down */
1948 GST_SOURCE_GROUP_WAIT (group);
1951 GST_SOURCE_GROUP_UNLOCK (group);
1954 GST_LOG_OBJECT (playbin, "reconfigure sink");
1955 /* we configure the modes if we were the last decodebin to complete. */
1956 gst_play_sink_reconfigure (playbin->playsink);
1958 /* signal the other decodebins that they can continue now. */
1959 GST_SOURCE_GROUP_LOCK (group);
1960 /* unblock all selectors */
1961 for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
1962 GstSourceSelect *select = &group->selector[i];
1964 if (select->selector) {
1965 GST_DEBUG_OBJECT (playbin, "unblocking %" GST_PTR_FORMAT,
1967 gst_pad_set_blocked_async (select->srcpad, FALSE, selector_blocked,
1971 GST_DEBUG_OBJECT (playbin, "signal other decodebins");
1972 GST_SOURCE_GROUP_BROADCAST (group);
1973 GST_SOURCE_GROUP_UNLOCK (group);
1976 GST_PLAY_BIN_SHUTDOWN_UNLOCK (playbin);
1982 GST_DEBUG ("ignoring, we are shutting down");
1983 /* Request a flushing pad from playsink that we then link to the selector.
1984 * Then we unblock the selectors so that they stop with a WRONG_STATE
1985 * instead of a NOT_LINKED error.
1987 GST_SOURCE_GROUP_LOCK (group);
1988 for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
1989 GstSourceSelect *select = &group->selector[i];
1991 if (select->selector && select->sinkpad == NULL) {
1992 GST_DEBUG_OBJECT (playbin, "requesting new flushing sink pad");
1994 gst_play_sink_request_pad (playbin->playsink,
1995 GST_PLAY_SINK_TYPE_FLUSHING);
1996 res = gst_pad_link (select->srcpad, select->sinkpad);
1997 GST_DEBUG_OBJECT (playbin, "linked flushing, result: %d", res);
1999 if (select->srcpad) {
2000 GST_DEBUG_OBJECT (playbin, "unblocking %" GST_PTR_FORMAT,
2002 gst_pad_set_blocked_async (select->srcpad, FALSE, selector_blocked,
2006 GST_SOURCE_GROUP_UNLOCK (group);
2012 drained_cb (GstElement * decodebin, GstSourceGroup * group)
2014 GstPlayBin *playbin;
2016 playbin = group->playbin;
2018 GST_DEBUG_OBJECT (playbin, "about to finish in group %p", group);
2020 /* mark us as sending out the about-to-finish signal. When the app sets a URI
2021 * when this signal is emitted, we're marking it as next-uri */
2022 playbin->about_to_finish = TRUE;
2024 /* after this call, we should have a next group to activate or we EOS */
2025 g_signal_emit (G_OBJECT (playbin),
2026 gst_play_bin_signals[SIGNAL_ABOUT_TO_FINISH], 0, NULL);
2028 playbin->about_to_finish = FALSE;
2030 /* now activate the next group. If the app did not set a next-uri, this will
2031 * fail and we can do EOS */
2032 setup_next_source (playbin);
2035 /* Called when we must provide a list of factories to plug to @pad with @caps.
2036 * We first check if we have a sink that can handle the format and if we do, we
2037 * return NULL, to expose the pad. If we have no sink (or the sink does not
2038 * work), we return the list of elements that can connect. */
2039 static GValueArray *
2040 autoplug_factories_cb (GstElement * decodebin, GstPad * pad,
2041 GstCaps * caps, GstSourceGroup * group)
2043 GstPlayBin *playbin;
2044 GValueArray *result;
2046 playbin = group->playbin;
2048 GST_DEBUG_OBJECT (playbin, "factories group %p for %s:%s, %" GST_PTR_FORMAT,
2049 group, GST_DEBUG_PAD_NAME (pad), caps);
2051 /* filter out the elements based on the caps. */
2052 result = gst_factory_list_filter (playbin->elements, caps);
2054 GST_DEBUG_OBJECT (playbin, "found factories %p", result);
2055 gst_factory_list_debug (result);
2060 /* We are asked to select an element. See if the next element to check
2061 * is a sink. If this is the case, we see if the sink works by setting it to
2062 * READY. If the sink works, we return SELECT_EXPOSE to make decodebin
2063 * expose the raw pad so that we can setup the mixers. */
2064 static GstAutoplugSelectResult
2065 autoplug_select_cb (GstElement * decodebin, GstPad * pad,
2066 GstCaps * caps, GstElementFactory * factory, GstSourceGroup * group)
2068 GstPlayBin *playbin;
2069 GstElement *element;
2072 playbin = group->playbin;
2074 GST_DEBUG_OBJECT (playbin, "select group %p for %s:%s, %" GST_PTR_FORMAT,
2075 group, GST_DEBUG_PAD_NAME (pad), caps);
2077 GST_DEBUG_OBJECT (playbin, "checking factory %s",
2078 GST_PLUGIN_FEATURE_NAME (factory));
2080 /* if it's not a sink, we just make decodebin try it */
2081 if (!gst_factory_list_is_type (factory, GST_FACTORY_LIST_SINK))
2082 return GST_AUTOPLUG_SELECT_TRY;
2084 /* it's a sink, see if an instance of it actually works */
2085 GST_DEBUG_OBJECT (playbin, "we found a sink");
2087 klass = gst_element_factory_get_klass (factory);
2089 /* if we are asked to do visualisations and it's an audio sink, skip the
2090 * element. We can only do visualisations with raw sinks */
2091 if (gst_play_sink_get_flags (playbin->playsink) & GST_PLAY_FLAG_VIS) {
2092 if (strstr (klass, "Audio")) {
2093 GST_DEBUG_OBJECT (playbin, "skip audio sink because of vis");
2094 return GST_AUTOPLUG_SELECT_SKIP;
2098 if ((element = gst_element_factory_create (factory, NULL)) == NULL) {
2099 GST_WARNING_OBJECT (playbin, "Could not create an element from %s",
2100 gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
2101 return GST_AUTOPLUG_SELECT_SKIP;
2104 /* ... activate it ... We do this before adding it to the bin so that we
2105 * don't accidentally make it post error messages that will stop
2107 if ((gst_element_set_state (element,
2108 GST_STATE_READY)) == GST_STATE_CHANGE_FAILURE) {
2109 GST_WARNING_OBJECT (playbin, "Couldn't set %s to READY",
2110 GST_ELEMENT_NAME (element));
2111 gst_object_unref (element);
2112 return GST_AUTOPLUG_SELECT_SKIP;
2115 /* get klass to figure out if it's audio or video */
2116 if (strstr (klass, "Audio")) {
2117 GST_DEBUG_OBJECT (playbin, "configure audio sink");
2118 gst_play_sink_set_audio_sink (playbin->playsink, element);
2119 g_object_notify (G_OBJECT (playbin), "audio-sink");
2120 } else if (strstr (klass, "Video")) {
2121 GST_DEBUG_OBJECT (playbin, "configure video sink");
2122 gst_play_sink_set_video_sink (playbin->playsink, element);
2123 g_object_notify (G_OBJECT (playbin), "video-sink");
2125 GST_WARNING_OBJECT (playbin, "unknown sink klass %s found", klass);
2128 /* tell decodebin to expose the pad because we are going to use this
2130 GST_DEBUG_OBJECT (playbin, "we found a working sink, expose pad");
2132 return GST_AUTOPLUG_SELECT_EXPOSE;
2136 notify_source_cb (GstElement * uridecodebin, GParamSpec * pspec,
2137 GstSourceGroup * group)
2139 GstPlayBin *playbin;
2142 playbin = group->playbin;
2144 GST_OBJECT_LOCK (playbin);
2145 g_object_get (group->uridecodebin, "source", &source, NULL);
2146 if (playbin->source)
2147 gst_object_unref (playbin->source);
2148 playbin->source = source;
2149 GST_OBJECT_UNLOCK (playbin);
2151 g_object_notify (G_OBJECT (playbin), "source");
2154 /* must be called with the group lock */
2156 group_set_locked_state_unlocked (GstPlayBin * playbin, GstSourceGroup * group,
2159 GST_DEBUG_OBJECT (playbin, "locked_state %d on group %p", locked, group);
2161 if (group->uridecodebin)
2162 gst_element_set_locked_state (group->uridecodebin, locked);
2163 if (group->suburidecodebin)
2164 gst_element_set_locked_state (group->suburidecodebin, locked);
2169 #define REMOVE_SIGNAL(obj,id) \
2171 g_signal_handler_disconnect (obj, id); \
2175 /* must be called with PLAY_BIN_LOCK */
2177 activate_group (GstPlayBin * playbin, GstSourceGroup * group)
2179 GstElement *uridecodebin;
2180 GstElement *suburidecodebin = NULL;
2182 g_return_val_if_fail (group->valid, FALSE);
2183 g_return_val_if_fail (!group->active, FALSE);
2185 GST_SOURCE_GROUP_LOCK (group);
2186 if (group->uridecodebin) {
2187 GST_DEBUG_OBJECT (playbin, "reusing existing uridecodebin");
2188 REMOVE_SIGNAL (group->uridecodebin, group->pad_added_id);
2189 REMOVE_SIGNAL (group->uridecodebin, group->pad_removed_id);
2190 REMOVE_SIGNAL (group->uridecodebin, group->no_more_pads_id);
2191 REMOVE_SIGNAL (group->uridecodebin, group->notify_source_id);
2192 REMOVE_SIGNAL (group->uridecodebin, group->drained_id);
2193 REMOVE_SIGNAL (group->uridecodebin, group->autoplug_factories_id);
2194 REMOVE_SIGNAL (group->uridecodebin, group->autoplug_select_id);
2195 gst_element_set_state (group->uridecodebin, GST_STATE_NULL);
2196 uridecodebin = group->uridecodebin;
2198 GST_DEBUG_OBJECT (playbin, "making new uridecodebin");
2199 uridecodebin = gst_element_factory_make ("uridecodebin", NULL);
2202 gst_bin_add (GST_BIN_CAST (playbin), uridecodebin);
2203 group->uridecodebin = uridecodebin;
2206 /* configure connection speed */
2207 g_object_set (uridecodebin, "connection-speed", playbin->connection_speed,
2209 /* configure subtitle encoding */
2210 g_object_set (uridecodebin, "subtitle-encoding", playbin->encoding, NULL);
2212 g_object_set (uridecodebin, "uri", group->uri, NULL);
2213 g_object_set (uridecodebin, "buffer-duration", playbin->buffer_duration,
2215 g_object_set (uridecodebin, "buffer-size", playbin->buffer_size, NULL);
2217 /* connect pads and other things */
2218 group->pad_added_id = g_signal_connect (uridecodebin, "pad-added",
2219 G_CALLBACK (pad_added_cb), group);
2220 group->pad_removed_id = g_signal_connect (uridecodebin, "pad-removed",
2221 G_CALLBACK (pad_removed_cb), group);
2222 group->no_more_pads_id = g_signal_connect (uridecodebin, "no-more-pads",
2223 G_CALLBACK (no_more_pads_cb), group);
2224 group->notify_source_id = g_signal_connect (uridecodebin, "notify::source",
2225 G_CALLBACK (notify_source_cb), group);
2226 /* we have 1 pending no-more-pads */
2229 /* is called when the uridecodebin is out of data and we can switch to the
2232 g_signal_connect (uridecodebin, "drained", G_CALLBACK (drained_cb),
2235 /* will be called when a new media type is found. We return a list of decoders
2236 * including sinks for decodebin to try */
2237 group->autoplug_factories_id =
2238 g_signal_connect (uridecodebin, "autoplug-factories",
2239 G_CALLBACK (autoplug_factories_cb), group);
2240 group->autoplug_select_id = g_signal_connect (uridecodebin, "autoplug-select",
2241 G_CALLBACK (autoplug_select_cb), group);
2243 if (group->suburi) {
2245 if (group->suburidecodebin) {
2246 GST_DEBUG_OBJECT (playbin, "reusing existing suburidecodebin");
2247 REMOVE_SIGNAL (group->suburidecodebin, group->sub_pad_added_id);
2248 REMOVE_SIGNAL (group->suburidecodebin, group->sub_pad_removed_id);
2249 REMOVE_SIGNAL (group->suburidecodebin, group->sub_no_more_pads_id);
2250 gst_element_set_state (group->suburidecodebin, GST_STATE_NULL);
2251 suburidecodebin = group->suburidecodebin;
2253 GST_DEBUG_OBJECT (playbin, "making new suburidecodebin");
2254 suburidecodebin = gst_element_factory_make ("uridecodebin", NULL);
2255 if (!suburidecodebin)
2258 gst_bin_add (GST_BIN_CAST (playbin), suburidecodebin);
2259 group->suburidecodebin = suburidecodebin;
2262 /* configure connection speed */
2263 g_object_set (suburidecodebin, "connection-speed",
2264 playbin->connection_speed, NULL);
2265 /* configure subtitle encoding */
2266 g_object_set (suburidecodebin, "subtitle-encoding", playbin->encoding,
2269 g_object_set (suburidecodebin, "uri", group->suburi, NULL);
2271 /* connect pads and other things */
2272 group->sub_pad_added_id = g_signal_connect (suburidecodebin, "pad-added",
2273 G_CALLBACK (pad_added_cb), group);
2274 group->sub_pad_removed_id = g_signal_connect (suburidecodebin,
2275 "pad-removed", G_CALLBACK (pad_removed_cb), group);
2276 group->sub_no_more_pads_id = g_signal_connect (suburidecodebin,
2277 "no-more-pads", G_CALLBACK (no_more_pads_cb), group);
2279 /* we have 2 pending no-more-pads */
2283 /* release the group lock before setting the state of the decodebins, they
2284 * might fire signals in this thread that we need to handle with the
2285 * group_lock taken. */
2286 GST_SOURCE_GROUP_UNLOCK (group);
2288 if (suburidecodebin) {
2289 if (gst_element_set_state (suburidecodebin,
2290 GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE)
2291 goto suburidecodebin_failure;
2293 if (gst_element_set_state (uridecodebin,
2294 GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE)
2295 goto uridecodebin_failure;
2297 GST_SOURCE_GROUP_LOCK (group);
2298 /* alow state changes of the playbin2 affect the group elements now */
2299 group_set_locked_state_unlocked (playbin, group, FALSE);
2300 group->active = TRUE;
2301 GST_SOURCE_GROUP_UNLOCK (group);
2308 GST_SOURCE_GROUP_UNLOCK (group);
2311 suburidecodebin_failure:
2313 GST_DEBUG_OBJECT (playbin, "failed state change of subtitle uridecodebin");
2316 uridecodebin_failure:
2318 GST_DEBUG_OBJECT (playbin, "failed state change of uridecodebin");
2323 /* unlink a group of uridecodebins from the sink.
2324 * must be called with PLAY_BIN_LOCK */
2326 deactivate_group (GstPlayBin * playbin, GstSourceGroup * group)
2330 g_return_val_if_fail (group->valid, FALSE);
2331 g_return_val_if_fail (group->active, FALSE);
2333 GST_DEBUG_OBJECT (playbin, "unlinking group %p", group);
2335 GST_SOURCE_GROUP_LOCK (group);
2336 group->active = FALSE;
2337 for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) {
2338 GstSourceSelect *select = &group->selector[i];
2340 if (!select->selector)
2343 GST_DEBUG_OBJECT (playbin, "unlinking selector %s", select->media);
2345 if (select->sinkpad) {
2346 GST_LOG_OBJECT (playbin, "unlinking from sink");
2347 gst_pad_unlink (select->srcpad, select->sinkpad);
2350 GST_LOG_OBJECT (playbin, "release sink pad");
2351 gst_play_sink_release_pad (playbin->playsink, select->sinkpad);
2352 select->sinkpad = NULL;
2355 gst_object_unref (select->srcpad);
2356 select->srcpad = NULL;
2358 gst_element_set_state (select->selector, GST_STATE_NULL);
2359 gst_bin_remove (GST_BIN_CAST (playbin), select->selector);
2360 select->selector = NULL;
2362 /* we still have the decodebins added to the playbin2 but we can't remove them
2363 * yet or change their state because this function might be called from the
2364 * streaming threads, instead block the state so that state changes on the
2365 * playbin2 don't affect us anymore */
2366 group_set_locked_state_unlocked (playbin, group, TRUE);
2367 GST_SOURCE_GROUP_UNLOCK (group);
2372 /* setup the next group to play, this assumes the next_group is valid and
2373 * configured. It swaps out the current_group and activates the valid
2376 setup_next_source (GstPlayBin * playbin)
2378 GstSourceGroup *new_group, *old_group;
2380 GST_DEBUG_OBJECT (playbin, "setup sources");
2382 /* see if there is a next group */
2383 GST_PLAY_BIN_LOCK (playbin);
2384 new_group = playbin->next_group;
2385 if (!new_group || !new_group->valid)
2388 /* first unlink the current source, if any */
2389 old_group = playbin->curr_group;
2390 if (old_group && old_group->valid) {
2391 /* unlink our pads with the sink */
2392 deactivate_group (playbin, old_group);
2393 old_group->valid = FALSE;
2396 /* activate the new group */
2397 if (!activate_group (playbin, new_group))
2398 goto activate_failed;
2400 /* swap old and new */
2401 playbin->curr_group = new_group;
2402 playbin->next_group = old_group;
2403 GST_PLAY_BIN_UNLOCK (playbin);
2410 GST_DEBUG_OBJECT (playbin, "no next group");
2411 GST_PLAY_BIN_UNLOCK (playbin);
2416 GST_DEBUG_OBJECT (playbin, "activate failed");
2417 GST_PLAY_BIN_UNLOCK (playbin);
2422 /* The group that is currently playing is copied again to the
2423 * next_group so that it will start playing the next time.
2426 save_current_group (GstPlayBin * playbin)
2428 GstSourceGroup *curr_group;
2430 GST_DEBUG_OBJECT (playbin, "save current group");
2432 /* see if there is a current group */
2433 GST_PLAY_BIN_LOCK (playbin);
2434 curr_group = playbin->curr_group;
2435 if (curr_group && curr_group->valid) {
2436 /* unlink our pads with the sink */
2437 deactivate_group (playbin, curr_group);
2439 /* swap old and new */
2440 playbin->curr_group = playbin->next_group;
2441 playbin->next_group = curr_group;
2442 GST_PLAY_BIN_UNLOCK (playbin);
2447 /* clear the locked state from all groups. This function is called before a
2448 * state change to NULL is performed on them. */
2450 groups_set_locked_state (GstPlayBin * playbin, gboolean locked)
2452 GST_DEBUG_OBJECT (playbin, "setting locked state to %d on all groups",
2455 GST_PLAY_BIN_LOCK (playbin);
2456 GST_SOURCE_GROUP_LOCK (playbin->curr_group);
2457 group_set_locked_state_unlocked (playbin, playbin->curr_group, locked);
2458 GST_SOURCE_GROUP_UNLOCK (playbin->curr_group);
2459 GST_SOURCE_GROUP_LOCK (playbin->next_group);
2460 group_set_locked_state_unlocked (playbin, playbin->next_group, locked);
2461 GST_SOURCE_GROUP_UNLOCK (playbin->next_group);
2462 GST_PLAY_BIN_UNLOCK (playbin);
2467 static GstStateChangeReturn
2468 gst_play_bin_change_state (GstElement * element, GstStateChange transition)
2470 GstStateChangeReturn ret;
2471 GstPlayBin *playbin;
2473 playbin = GST_PLAY_BIN (element);
2475 switch (transition) {
2476 case GST_STATE_CHANGE_READY_TO_PAUSED:
2477 GST_LOG_OBJECT (playbin, "clearing shutdown flag");
2478 g_atomic_int_set (&playbin->shutdown, 0);
2479 if (!setup_next_source (playbin))
2482 case GST_STATE_CHANGE_PAUSED_TO_READY:
2483 /* FIXME unlock our waiting groups */
2484 GST_LOG_OBJECT (playbin, "setting shutdown flag");
2485 g_atomic_int_set (&playbin->shutdown, 1);
2486 /* wait for all callbacks to end by taking the lock.
2487 * No dynamic (critical) new callbacks will
2488 * be able to happen as we set the shutdown flag. */
2489 GST_PLAY_BIN_DYN_LOCK (playbin);
2490 GST_LOG_OBJECT (playbin, "dynamic lock taken, we can continue shutdown");
2491 GST_PLAY_BIN_DYN_UNLOCK (playbin);
2493 case GST_STATE_CHANGE_READY_TO_NULL:
2494 /* unlock so that all groups go to NULL */
2495 groups_set_locked_state (playbin, FALSE);
2501 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2502 if (ret == GST_STATE_CHANGE_FAILURE)
2505 switch (transition) {
2506 case GST_STATE_CHANGE_READY_TO_PAUSED:
2508 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
2509 /* FIXME Release audio device when we implement that */
2511 case GST_STATE_CHANGE_PAUSED_TO_READY:
2512 save_current_group (playbin);
2514 case GST_STATE_CHANGE_READY_TO_NULL:
2515 /* make sure the groups don't perform a state change anymore until we
2516 * enable them again */
2517 groups_set_locked_state (playbin, TRUE);
2528 return GST_STATE_CHANGE_FAILURE;
2533 gst_play_bin2_plugin_init (GstPlugin * plugin)
2535 GST_DEBUG_CATEGORY_INIT (gst_play_bin_debug, "playbin2", 0, "play bin");
2537 return gst_element_register (plugin, "playbin2", GST_RANK_NONE,