[svn r860] moved playbinmaemo to maemo-myth project 'https://garage.maemo.org/svn/mtv/trunk/gst'
1.1 --- a/gst-gmyth/Makefile.am Tue Sep 18 21:01:18 2007 +0100
1.2 +++ b/gst-gmyth/Makefile.am Mon Sep 24 16:06:54 2007 +0100
1.3 @@ -1,16 +1,8 @@
1.4 SUBDIRS = \
1.5 - nuvdemux \
1.6 - concatmux \
1.7 - playbinmaemo \
1.8 - decodebin2 \
1.9 - multiqueue
1.10 + nuvdemux
1.11
1.12 DIST_SUBDIRS = \
1.13 - nuvdemux \
1.14 - concatmux \
1.15 - playbinmaemo \
1.16 - decodebin2 \
1.17 - multiqueue
1.18 + nuvdemux
1.19
1.20 if WITH_GMYTH
1.21 SUBDIRS += mythsrc
2.1 --- a/gst-gmyth/configure.ac Tue Sep 18 21:01:18 2007 +0100
2.2 +++ b/gst-gmyth/configure.ac Mon Sep 24 16:06:54 2007 +0100
2.3 @@ -144,10 +144,6 @@
2.4 AC_OUTPUT( \
2.5 Makefile \
2.6 nuvdemux/Makefile \
2.7 - mythsrc/Makefile \
2.8 - concatmux/Makefile \
2.9 - playbinmaemo/Makefile \
2.10 - decodebin2/Makefile \
2.11 - multiqueue/Makefile
2.12 + mythsrc/Makefile
2.13 )
2.14
3.1 --- a/gst-gmyth/debian/control Tue Sep 18 21:01:18 2007 +0100
3.2 +++ b/gst-gmyth/debian/control Mon Sep 24 16:06:54 2007 +0100
3.3 @@ -21,21 +21,6 @@
3.4 Description: INdT mythtv source GStreamer plugin
3.5 This GStreamer plugin permits read streamer from MythTv Server
3.6
3.7 -Package: gstreamer0.10-indt-concatmux
3.8 -Architecture: any
3.9 -Section: user/library
3.10 -Depends: ${misc:Depends}, ${shlibs:Depends}
3.11 -Description: INdT Concat Stream Mux GStreamer plugin
3.12 - This GStreamer plugin permits contact any stream in a single stream
3.13 -
3.14 -Package: gstreamer0.10-indt-playbinmaemo
3.15 -Architecture: any
3.16 -Section: user/library
3.17 -Depends: ${misc:Depends}, ${shlibs:Depends}
3.18 -Description: INdT Playbinmaemo GStreamer plugin
3.19 - Contains some necessary gstreamear elemenets and playbinmaemo autoplug element
3.20 -
3.21 -
3.22 Package: maemo-nuvdemux
3.23 Architecture: all
3.24 Section: user/library
4.1 --- a/gst-gmyth/decodebin2/Makefile.am Tue Sep 18 21:01:18 2007 +0100
4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
4.3 @@ -1,23 +0,0 @@
4.4 -plugin_LTLIBRARIES = libgstdecodebin2.la
4.5 -
4.6 -libgstdecodebin2_la_SOURCES = \
4.7 - gstdecodebin2.c \
4.8 - gstplay-marshal.c
4.9 -
4.10 -libgstdecodebin2_la_CFLAGS = \
4.11 - $(GST_CFLAGS) \
4.12 - $(GST_BASE_CFLAGS) \
4.13 - $(GST_PLUGINS_BASE_CFLAGS)
4.14 -
4.15 -libgstdecodebin2_la_LIBADD = \
4.16 - $(GST_LIBS_LIBS)
4.17 -
4.18 -libgstdecodebin2_la_LDFLAGS = \
4.19 - $(GST_LIBS) \
4.20 - $(GST_PLUGIN_LDFLAGS) \
4.21 - $(GST_BASE_LIBS) \
4.22 - $(GST_PLUGINS_BASE_LIBS)
4.23 -
4.24 -noinst_HEADERS = \
4.25 - gstplay-marshal.h
4.26 -
5.1 --- a/gst-gmyth/decodebin2/gstdecodebin2.c Tue Sep 18 21:01:18 2007 +0100
5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
5.3 @@ -1,2113 +0,0 @@
5.4 -/* GStreamer
5.5 - * Copyright (C) <2006> Edward Hervey <edward@fluendo.com>
5.6 - *
5.7 - * This library is free software; you can redistribute it and/or
5.8 - * modify it under the terms of the GNU Library General Public
5.9 - * License as published by the Free Software Foundation; either
5.10 - * version 2 of the License, or (at your option) any later version.
5.11 - *
5.12 - * This library is distributed in the hope that it will be useful,
5.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
5.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5.15 - * Library General Public License for more details.
5.16 - *
5.17 - * You should have received a copy of the GNU Library General Public
5.18 - * License along with this library; if not, write to the
5.19 - * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
5.20 - * Boston, MA 02111-1307, USA.
5.21 - */
5.22 -
5.23 -/**
5.24 - * SECTION:element-decodebin2
5.25 - * @short_description: Next-generation automatic decoding bin
5.26 - *
5.27 - * #GstBin that auto-magically constructs a decoding pipeline using available
5.28 - * decoders and demuxers via auto-plugging.
5.29 - *
5.30 - * At this stage, decodebin2 is considered UNSTABLE. The API provided in the
5.31 - * signals is expected to change in the near future.
5.32 - *
5.33 - * To try out decodebin2, you can set the USE_DECODEBIN2 environment
5.34 - * variable (USE_DECODEBIN2=1 for example). This will cause playbin to use
5.35 - * decodebin2 instead of the older decodebin for its internal auto-plugging.
5.36 - */
5.37 -
5.38 -#ifdef HAVE_CONFIG_H
5.39 -#include "config.h"
5.40 -#endif
5.41 -
5.42 -#include <string.h>
5.43 -#include <gst/gst.h>
5.44 -
5.45 -#include "gstplay-marshal.h"
5.46 -
5.47 -/* generic templates */
5.48 -static GstStaticPadTemplate decoder_bin_sink_template =
5.49 -GST_STATIC_PAD_TEMPLATE ("sink",
5.50 - GST_PAD_SINK,
5.51 - GST_PAD_ALWAYS,
5.52 - GST_STATIC_CAPS_ANY);
5.53 -
5.54 -static GstStaticPadTemplate decoder_bin_src_template =
5.55 -GST_STATIC_PAD_TEMPLATE ("src%d",
5.56 - GST_PAD_SRC,
5.57 - GST_PAD_SOMETIMES,
5.58 - GST_STATIC_CAPS_ANY);
5.59 -
5.60 -GST_DEBUG_CATEGORY_STATIC (gst_decode_bin_debug);
5.61 -#define GST_CAT_DEFAULT gst_decode_bin_debug
5.62 -
5.63 -typedef struct _GstDecodeGroup GstDecodeGroup;
5.64 -typedef struct _GstDecodePad GstDecodePad;
5.65 -typedef struct _GstDecodeBin GstDecodeBin;
5.66 -typedef struct _GstDecodeBin GstDecodeBin2;
5.67 -typedef struct _GstDecodeBinClass GstDecodeBinClass;
5.68 -
5.69 -#define GST_TYPE_DECODE_BIN (gst_decode_bin_get_type())
5.70 -#define GST_DECODE_BIN_CAST(obj) ((GstDecodeBin*)(obj))
5.71 -#define GST_DECODE_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DECODE_BIN,GstDecodeBin))
5.72 -#define GST_DECODE_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DECODE_BIN,GstDecodeBinClass))
5.73 -#define GST_IS_DECODE_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DECODE_BIN))
5.74 -#define GST_IS_DECODE_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DECODE_BIN))
5.75 -
5.76 -/**
5.77 - * GstDecodeBin2:
5.78 - *
5.79 - * The opaque #DecodeBin2 data structure
5.80 - */
5.81 -struct _GstDecodeBin
5.82 -{
5.83 - GstBin bin; /* we extend GstBin */
5.84 -
5.85 - GstElement *typefind; /* this holds the typefind object */
5.86 - GstElement *fakesink;
5.87 -
5.88 - GMutex *lock; /* Protects activegroup and groups */
5.89 - GstDecodeGroup *activegroup; /* group currently active */
5.90 - GList *groups; /* List of non-active GstDecodeGroups, sorted in
5.91 - * order of creation. */
5.92 - GList *oldgroups; /* List of no-longer-used GstDecodeGroups.
5.93 - * Should be freed in dispose */
5.94 - gint nbpads; /* unique identifier for source pads */
5.95 - GstCaps *caps; /* caps on which to stop decoding */
5.96 -
5.97 - GList *factories; /* factories we can use for selecting elements */
5.98 -};
5.99 -
5.100 -struct _GstDecodeBinClass
5.101 -{
5.102 - GstBinClass parent_class;
5.103 -
5.104 - /* signal we fire when a new pad has been decoded into raw audio/video */
5.105 - void (*new_decoded_pad) (GstElement * element, GstPad * pad, gboolean last);
5.106 - /* signal we fire when a pad has been removed */
5.107 - void (*removed_decoded_pad) (GstElement * element, GstPad * pad);
5.108 - /* signal fired when we found a pad that we cannot decode */
5.109 - void (*unknown_type) (GstElement * element, GstPad * pad, GstCaps * caps);
5.110 - /* signal fired to know if we continue trying to decode the given caps */
5.111 - gboolean (*autoplug_continue) (GstElement * element, GstCaps * caps);
5.112 - /* signal fired to reorder the proposed list of factories */
5.113 - gboolean (*autoplug_sort) (GstElement * element, GstCaps * caps,
5.114 - GList ** list);
5.115 -};
5.116 -
5.117 -/* signals */
5.118 -enum
5.119 -{
5.120 - SIGNAL_NEW_DECODED_PAD,
5.121 - SIGNAL_REMOVED_DECODED_PAD,
5.122 - SIGNAL_UNKNOWN_TYPE,
5.123 - SIGNAL_AUTOPLUG_CONTINUE,
5.124 - SIGNAL_AUTOPLUG_SORT,
5.125 - LAST_SIGNAL
5.126 -};
5.127 -
5.128 -/* Properties */
5.129 -enum
5.130 -{
5.131 - PROP_0,
5.132 - PROP_CAPS,
5.133 -};
5.134 -
5.135 -static GstBinClass *parent_class;
5.136 -static guint gst_decode_bin_signals[LAST_SIGNAL] = { 0 };
5.137 -
5.138 -static const GstElementDetails gst_decode_bin_details =
5.139 -GST_ELEMENT_DETAILS ("Decoder Bin",
5.140 - "Generic/Bin/Decoder",
5.141 - "Autoplug and decode to raw media",
5.142 - "Edward Hervey <edward@fluendo.com>");
5.143 -
5.144 -
5.145 -static gboolean add_fakesink (GstDecodeBin * decode_bin);
5.146 -static void remove_fakesink (GstDecodeBin * decode_bin);
5.147 -
5.148 -static void type_found (GstElement * typefind, guint probability,
5.149 - GstCaps * caps, GstDecodeBin * decode_bin);
5.150 -
5.151 -static gboolean gst_decode_bin_autoplug_continue (GstElement * element,
5.152 - GstCaps * caps);
5.153 -static gboolean gst_decode_bin_autoplug_sort (GstElement * element,
5.154 - GstCaps * caps, GList ** list);
5.155 -static void gst_decode_bin_set_property (GObject * object, guint prop_id,
5.156 - const GValue * value, GParamSpec * pspec);
5.157 -static void gst_decode_bin_get_property (GObject * object, guint prop_id,
5.158 - GValue * value, GParamSpec * pspec);
5.159 -static void gst_decode_bin_set_caps (GstDecodeBin * dbin, GstCaps * caps);
5.160 -static GstCaps *gst_decode_bin_get_caps (GstDecodeBin * dbin);
5.161 -
5.162 -static GstPad *find_sink_pad (GstElement * element);
5.163 -static GstStateChangeReturn gst_decode_bin_change_state (GstElement * element,
5.164 - GstStateChange transition);
5.165 -
5.166 -#define DECODE_BIN_LOCK(dbin) G_STMT_START { \
5.167 - GST_LOG_OBJECT (dbin, \
5.168 - "locking from thread %p", \
5.169 - g_thread_self ()); \
5.170 - g_mutex_lock (GST_DECODE_BIN_CAST(dbin)->lock); \
5.171 - GST_LOG_OBJECT (dbin, \
5.172 - "locked from thread %p", \
5.173 - g_thread_self ()); \
5.174 -} G_STMT_END
5.175 -
5.176 -#define DECODE_BIN_UNLOCK(dbin) G_STMT_START { \
5.177 - GST_LOG_OBJECT (dbin, \
5.178 - "unlocking from thread %p", \
5.179 - g_thread_self ()); \
5.180 - g_mutex_unlock (GST_DECODE_BIN_CAST(dbin)->lock); \
5.181 -} G_STMT_END
5.182 -
5.183 -/* GstDecodeGroup
5.184 - *
5.185 - * Streams belonging to the same group/chain of a media file
5.186 - *
5.187 - */
5.188 -
5.189 -struct _GstDecodeGroup
5.190 -{
5.191 - GstDecodeBin *dbin;
5.192 - GMutex *lock;
5.193 - GstElement *multiqueue;
5.194 - gboolean exposed; /* TRUE if this group is exposed */
5.195 - gboolean drained; /* TRUE if EOS went throug all endpads */
5.196 - gboolean blocked; /* TRUE if all endpads are blocked */
5.197 - gboolean complete; /* TRUE if we are not expecting anymore streams
5.198 - * on this group */
5.199 - gulong overrunsig;
5.200 - gulong underrunsig;
5.201 - guint nbdynamic; /* number of dynamic pads in the group. */
5.202 -
5.203 - GList *endpads; /* List of GstDecodePad of source pads to be exposed */
5.204 - GList *ghosts; /* List of GstGhostPad for the endpads */
5.205 -};
5.206 -
5.207 -#define GROUP_MUTEX_LOCK(group) G_STMT_START { \
5.208 - GST_LOG_OBJECT (group->dbin, \
5.209 - "locking group %p from thread %p", \
5.210 - group, g_thread_self ()); \
5.211 - g_mutex_lock (group->lock); \
5.212 - GST_LOG_OBJECT (group->dbin, \
5.213 - "locked group %p from thread %p", \
5.214 - group, g_thread_self ()); \
5.215 -} G_STMT_END
5.216 -
5.217 -#define GROUP_MUTEX_UNLOCK(group) G_STMT_START { \
5.218 - GST_LOG_OBJECT (group->dbin, \
5.219 - "unlocking group %p from thread %p", \
5.220 - group, g_thread_self ()); \
5.221 - g_mutex_unlock (group->lock); \
5.222 -} G_STMT_END
5.223 -
5.224 -
5.225 -static GstDecodeGroup *gst_decode_group_new (GstDecodeBin * decode_bin);
5.226 -static GstPad *gst_decode_group_control_demuxer_pad (GstDecodeGroup * group,
5.227 - GstPad * pad);
5.228 -static gboolean gst_decode_group_control_source_pad (GstDecodeGroup * group,
5.229 - GstPad * pad);
5.230 -static gboolean gst_decode_group_expose (GstDecodeGroup * group);
5.231 -static void gst_decode_group_check_if_blocked (GstDecodeGroup * group);
5.232 -static void gst_decode_group_set_complete (GstDecodeGroup * group);
5.233 -static void gst_decode_group_hide (GstDecodeGroup * group);
5.234 -static void gst_decode_group_free (GstDecodeGroup * group);
5.235 -
5.236 -/* GstDecodePad
5.237 - *
5.238 - * GstPad private used for source pads of groups
5.239 - */
5.240 -
5.241 -struct _GstDecodePad
5.242 -{
5.243 - GstPad *pad;
5.244 - GstDecodeGroup *group;
5.245 - gboolean blocked;
5.246 - gboolean drained;
5.247 -};
5.248 -
5.249 -static GstDecodePad *gst_decode_pad_new (GstDecodeGroup * group, GstPad * pad,
5.250 - gboolean block);
5.251 -static void source_pad_blocked_cb (GstPad * pad, gboolean blocked,
5.252 - GstDecodePad * dpad);
5.253 -
5.254 -/* TempPadStruct
5.255 - * Internal structure used for pads which have more than one structure.
5.256 - */
5.257 -typedef struct _TempPadStruct
5.258 -{
5.259 - GstDecodeBin *dbin;
5.260 - GstDecodeGroup *group;
5.261 -} TempPadStruct;
5.262 -
5.263 -/********************************
5.264 - * Standard GObject boilerplate *
5.265 - ********************************/
5.266 -
5.267 -static void gst_decode_bin_class_init (GstDecodeBinClass * klass);
5.268 -static void gst_decode_bin_init (GstDecodeBin * decode_bin);
5.269 -static void gst_decode_bin_dispose (GObject * object);
5.270 -static void gst_decode_bin_finalize (GObject * object);
5.271 -
5.272 -static GType
5.273 -gst_decode_bin_get_type (void)
5.274 -{
5.275 - static GType gst_decode_bin_type = 0;
5.276 -
5.277 - if (!gst_decode_bin_type) {
5.278 - static const GTypeInfo gst_decode_bin_info = {
5.279 - sizeof (GstDecodeBinClass),
5.280 - NULL,
5.281 - NULL,
5.282 - (GClassInitFunc) gst_decode_bin_class_init,
5.283 - NULL,
5.284 - NULL,
5.285 - sizeof (GstDecodeBin),
5.286 - 0,
5.287 - (GInstanceInitFunc) gst_decode_bin_init,
5.288 - NULL
5.289 - };
5.290 -
5.291 - gst_decode_bin_type =
5.292 - g_type_register_static (GST_TYPE_BIN, "GstDecodeBin2",
5.293 - &gst_decode_bin_info, 0);
5.294 - }
5.295 -
5.296 - return gst_decode_bin_type;
5.297 -}
5.298 -
5.299 -static gboolean
5.300 -_gst_boolean_accumulator (GSignalInvocationHint * ihint,
5.301 - GValue * return_accu, const GValue * handler_return, gpointer dummy)
5.302 -{
5.303 - gboolean myboolean;
5.304 -
5.305 - myboolean = g_value_get_boolean (handler_return);
5.306 - if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
5.307 - g_value_set_boolean (return_accu, myboolean);
5.308 -
5.309 - /* stop emission if FALSE */
5.310 - return myboolean;
5.311 -}
5.312 -
5.313 -static void
5.314 -gst_decode_bin_class_init (GstDecodeBinClass * klass)
5.315 -{
5.316 - GObjectClass *gobject_klass;
5.317 - GstElementClass *gstelement_klass;
5.318 - GstBinClass *gstbin_klass;
5.319 -
5.320 - gobject_klass = (GObjectClass *) klass;
5.321 - gstelement_klass = (GstElementClass *) klass;
5.322 - gstbin_klass = (GstBinClass *) klass;
5.323 -
5.324 - parent_class = g_type_class_peek_parent (klass);
5.325 -
5.326 - gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_decode_bin_dispose);
5.327 - gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_decode_bin_finalize);
5.328 - gobject_klass->set_property = GST_DEBUG_FUNCPTR (gst_decode_bin_set_property);
5.329 - gobject_klass->get_property = GST_DEBUG_FUNCPTR (gst_decode_bin_get_property);
5.330 -
5.331 - /**
5.332 - * GstDecodeBin2::new-decoded-pad:
5.333 - * @pad: the newly created pad
5.334 - * @islast: #TRUE if this is the last pad to be added. Deprecated.
5.335 - *
5.336 - * This signal gets emitted as soon as a new pad of the same type as one of
5.337 - * the valid 'raw' types is added.
5.338 - */
5.339 -
5.340 - gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD] =
5.341 - g_signal_new ("new-decoded-pad", G_TYPE_FROM_CLASS (klass),
5.342 - G_SIGNAL_RUN_LAST,
5.343 - G_STRUCT_OFFSET (GstDecodeBinClass, new_decoded_pad), NULL, NULL,
5.344 - gst_play_marshal_VOID__OBJECT_BOOLEAN, G_TYPE_NONE, 2, GST_TYPE_PAD,
5.345 - G_TYPE_BOOLEAN);
5.346 -
5.347 - /**
5.348 - * GstDecodeBin2::removed-decoded-pad:
5.349 - * @pad: the pad that was removed
5.350 - *
5.351 - * This signal is emitted when a 'final' caps pad has been removed.
5.352 - */
5.353 -
5.354 - gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD] =
5.355 - g_signal_new ("removed-decoded-pad", G_TYPE_FROM_CLASS (klass),
5.356 - G_SIGNAL_RUN_LAST,
5.357 - G_STRUCT_OFFSET (GstDecodeBinClass, removed_decoded_pad), NULL, NULL,
5.358 - gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD);
5.359 -
5.360 - /**
5.361 - * GstDecodeBin2::unknown-type:
5.362 - * @pad: the new pad containing caps that cannot be resolved to a 'final' stream type.
5.363 - * @caps: the #GstCaps of the pad that cannot be resolved.
5.364 - *
5.365 - * This signal is emitted when a pad for which there is no further possible
5.366 - * decoding is added to the decodebin.
5.367 - */
5.368 -
5.369 - gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE] =
5.370 - g_signal_new ("unknown-type", G_TYPE_FROM_CLASS (klass),
5.371 - G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, unknown_type),
5.372 - NULL, NULL, gst_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2,
5.373 - GST_TYPE_PAD, GST_TYPE_CAPS);
5.374 -
5.375 - /**
5.376 - * GstDecodeBin2::autoplug-continue:
5.377 - * @caps: The #GstCaps found.
5.378 - *
5.379 - * This signal is emitted whenever decodebin2 finds a new stream. It is
5.380 - * emitted before looking for any elements that can handle that stream.
5.381 - *
5.382 - * Returns: #TRUE if you wish decodebin2 to look for elements that can
5.383 - * handle the given @caps. If #FALSE, those caps will be considered as
5.384 - * final and the pad will be exposed as such (see 'new-decoded-pad'
5.385 - * signal).
5.386 - */
5.387 -
5.388 - gst_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE] =
5.389 - g_signal_new ("autoplug-continue", G_TYPE_FROM_CLASS (klass),
5.390 - G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_continue),
5.391 - _gst_boolean_accumulator, NULL, gst_play_marshal_BOOLEAN__OBJECT,
5.392 - G_TYPE_BOOLEAN, 1, GST_TYPE_CAPS);
5.393 -
5.394 - /**
5.395 - * GstDecodeBin2::autoplug-sort:
5.396 - * @caps: The #GstCaps.
5.397 - * @factories: A #GList of possible #GstElementFactory to use.
5.398 - *
5.399 - * This signal is emitted once decodebin2 has found all the possible
5.400 - * #GstElementFactory that can be used to handle the given @caps.
5.401 - *
5.402 - * UNSTABLE API. Will change soon.
5.403 - *
5.404 - * Returns: #TRUE if you wish decodebin2 to start trying to decode
5.405 - * the given @caps with the list of factories. #FALSE if you do not want
5.406 - * these #GstCaps, if so the pad will be exposed as unknown (see
5.407 - * 'unknown-type' signal).
5.408 - */
5.409 -
5.410 - gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT] =
5.411 - g_signal_new ("autoplug-sort", G_TYPE_FROM_CLASS (klass),
5.412 - G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_sort),
5.413 - _gst_boolean_accumulator, NULL, gst_play_marshal_BOOLEAN__OBJECT_POINTER,
5.414 - G_TYPE_BOOLEAN, 2, GST_TYPE_CAPS, G_TYPE_POINTER);
5.415 -
5.416 - g_object_class_install_property (gobject_klass, PROP_CAPS,
5.417 - g_param_spec_boxed ("caps", "Caps", "The caps on which to stop decoding.",
5.418 - GST_TYPE_CAPS, G_PARAM_READWRITE));
5.419 -
5.420 - klass->autoplug_continue =
5.421 - GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_continue);
5.422 - klass->autoplug_sort = GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_sort);
5.423 -
5.424 - gst_element_class_add_pad_template (gstelement_klass,
5.425 - gst_static_pad_template_get (&decoder_bin_sink_template));
5.426 - gst_element_class_add_pad_template (gstelement_klass,
5.427 - gst_static_pad_template_get (&decoder_bin_src_template));
5.428 -
5.429 - gst_element_class_set_details (gstelement_klass, &gst_decode_bin_details);
5.430 -
5.431 - gstelement_klass->change_state =
5.432 - GST_DEBUG_FUNCPTR (gst_decode_bin_change_state);
5.433 -}
5.434 -
5.435 -/* the filter function for selecting the elements we can use in
5.436 - * autoplugging */
5.437 -static gboolean
5.438 -gst_decode_bin_factory_filter (GstPluginFeature * feature,
5.439 - GstDecodeBin * decode_bin)
5.440 -{
5.441 - guint rank;
5.442 - const gchar *klass;
5.443 -
5.444 - /* we only care about element factories */
5.445 - if (!GST_IS_ELEMENT_FACTORY (feature))
5.446 - return FALSE;
5.447 -
5.448 - klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature));
5.449 - /* only demuxers, decoders and parsers can play */
5.450 - if (strstr (klass, "Demux") == NULL &&
5.451 - strstr (klass, "Decoder") == NULL && strstr (klass, "Parse") == NULL) {
5.452 - return FALSE;
5.453 - }
5.454 -
5.455 - /* only select elements with autoplugging rank */
5.456 -#if 0
5.457 - rank = gst_plugin_feature_get_rank (feature);
5.458 - if (rank < GST_RANK_MARGINAL)
5.459 - return FALSE;
5.460 -#endif
5.461 -
5.462 - return TRUE;
5.463 -}
5.464 -
5.465 -/* function used to sort element features */
5.466 -static gint
5.467 -compare_ranks (GstPluginFeature * f1, GstPluginFeature * f2)
5.468 -{
5.469 - gint diff;
5.470 - const gchar *rname1, *rname2;
5.471 -
5.472 - diff = gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1);
5.473 - if (diff != 0)
5.474 - return diff;
5.475 -
5.476 - rname1 = gst_plugin_feature_get_name (f1);
5.477 - rname2 = gst_plugin_feature_get_name (f2);
5.478 -
5.479 - diff = strcmp (rname2, rname1);
5.480 -
5.481 - return diff;
5.482 -}
5.483 -
5.484 -static void
5.485 -print_feature (GstPluginFeature * feature)
5.486 -{
5.487 - const gchar *rname;
5.488 -
5.489 - rname = gst_plugin_feature_get_name (feature);
5.490 -
5.491 - GST_DEBUG ("%s", rname);
5.492 -}
5.493 -
5.494 -static void
5.495 -gst_decode_bin_init (GstDecodeBin * decode_bin)
5.496 -{
5.497 - GList *factories;
5.498 -
5.499 - /* first filter out the interesting element factories */
5.500 - factories = gst_default_registry_feature_filter (
5.501 - (GstPluginFeatureFilter) gst_decode_bin_factory_filter,
5.502 - FALSE, decode_bin);
5.503 -
5.504 - /* sort them according to their ranks */
5.505 - decode_bin->factories = g_list_sort (factories, (GCompareFunc) compare_ranks);
5.506 - /* do some debugging */
5.507 - g_list_foreach (decode_bin->factories, (GFunc) print_feature, NULL);
5.508 -
5.509 -
5.510 - /* we create the typefind element only once */
5.511 - decode_bin->typefind = gst_element_factory_make ("typefind", "typefind");
5.512 - if (!decode_bin->typefind) {
5.513 - g_warning ("can't find typefind element, decodebin will not work");
5.514 - } else {
5.515 - GstPad *pad;
5.516 - GstPad *gpad;
5.517 -
5.518 - /* add the typefind element */
5.519 - if (!gst_bin_add (GST_BIN (decode_bin), decode_bin->typefind)) {
5.520 - g_warning ("Could not add typefind element, decodebin will not work");
5.521 - gst_object_unref (decode_bin->typefind);
5.522 - decode_bin->typefind = NULL;
5.523 - }
5.524 -
5.525 - /* get the sinkpad */
5.526 - pad = gst_element_get_pad (decode_bin->typefind, "sink");
5.527 -
5.528 - /* ghost the sink pad to ourself */
5.529 - gpad = gst_ghost_pad_new ("sink", pad);
5.530 - gst_pad_set_active (gpad, TRUE);
5.531 - gst_element_add_pad (GST_ELEMENT (decode_bin), gpad);
5.532 -
5.533 - gst_object_unref (pad);
5.534 -
5.535 - /* connect a signal to find out when the typefind element found
5.536 - * a type */
5.537 - g_signal_connect (G_OBJECT (decode_bin->typefind), "have_type",
5.538 - G_CALLBACK (type_found), decode_bin);
5.539 - }
5.540 -
5.541 - decode_bin->lock = g_mutex_new ();
5.542 - decode_bin->activegroup = NULL;
5.543 - decode_bin->groups = NULL;
5.544 -
5.545 - decode_bin->caps =
5.546 - gst_caps_from_string ("video/x-raw-yuv;video/x-raw-rgb;video/x-raw-gray;"
5.547 - "audio/x-raw-int;audio/x-raw-float;" "text/plain;text/x-pango-markup");
5.548 -
5.549 - add_fakesink (decode_bin);
5.550 -
5.551 - /* FILLME */
5.552 -}
5.553 -
5.554 -static void
5.555 -gst_decode_bin_dispose (GObject * object)
5.556 -{
5.557 - GstDecodeBin *decode_bin;
5.558 - GList *tmp;
5.559 -
5.560 - decode_bin = GST_DECODE_BIN (object);
5.561 -
5.562 - if (decode_bin->factories)
5.563 - gst_plugin_feature_list_free (decode_bin->factories);
5.564 - decode_bin->factories = NULL;
5.565 -
5.566 - if (decode_bin->activegroup) {
5.567 - gst_decode_group_free (decode_bin->activegroup);
5.568 - decode_bin->activegroup = NULL;
5.569 - }
5.570 -
5.571 - /* remove groups */
5.572 - for (tmp = decode_bin->groups; tmp; tmp = g_list_next (tmp)) {
5.573 - GstDecodeGroup *group = (GstDecodeGroup *) tmp->data;
5.574 -
5.575 - gst_decode_group_free (group);
5.576 - }
5.577 - g_list_free (decode_bin->groups);
5.578 - decode_bin->groups = NULL;
5.579 -
5.580 - for (tmp = decode_bin->oldgroups; tmp; tmp = g_list_next (tmp)) {
5.581 - GstDecodeGroup *group = (GstDecodeGroup *) tmp->data;
5.582 -
5.583 - gst_decode_group_free (group);
5.584 - }
5.585 - g_list_free (decode_bin->oldgroups);
5.586 - decode_bin->oldgroups = NULL;
5.587 -
5.588 - if (decode_bin->caps)
5.589 - gst_caps_unref (decode_bin->caps);
5.590 - decode_bin->caps = NULL;
5.591 - remove_fakesink (decode_bin);
5.592 -
5.593 - G_OBJECT_CLASS (parent_class)->dispose (object);
5.594 -}
5.595 -
5.596 -static void
5.597 -gst_decode_bin_finalize (GObject * object)
5.598 -{
5.599 - GstDecodeBin *decode_bin;
5.600 -
5.601 - decode_bin = GST_DECODE_BIN (object);
5.602 -
5.603 - if (decode_bin->lock) {
5.604 - g_mutex_free (decode_bin->lock);
5.605 - decode_bin->lock = NULL;
5.606 - }
5.607 -
5.608 - G_OBJECT_CLASS (parent_class)->finalize (object);
5.609 -}
5.610 -
5.611 -static void
5.612 -gst_decode_bin_set_property (GObject * object, guint prop_id,
5.613 - const GValue * value, GParamSpec * pspec)
5.614 -{
5.615 - GstDecodeBin *dbin;
5.616 -
5.617 - dbin = GST_DECODE_BIN (object);
5.618 -
5.619 - switch (prop_id) {
5.620 - case PROP_CAPS:
5.621 - gst_decode_bin_set_caps (dbin, (GstCaps *) g_value_dup_boxed (value));
5.622 - break;
5.623 - default:
5.624 - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
5.625 - break;
5.626 - }
5.627 -}
5.628 -
5.629 -static void
5.630 -gst_decode_bin_get_property (GObject * object, guint prop_id,
5.631 - GValue * value, GParamSpec * pspec)
5.632 -{
5.633 - GstDecodeBin *dbin;
5.634 -
5.635 - dbin = GST_DECODE_BIN (object);
5.636 - switch (prop_id) {
5.637 - case PROP_CAPS:{
5.638 - g_value_take_boxed (value, gst_decode_bin_get_caps (dbin));
5.639 - break;
5.640 - }
5.641 - default:
5.642 - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
5.643 - break;
5.644 - }
5.645 -
5.646 -}
5.647 -
5.648 -/* _set_caps
5.649 - * Changes the caps on which decodebin will stop decoding.
5.650 - * Will unref the previously set one. The refcount of the given caps will be
5.651 - * taken.
5.652 - * @caps can be NULL.
5.653 - *
5.654 - * MT-safe
5.655 - */
5.656 -
5.657 -static void
5.658 -gst_decode_bin_set_caps (GstDecodeBin * dbin, GstCaps * caps)
5.659 -{
5.660 - GST_DEBUG_OBJECT (dbin, "Setting new caps: %" GST_PTR_FORMAT, caps);
5.661 -
5.662 - DECODE_BIN_LOCK (dbin);
5.663 - if (dbin->caps)
5.664 - gst_caps_unref (dbin->caps);
5.665 - dbin->caps = caps;
5.666 - DECODE_BIN_UNLOCK (dbin);
5.667 -}
5.668 -
5.669 -/* _get_caps
5.670 - * Returns the currently configured caps on which decodebin will stop decoding.
5.671 - * The returned caps (if not NULL), will have its refcount incremented.
5.672 - *
5.673 - * MT-safe
5.674 - */
5.675 -
5.676 -static GstCaps *
5.677 -gst_decode_bin_get_caps (GstDecodeBin * dbin)
5.678 -{
5.679 - GstCaps *caps;
5.680 -
5.681 - GST_DEBUG_OBJECT (dbin, "Getting currently set caps");
5.682 -
5.683 - DECODE_BIN_LOCK (dbin);
5.684 - caps = dbin->caps;
5.685 - if (caps)
5.686 - gst_caps_ref (caps);
5.687 - DECODE_BIN_UNLOCK (dbin);
5.688 -
5.689 - return caps;
5.690 -}
5.691 -
5.692 -/*****
5.693 - * Default autoplug signal handlers
5.694 - *****/
5.695 -
5.696 -static gboolean
5.697 -gst_decode_bin_autoplug_continue (GstElement * element, GstCaps * caps)
5.698 -{
5.699 - return TRUE;
5.700 -}
5.701 -
5.702 -static gboolean
5.703 -gst_decode_bin_autoplug_sort (GstElement * element, GstCaps * caps,
5.704 - GList ** list)
5.705 -{
5.706 - return TRUE;
5.707 -}
5.708 -
5.709 -
5.710 -
5.711 -/********
5.712 - * Discovery methods
5.713 - *****/
5.714 -
5.715 -static gboolean are_raw_caps (GstDecodeBin * dbin, GstCaps * caps);
5.716 -static gboolean is_demuxer_element (GstElement * srcelement);
5.717 -static GList *find_compatibles (GstDecodeBin * decode_bin,
5.718 - const GstCaps * caps);
5.719 -
5.720 -static gboolean connect_pad (GstDecodeBin * dbin, GstElement * src,
5.721 - GstPad * pad, GList * factories, GstDecodeGroup * group);
5.722 -static gboolean connect_element (GstDecodeBin * dbin, GstElement * element,
5.723 - GstDecodeGroup * group);
5.724 -static void expose_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
5.725 - GstDecodeGroup * group);
5.726 -
5.727 -static void pad_added_group_cb (GstElement * element, GstPad * pad,
5.728 - GstDecodeGroup * group);
5.729 -static void pad_removed_group_cb (GstElement * element, GstPad * pad,
5.730 - GstDecodeGroup * group);
5.731 -static void no_more_pads_group_cb (GstElement * element,
5.732 - GstDecodeGroup * group);
5.733 -static void pad_added_cb (GstElement * element, GstPad * pad,
5.734 - GstDecodeBin * dbin);
5.735 -static void pad_removed_cb (GstElement * element, GstPad * pad,
5.736 - GstDecodeBin * dbin);
5.737 -static void no_more_pads_cb (GstElement * element, GstDecodeBin * dbin);
5.738 -
5.739 -static GstDecodeGroup *get_current_group (GstDecodeBin * dbin);
5.740 -
5.741 -static void
5.742 -analyze_new_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
5.743 - GstCaps * caps, GstDecodeGroup * group)
5.744 -{
5.745 - gboolean apcontinue = TRUE;
5.746 - GList *factories = NULL;
5.747 - gboolean apsort = TRUE;
5.748 -
5.749 - GST_DEBUG_OBJECT (dbin, "Pad %s:%s caps:%" GST_PTR_FORMAT,
5.750 - GST_DEBUG_PAD_NAME (pad), caps);
5.751 -
5.752 - if ((caps == NULL) || gst_caps_is_empty (caps))
5.753 - goto unknown_type;
5.754 -
5.755 - if (gst_caps_is_any (caps))
5.756 - goto any_caps;
5.757 -
5.758 - /* 1. Emit 'autoplug-continue' */
5.759 - g_signal_emit (G_OBJECT (dbin),
5.760 - gst_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE], 0, caps, &apcontinue);
5.761 -
5.762 - /* 1.a if autoplug-continue is FALSE or caps is a raw format, goto pad_is_final */
5.763 - if ((!apcontinue) || are_raw_caps (dbin, caps))
5.764 - goto expose_pad;
5.765 -
5.766 - /* 1.b else if there's no compatible factory or 'autoplug-sort' returned FALSE, goto pad_not_used */
5.767 - if ((factories = find_compatibles (dbin, caps))) {
5.768 - /* emit autoplug-sort */
5.769 - g_signal_emit (G_OBJECT (dbin),
5.770 - gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT],
5.771 - 0, caps, &factories, &apsort);
5.772 - if (!apsort) {
5.773 - g_list_free (factories);
5.774 - /* User doesn't want that pad */
5.775 - goto pad_not_wanted;
5.776 - }
5.777 - } else {
5.778 - /* no compatible factories */
5.779 - goto unknown_type;
5.780 - }
5.781 -
5.782 - /* 1.c else goto pad_is_valid */
5.783 - GST_LOG_OBJECT (pad, "Let's continue discovery on this pad");
5.784 -
5.785 - connect_pad (dbin, src, pad, factories, group);
5.786 - g_list_free (factories);
5.787 -
5.788 - return;
5.789 -
5.790 -expose_pad:
5.791 - {
5.792 - GST_LOG_OBJECT (dbin, "Pad is final. autoplug-continue:%d", apcontinue);
5.793 - expose_pad (dbin, src, pad, group);
5.794 - return;
5.795 - }
5.796 -
5.797 -pad_not_wanted:
5.798 - {
5.799 - GST_LOG_OBJECT (pad, "User doesn't want this pad, stopping discovery");
5.800 - return;
5.801 - }
5.802 -
5.803 -unknown_type:
5.804 - {
5.805 - GST_LOG_OBJECT (pad, "Unknown type, firing signal");
5.806 - g_signal_emit (G_OBJECT (dbin),
5.807 - gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE], 0, pad, caps);
5.808 -
5.809 - /* Check if there are no pending groups, if so, remove fakesink */
5.810 - if (dbin->groups == NULL)
5.811 - remove_fakesink (dbin);
5.812 -
5.813 - return;
5.814 - }
5.815 -
5.816 -any_caps:
5.817 - {
5.818 - GST_WARNING_OBJECT (pad,
5.819 - "pad has ANY caps, not able to autoplug to anything");
5.820 - /* FIXME : connect to caps notification */
5.821 - return;
5.822 - }
5.823 -}
5.824 -
5.825 -
5.826 -/* connect_pad:
5.827 - *
5.828 - * Try to connect the given pad to an element created from one of the factories,
5.829 - * and recursively.
5.830 - *
5.831 - * Returns TRUE if an element was properly created and linked
5.832 - */
5.833 -
5.834 -static gboolean
5.835 -connect_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
5.836 - GList * factories, GstDecodeGroup * group)
5.837 -{
5.838 - gboolean res = FALSE;
5.839 - GList *tmp;
5.840 -
5.841 - g_return_val_if_fail (factories != NULL, FALSE);
5.842 - GST_DEBUG_OBJECT (dbin, "pad %s:%s , group:%p",
5.843 - GST_DEBUG_PAD_NAME (pad), group);
5.844 -
5.845 - /* 1. is element demuxer or parser */
5.846 - if (is_demuxer_element (src)) {
5.847 - GstPad *mqpad;
5.848 -
5.849 - GST_LOG_OBJECT (src, "is a demuxer, connecting the pad through multiqueue");
5.850 -
5.851 - if (!group)
5.852 - if (!(group = get_current_group (dbin))) {
5.853 - group = gst_decode_group_new (dbin);
5.854 - DECODE_BIN_LOCK (dbin);
5.855 - dbin->groups = g_list_append (dbin->groups, group);
5.856 - DECODE_BIN_UNLOCK (dbin);
5.857 - }
5.858 -
5.859 - if (!(mqpad = gst_decode_group_control_demuxer_pad (group, pad)))
5.860 - goto beach;
5.861 - pad = mqpad;
5.862 - }
5.863 -
5.864 - /* 2. Try to create an element and link to it */
5.865 - for (tmp = factories; tmp; tmp = g_list_next (tmp)) {
5.866 - GstElementFactory *factory = (GstElementFactory *) tmp->data;
5.867 - GstElement *element;
5.868 - GstPad *sinkpad;
5.869 -
5.870 - /* 2.1. Try to create an element */
5.871 - if ((element = gst_element_factory_create (factory, NULL)) == NULL) {
5.872 - GST_WARNING_OBJECT (dbin, "Could not create an element from %s",
5.873 - gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
5.874 - continue;
5.875 - }
5.876 -
5.877 - /* 2.3. Find its sink pad */
5.878 - if (!(sinkpad = find_sink_pad (element))) {
5.879 - GST_WARNING_OBJECT (dbin, "Element %s doesn't have a sink pad",
5.880 - GST_ELEMENT_NAME (element));
5.881 - gst_object_unref (element);
5.882 - continue;
5.883 - }
5.884 -
5.885 - /* 2.4 add it ... */
5.886 - if (!(gst_bin_add (GST_BIN (dbin), element))) {
5.887 - GST_WARNING_OBJECT (dbin, "Couldn't add %s to the bin",
5.888 - GST_ELEMENT_NAME (element));
5.889 - gst_object_unref (sinkpad);
5.890 - gst_object_unref (element);
5.891 - continue;
5.892 - }
5.893 -
5.894 - /* ... activate it ... */
5.895 - if ((gst_element_set_state (element,
5.896 - GST_STATE_READY)) == GST_STATE_CHANGE_FAILURE) {
5.897 - GST_WARNING_OBJECT (dbin, "Couldn't set %s to READY",
5.898 - GST_ELEMENT_NAME (element));
5.899 - gst_object_unref (sinkpad);
5.900 - gst_bin_remove (GST_BIN (dbin), element);
5.901 - continue;
5.902 - }
5.903 -
5.904 - /* 2.5 ...and try to link */
5.905 - if ((gst_pad_link (pad, sinkpad)) != GST_PAD_LINK_OK) {
5.906 - GST_WARNING_OBJECT (dbin, "Link failed on pad %s:%s",
5.907 - GST_DEBUG_PAD_NAME (sinkpad));
5.908 - gst_element_set_state (element, GST_STATE_NULL);
5.909 - gst_object_unref (sinkpad);
5.910 - gst_bin_remove (GST_BIN (dbin), element);
5.911 - continue;
5.912 - }
5.913 -
5.914 - GST_LOG_OBJECT (dbin, "linked on pad %s:%s", GST_DEBUG_PAD_NAME (pad));
5.915 -
5.916 - /* link this element further */
5.917 - connect_element (dbin, element, group);
5.918 -
5.919 - /* Bring the element to the state of the parent */
5.920 - if ((gst_element_set_state (element,
5.921 - GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) {
5.922 - GST_WARNING_OBJECT (dbin, "Couldn't set %s to PAUSED",
5.923 - GST_ELEMENT_NAME (element));
5.924 - gst_element_set_state (element, GST_STATE_NULL);
5.925 - gst_object_unref (sinkpad);
5.926 - gst_bin_remove (GST_BIN (dbin), element);
5.927 - continue;
5.928 - }
5.929 -
5.930 - res = TRUE;
5.931 - break;
5.932 - }
5.933 -
5.934 -beach:
5.935 - return res;
5.936 -}
5.937 -
5.938 -static gboolean
5.939 -connect_element (GstDecodeBin * dbin, GstElement * element,
5.940 - GstDecodeGroup * group)
5.941 -{
5.942 - GList *pads;
5.943 - gboolean res = TRUE;
5.944 - gboolean dynamic = FALSE;
5.945 - GList *to_connect = NULL;
5.946 -
5.947 - GST_DEBUG_OBJECT (dbin, "Attempting to connect element %s [group:%p] further",
5.948 - GST_ELEMENT_NAME (element), group);
5.949 -
5.950 - /* 1. Loop over pad templates, grabbing existing pads along the way */
5.951 - for (pads = GST_ELEMENT_GET_CLASS (element)->padtemplates; pads;
5.952 - pads = g_list_next (pads)) {
5.953 - GstPadTemplate *templ = GST_PAD_TEMPLATE (pads->data);
5.954 - const gchar *templ_name;
5.955 -
5.956 - /* we are only interested in source pads */
5.957 - if (GST_PAD_TEMPLATE_DIRECTION (templ) != GST_PAD_SRC)
5.958 - continue;
5.959 -
5.960 - templ_name = GST_PAD_TEMPLATE_NAME_TEMPLATE (templ);
5.961 - GST_DEBUG_OBJECT (dbin, "got a source pad template %s", templ_name);
5.962 -
5.963 - /* figure out what kind of pad this is */
5.964 - switch (GST_PAD_TEMPLATE_PRESENCE (templ)) {
5.965 - case GST_PAD_ALWAYS:
5.966 - {
5.967 - /* get the pad that we need to autoplug */
5.968 - GstPad *pad = gst_element_get_pad (element, templ_name);
5.969 -
5.970 - if (pad) {
5.971 - GST_DEBUG_OBJECT (dbin, "got the pad for always template %s",
5.972 - templ_name);
5.973 - /* here is the pad, we need to autoplug it */
5.974 - to_connect = g_list_prepend (to_connect, pad);
5.975 - } else {
5.976 - /* strange, pad is marked as always but it's not
5.977 - * there. Fix the element */
5.978 - GST_WARNING_OBJECT (dbin,
5.979 - "could not get the pad for always template %s", templ_name);
5.980 - }
5.981 - break;
5.982 - }
5.983 - case GST_PAD_SOMETIMES:
5.984 - {
5.985 - /* try to get the pad to see if it is already created or
5.986 - * not */
5.987 - GstPad *pad = gst_element_get_pad (element, templ_name);
5.988 -
5.989 - if (pad) {
5.990 - GST_DEBUG_OBJECT (dbin, "got the pad for sometimes template %s",
5.991 - templ_name);
5.992 - /* the pad is created, we need to autoplug it */
5.993 - to_connect = g_list_prepend (to_connect, pad);
5.994 - } else {
5.995 - GST_DEBUG_OBJECT (dbin,
5.996 - "did not get the sometimes pad of template %s", templ_name);
5.997 - /* we have an element that will create dynamic pads */
5.998 - dynamic = TRUE;
5.999 - }
5.1000 - break;
5.1001 - }
5.1002 - case GST_PAD_REQUEST:
5.1003 - /* ignore request pads */
5.1004 - GST_DEBUG_OBJECT (dbin, "ignoring request padtemplate %s", templ_name);
5.1005 - break;
5.1006 - }
5.1007 - }
5.1008 -
5.1009 - /* 2. if there are more potential pads, connect to relevent signals */
5.1010 - if (dynamic) {
5.1011 - if (group) {
5.1012 - GST_LOG ("Adding signals to element %s in group %p",
5.1013 - GST_ELEMENT_NAME (element), group);
5.1014 - GROUP_MUTEX_LOCK (group);
5.1015 - group->nbdynamic++;
5.1016 - GST_LOG ("Group %p has now %d dynamic elements", group, group->nbdynamic);
5.1017 - GROUP_MUTEX_UNLOCK (group);
5.1018 - g_signal_connect (G_OBJECT (element), "pad-added",
5.1019 - G_CALLBACK (pad_added_group_cb), group);
5.1020 - g_signal_connect (G_OBJECT (element), "pad-removed",
5.1021 - G_CALLBACK (pad_removed_group_cb), group);
5.1022 - g_signal_connect (G_OBJECT (element), "no-more-pads",
5.1023 - G_CALLBACK (no_more_pads_group_cb), group);
5.1024 - } else {
5.1025 - /* This is a non-grouped element, the handlers are different */
5.1026 - g_signal_connect (G_OBJECT (element), "pad-added",
5.1027 - G_CALLBACK (pad_added_cb), dbin);
5.1028 - g_signal_connect (G_OBJECT (element), "pad-removed",
5.1029 - G_CALLBACK (pad_removed_cb), dbin);
5.1030 - g_signal_connect (G_OBJECT (element), "no-more-pads",
5.1031 - G_CALLBACK (no_more_pads_cb), dbin);
5.1032 - }
5.1033 - }
5.1034 -
5.1035 - /* 3. for every available pad, connect it */
5.1036 - for (pads = to_connect; pads; pads = g_list_next (pads)) {
5.1037 - GstPad *pad = GST_PAD_CAST (pads->data);
5.1038 - GstCaps *caps;
5.1039 -
5.1040 - caps = gst_pad_get_caps (pad);
5.1041 - analyze_new_pad (dbin, element, pad, caps, group);
5.1042 - if (caps)
5.1043 - gst_caps_unref (caps);
5.1044 -
5.1045 - gst_object_unref (pad);
5.1046 - }
5.1047 - g_list_free (to_connect);
5.1048 -
5.1049 - return res;
5.1050 -}
5.1051 -
5.1052 -/* expose_pad:
5.1053 - *
5.1054 - * Expose the given pad on the group as a decoded pad.
5.1055 - * If group is NULL, a GstDecodeGroup will be created and setup properly.
5.1056 - */
5.1057 -static void
5.1058 -expose_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad,
5.1059 - GstDecodeGroup * group)
5.1060 -{
5.1061 - gboolean newgroup = FALSE;
5.1062 - gboolean isdemux;
5.1063 -
5.1064 - GST_DEBUG_OBJECT (dbin, "pad %s:%s, group:%p",
5.1065 - GST_DEBUG_PAD_NAME (pad), group);
5.1066 -
5.1067 - if (!group)
5.1068 - if (!(group = get_current_group (dbin))) {
5.1069 - group = gst_decode_group_new (dbin);
5.1070 - DECODE_BIN_LOCK (dbin);
5.1071 - dbin->groups = g_list_append (dbin->groups, group);
5.1072 - DECODE_BIN_UNLOCK (dbin);
5.1073 - newgroup = TRUE;
5.1074 - }
5.1075 -
5.1076 - isdemux = is_demuxer_element (src);
5.1077 -
5.1078 - if (isdemux || newgroup) {
5.1079 - GstPad *mqpad;
5.1080 -
5.1081 - GST_LOG_OBJECT (src, "is a demuxer, connecting the pad through multiqueue");
5.1082 -
5.1083 - if (!(mqpad = gst_decode_group_control_demuxer_pad (group, pad)))
5.1084 - goto beach;
5.1085 - pad = mqpad;
5.1086 - }
5.1087 -
5.1088 - gst_decode_group_control_source_pad (group, pad);
5.1089 -
5.1090 - if (newgroup && !isdemux) {
5.1091 - /* If we have discovered a raw pad and it doesn't belong to any group,
5.1092 - * that means there wasn't any demuxer. In that case, we consider the
5.1093 - * group as being complete. */
5.1094 - gst_decode_group_set_complete (group);
5.1095 - }
5.1096 -beach:
5.1097 - return;
5.1098 -}
5.1099 -
5.1100 -static void
5.1101 -type_found (GstElement * typefind, guint probability,
5.1102 - GstCaps * caps, GstDecodeBin * decode_bin)
5.1103 -{
5.1104 - GstPad *pad;
5.1105 -
5.1106 - GST_STATE_LOCK (decode_bin);
5.1107 -
5.1108 - GST_DEBUG_OBJECT (decode_bin, "typefind found caps %" GST_PTR_FORMAT, caps);
5.1109 -
5.1110 - pad = gst_element_get_pad (typefind, "src");
5.1111 -
5.1112 - analyze_new_pad (decode_bin, typefind, pad, caps, NULL);
5.1113 -
5.1114 - gst_object_unref (pad);
5.1115 -
5.1116 - GST_STATE_UNLOCK (decode_bin);
5.1117 - return;
5.1118 -}
5.1119 -
5.1120 -static void
5.1121 -pad_added_group_cb (GstElement * element, GstPad * pad, GstDecodeGroup * group)
5.1122 -{
5.1123 - GstCaps *caps;
5.1124 - gboolean expose = FALSE;
5.1125 -
5.1126 - GST_LOG_OBJECT (pad, "pad added, group:%p", group);
5.1127 -
5.1128 - caps = gst_pad_get_caps (pad);
5.1129 - analyze_new_pad (group->dbin, element, pad, caps, group);
5.1130 - if (caps)
5.1131 - gst_caps_unref (caps);
5.1132 -
5.1133 - GROUP_MUTEX_LOCK (group);
5.1134 - group->nbdynamic--;
5.1135 - GST_LOG ("Group %p has now %d dynamic objects", group, group->nbdynamic);
5.1136 - if (group->nbdynamic == 0)
5.1137 - expose = TRUE;
5.1138 - GROUP_MUTEX_UNLOCK (group);
5.1139 - if (expose) {
5.1140 - GST_LOG
5.1141 - ("That was the last dynamic object, now attempting to expose the group");
5.1142 - DECODE_BIN_LOCK (group->dbin);
5.1143 - gst_decode_group_expose (group);
5.1144 - DECODE_BIN_UNLOCK (group->dbin);
5.1145 - }
5.1146 -}
5.1147 -
5.1148 -static void
5.1149 -pad_removed_group_cb (GstElement * element, GstPad * pad,
5.1150 - GstDecodeGroup * group)
5.1151 -{
5.1152 - GST_LOG_OBJECT (pad, "pad removed, group:%p", group);
5.1153 -
5.1154 - /* In fact, we don't have to do anything here, the active group will be
5.1155 - * removed when the group's multiqueue is drained */
5.1156 -}
5.1157 -
5.1158 -static void
5.1159 -no_more_pads_group_cb (GstElement * element, GstDecodeGroup * group)
5.1160 -{
5.1161 - GST_LOG_OBJECT (element, "no more pads, setting group %p to complete", group);
5.1162 -
5.1163 - /* FIXME : FILLME */
5.1164 - gst_decode_group_set_complete (group);
5.1165 -}
5.1166 -
5.1167 -static void
5.1168 -pad_added_cb (GstElement * element, GstPad * pad, GstDecodeBin * dbin)
5.1169 -{
5.1170 - GstCaps *caps;
5.1171 -
5.1172 - GST_LOG_OBJECT (pad, "Pad added to non-grouped element");
5.1173 -
5.1174 - caps = gst_pad_get_caps (pad);
5.1175 - analyze_new_pad (dbin, element, pad, caps, NULL);
5.1176 - if (caps)
5.1177 - gst_caps_unref (caps);
5.1178 -}
5.1179 -
5.1180 -static void
5.1181 -pad_removed_cb (GstElement * element, GstPad * pad, GstDecodeBin * dbin)
5.1182 -{
5.1183 - GST_LOG_OBJECT (pad, "Pad removed from non-grouped element");
5.1184 -}
5.1185 -
5.1186 -static void
5.1187 -no_more_pads_cb (GstElement * element, GstDecodeBin * dbin)
5.1188 -{
5.1189 - GstDecodeGroup *group;
5.1190 -
5.1191 - GST_LOG_OBJECT (element, "No more pads, setting current group to complete");
5.1192 -
5.1193 - /* Find the non-complete group, there should only be one */
5.1194 - if (!(group = get_current_group (dbin)))
5.1195 - goto no_group;
5.1196 -
5.1197 - gst_decode_group_set_complete (group);
5.1198 - return;
5.1199 -
5.1200 -no_group:
5.1201 - {
5.1202 - GST_WARNING_OBJECT (dbin, "We couldn't find a non-completed group !!");
5.1203 - return;
5.1204 - }
5.1205 -}
5.1206 -
5.1207 -/* this function runs through the element factories and returns a list
5.1208 - * of all elements that are able to sink the given caps
5.1209 - */
5.1210 -static GList *
5.1211 -find_compatibles (GstDecodeBin * decode_bin, const GstCaps * caps)
5.1212 -{
5.1213 - GList *factories;
5.1214 - GList *to_try = NULL;
5.1215 -
5.1216 - /* loop over all the factories */
5.1217 - for (factories = decode_bin->factories; factories;
5.1218 - factories = g_list_next (factories)) {
5.1219 - GstElementFactory *factory = GST_ELEMENT_FACTORY (factories->data);
5.1220 - const GList *templates;
5.1221 - GList *walk;
5.1222 -
5.1223 - /* get the templates from the element factory */
5.1224 - templates = gst_element_factory_get_static_pad_templates (factory);
5.1225 - for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
5.1226 - GstStaticPadTemplate *templ = walk->data;
5.1227 -
5.1228 - /* we only care about the sink templates */
5.1229 - if (templ->direction == GST_PAD_SINK) {
5.1230 - GstCaps *intersect;
5.1231 - GstCaps *tmpl_caps;
5.1232 -
5.1233 - /* try to intersect the caps with the caps of the template */
5.1234 - tmpl_caps = gst_static_caps_get (&templ->static_caps);
5.1235 -
5.1236 - intersect = gst_caps_intersect (caps, tmpl_caps);
5.1237 - gst_caps_unref (tmpl_caps);
5.1238 -
5.1239 - /* check if the intersection is empty */
5.1240 - if (!gst_caps_is_empty (intersect)) {
5.1241 - /* non empty intersection, we can use this element */
5.1242 - to_try = g_list_prepend (to_try, factory);
5.1243 - gst_caps_unref (intersect);
5.1244 - break;
5.1245 - }
5.1246 - gst_caps_unref (intersect);
5.1247 - }
5.1248 - }
5.1249 - }
5.1250 - to_try = g_list_reverse (to_try);
5.1251 -
5.1252 - return to_try;
5.1253 -}
5.1254 -
5.1255 -/* Decide whether an element is a demuxer based on the
5.1256 - * klass and number/type of src pad templates it has */
5.1257 -static gboolean
5.1258 -is_demuxer_element (GstElement * srcelement)
5.1259 -{
5.1260 - GstElementFactory *srcfactory;
5.1261 - GstElementClass *elemclass;
5.1262 - GList *templates, *walk;
5.1263 - const gchar *klass;
5.1264 - gint potential_src_pads = 0;
5.1265 -
5.1266 - srcfactory = gst_element_get_factory (srcelement);
5.1267 - klass = gst_element_factory_get_klass (srcfactory);
5.1268 -
5.1269 - /* Can't be a demuxer unless it has Demux in the klass name */
5.1270 - if (!strstr (klass, "Demux"))
5.1271 - return FALSE;
5.1272 -
5.1273 - /* Walk the src pad templates and count how many the element
5.1274 - * might produce */
5.1275 - elemclass = GST_ELEMENT_GET_CLASS (srcelement);
5.1276 -
5.1277 - walk = templates = gst_element_class_get_pad_template_list (elemclass);
5.1278 - while (walk != NULL) {
5.1279 - GstPadTemplate *templ;
5.1280 -
5.1281 - templ = (GstPadTemplate *) walk->data;
5.1282 - if (GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC) {
5.1283 - switch (GST_PAD_TEMPLATE_PRESENCE (templ)) {
5.1284 - case GST_PAD_ALWAYS:
5.1285 - case GST_PAD_SOMETIMES:
5.1286 - if (strstr (GST_PAD_TEMPLATE_NAME_TEMPLATE (templ), "%"))
5.1287 - potential_src_pads += 2; /* Might make multiple pads */
5.1288 - else
5.1289 - potential_src_pads += 1;
5.1290 - break;
5.1291 - case GST_PAD_REQUEST:
5.1292 - potential_src_pads += 2;
5.1293 - break;
5.1294 - }
5.1295 - }
5.1296 - walk = g_list_next (walk);
5.1297 - }
5.1298 -
5.1299 - if (potential_src_pads < 2)
5.1300 - return FALSE;
5.1301 -
5.1302 - return TRUE;
5.1303 -}
5.1304 -
5.1305 -/* Returns TRUE if the caps are raw, or if they are compatible with the caps
5.1306 - * specified in the 'caps' property
5.1307 - *
5.1308 - * The decodebin_lock should be taken !
5.1309 - */
5.1310 -static gboolean
5.1311 -are_raw_caps (GstDecodeBin * dbin, GstCaps * caps)
5.1312 -{
5.1313 - GstCaps *intersection;
5.1314 - gboolean res;
5.1315 -
5.1316 - GST_LOG_OBJECT (dbin, "Checking with caps %" GST_PTR_FORMAT, caps);
5.1317 -
5.1318 - intersection = gst_caps_intersect (dbin->caps, caps);
5.1319 -
5.1320 - res = (!(gst_caps_is_empty (intersection)));
5.1321 -
5.1322 - gst_caps_unref (intersection);
5.1323 -
5.1324 - GST_LOG_OBJECT (dbin, "Caps are %sfinal caps", res ? "" : "not ");
5.1325 -
5.1326 - return res;
5.1327 -}
5.1328 -
5.1329 -
5.1330 -/****
5.1331 - * GstDecodeGroup functions
5.1332 - ****/
5.1333 -
5.1334 -static void
5.1335 -multi_queue_overrun_cb (GstElement * queue, GstDecodeGroup * group)
5.1336 -{
5.1337 - GST_LOG_OBJECT (group->dbin, "multiqueue is full");
5.1338 -
5.1339 - /* if we haven't exposed the group, do it */
5.1340 - DECODE_BIN_LOCK (group->dbin);
5.1341 - gst_decode_group_expose (group);
5.1342 - DECODE_BIN_UNLOCK (group->dbin);
5.1343 -}
5.1344 -
5.1345 -static void
5.1346 -multi_queue_underrun_cb (GstElement * queue, GstDecodeGroup * group)
5.1347 -{
5.1348 - GstDecodeBin *dbin = group->dbin;
5.1349 -
5.1350 - GST_LOG_OBJECT (dbin, "multiqueue is empty for group %p", group);
5.1351 -
5.1352 - /* Check if we need to activate another group */
5.1353 - DECODE_BIN_LOCK (dbin);
5.1354 - if ((group == dbin->activegroup) && dbin->groups) {
5.1355 - GST_DEBUG_OBJECT (dbin, "Switching to new group");
5.1356 - /* unexpose current active */
5.1357 - gst_decode_group_hide (group);
5.1358 -
5.1359 - /* expose first group of groups */
5.1360 - gst_decode_group_expose ((GstDecodeGroup *) dbin->groups->data);
5.1361 - }
5.1362 - DECODE_BIN_UNLOCK (dbin);
5.1363 -}
5.1364 -
5.1365 -/* gst_decode_group_new
5.1366 - *
5.1367 - * Creates a new GstDecodeGroup. It is up to the caller to add it to the list
5.1368 - * of groups.
5.1369 - */
5.1370 -static GstDecodeGroup *
5.1371 -gst_decode_group_new (GstDecodeBin * dbin)
5.1372 -{
5.1373 - GstDecodeGroup *group;
5.1374 - GstElement *mq;
5.1375 -
5.1376 - GST_LOG_OBJECT (dbin, "Creating new group");
5.1377 -
5.1378 - if (!(mq = gst_element_factory_make ("multiqueue", NULL))) {
5.1379 - GST_WARNING ("Couldn't create multiqueue element");
5.1380 - return NULL;
5.1381 - }
5.1382 -
5.1383 - g_object_set (G_OBJECT (mq),
5.1384 - "max-size-bytes", 2 * 1024 * 1024,
5.1385 - "max-size-time", 5 * GST_SECOND, "max-size-buffers", 0, NULL);
5.1386 -
5.1387 - group = g_new0 (GstDecodeGroup, 1);
5.1388 - group->lock = g_mutex_new ();
5.1389 - group->dbin = dbin;
5.1390 - group->multiqueue = mq;
5.1391 - group->exposed = FALSE;
5.1392 - group->drained = FALSE;
5.1393 - group->blocked = FALSE;
5.1394 - group->complete = FALSE;
5.1395 - group->endpads = NULL;
5.1396 -
5.1397 - group->overrunsig = g_signal_connect (G_OBJECT (mq), "overrun",
5.1398 - G_CALLBACK (multi_queue_overrun_cb), group);
5.1399 - group->underrunsig = g_signal_connect (G_OBJECT (mq), "underrun",
5.1400 - G_CALLBACK (multi_queue_underrun_cb), group);
5.1401 -
5.1402 - gst_bin_add (GST_BIN (dbin), group->multiqueue);
5.1403 - gst_element_set_state (group->multiqueue, GST_STATE_PAUSED);
5.1404 -
5.1405 - GST_LOG_OBJECT (dbin, "Returning new group %p", group);
5.1406 -
5.1407 - return group;
5.1408 -}
5.1409 -
5.1410 -/** get_current_group:
5.1411 - *
5.1412 - * Returns the current non-completed group.
5.1413 - *
5.1414 - * Returns NULL if no groups are available, or all groups are completed.
5.1415 - */
5.1416 -static GstDecodeGroup *
5.1417 -get_current_group (GstDecodeBin * dbin)
5.1418 -{
5.1419 - GList *tmp;
5.1420 - GstDecodeGroup *group = NULL;
5.1421 -
5.1422 - DECODE_BIN_LOCK (dbin);
5.1423 - for (tmp = dbin->groups; tmp; tmp = g_list_next (tmp)) {
5.1424 - GstDecodeGroup *this = (GstDecodeGroup *) tmp->data;
5.1425 -
5.1426 - GST_LOG_OBJECT (dbin, "group %p, complete:%d", this, this->complete);
5.1427 -
5.1428 - if (!this->complete) {
5.1429 - group = this;
5.1430 - break;
5.1431 - }
5.1432 - }
5.1433 - DECODE_BIN_UNLOCK (dbin);
5.1434 -
5.1435 - GST_LOG_OBJECT (dbin, "Returning group %p", group);
5.1436 -
5.1437 - return group;
5.1438 -}
5.1439 -
5.1440 -static gboolean
5.1441 -group_demuxer_event_probe (GstPad * pad, GstEvent * event,
5.1442 - GstDecodeGroup * group)
5.1443 -{
5.1444 - if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
5.1445 - GST_DEBUG_OBJECT (group->dbin,
5.1446 - "Got EOS on group input pads, exposing group if it wasn't before");
5.1447 - DECODE_BIN_LOCK (group->dbin);
5.1448 - gst_decode_group_expose (group);
5.1449 - DECODE_BIN_UNLOCK (group->dbin);
5.1450 - }
5.1451 - return TRUE;
5.1452 -}
5.1453 -
5.1454 -/* gst_decode_group_control_demuxer_pad
5.1455 - *
5.1456 - * Adds a new demuxer srcpad to the given group.
5.1457 - *
5.1458 - * Returns the srcpad of the multiqueue corresponding the given pad.
5.1459 - * Returns NULL if there was an error.
5.1460 - */
5.1461 -static GstPad *
5.1462 -gst_decode_group_control_demuxer_pad (GstDecodeGroup * group, GstPad * pad)
5.1463 -{
5.1464 - GstPad *srcpad, *sinkpad;
5.1465 - gchar *nb, *sinkname, *srcname;
5.1466 -
5.1467 - GST_LOG ("group:%p pad %s:%s", group, GST_DEBUG_PAD_NAME (pad));
5.1468 -
5.1469 - srcpad = NULL;
5.1470 -
5.1471 - if (!(sinkpad = gst_element_get_pad (group->multiqueue, "sink%d"))) {
5.1472 - GST_ERROR ("Couldn't get sinkpad from multiqueue");
5.1473 - return NULL;
5.1474 - }
5.1475 -
5.1476 - if ((gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK)) {
5.1477 - GST_ERROR ("Couldn't link demuxer and multiqueue");
5.1478 - goto beach;
5.1479 - }
5.1480 -
5.1481 - sinkname = gst_pad_get_name (sinkpad);
5.1482 - nb = sinkname + 4;
5.1483 - srcname = g_strdup_printf ("src%s", nb);
5.1484 - g_free (sinkname);
5.1485 -
5.1486 - GROUP_MUTEX_LOCK (group);
5.1487 -
5.1488 - if (!(srcpad = gst_element_get_pad (group->multiqueue, srcname))) {
5.1489 - GST_ERROR ("Couldn't get srcpad %s from multiqueue", srcname);
5.1490 - goto chiringuito;
5.1491 - }
5.1492 -
5.1493 - /* connect event handler on pad to intercept EOS events */
5.1494 - gst_pad_add_event_probe (pad, G_CALLBACK (group_demuxer_event_probe), group);
5.1495 -
5.1496 -chiringuito:
5.1497 - g_free (srcname);
5.1498 - GROUP_MUTEX_UNLOCK (group);
5.1499 -
5.1500 -beach:
5.1501 - gst_object_unref (sinkpad);
5.1502 - return srcpad;
5.1503 -}
5.1504 -
5.1505 -static gboolean
5.1506 -gst_decode_group_control_source_pad (GstDecodeGroup * group, GstPad * pad)
5.1507 -{
5.1508 - GstDecodePad *dpad;
5.1509 -
5.1510 - g_return_val_if_fail (group != NULL, FALSE);
5.1511 -
5.1512 - GST_LOG ("group:%p , pad %s:%s", group, GST_DEBUG_PAD_NAME (pad));
5.1513 -
5.1514 - /* FIXME : check if pad is already controlled */
5.1515 -
5.1516 - GROUP_MUTEX_LOCK (group);
5.1517 -
5.1518 - /* Create GstDecodePad for the pad */
5.1519 - dpad = gst_decode_pad_new (group, pad, TRUE);
5.1520 -
5.1521 - group->endpads = g_list_append (group->endpads, dpad);
5.1522 -
5.1523 - GROUP_MUTEX_UNLOCK (group);
5.1524 -
5.1525 - return TRUE;
5.1526 -}
5.1527 -
5.1528 -/* gst_decode_group_check_if_blocked:
5.1529 - *
5.1530 - * Call this when one of the pads blocked status has changed.
5.1531 - * If the group is complete and blocked, the group will be marked as blocked
5.1532 - * and will ghost/expose all pads on decodebin if the group is the current one.
5.1533 - *
5.1534 - * Call with the group lock taken ! MT safe
5.1535 - */
5.1536 -static void
5.1537 -gst_decode_group_check_if_blocked (GstDecodeGroup * group)
5.1538 -{
5.1539 - GList *tmp;
5.1540 - gboolean blocked = TRUE;
5.1541 -
5.1542 - GST_LOG ("group : %p , ->complete:%d , ->nbdynamic:%d",
5.1543 - group, group->complete, group->nbdynamic);
5.1544 -
5.1545 - /* 1. don't do anything if group is not complete */
5.1546 - if (!group->complete || group->nbdynamic) {
5.1547 - GST_DEBUG_OBJECT (group->dbin, "Group isn't complete yet");
5.1548 - return;
5.1549 - }
5.1550 -
5.1551 - for (tmp = group->endpads; tmp; tmp = g_list_next (tmp)) {
5.1552 - GstDecodePad *dpad = (GstDecodePad *) tmp->data;
5.1553 -
5.1554 - if (!dpad->blocked) {
5.1555 - blocked = FALSE;
5.1556 - break;
5.1557 - }
5.1558 - }
5.1559 -
5.1560 - /* 2. Update status of group */
5.1561 - group->blocked = blocked;
5.1562 - GST_LOG ("group is blocked:%d", blocked);
5.1563 -
5.1564 - /* 3. don't do anything if not blocked completely */
5.1565 - if (!blocked)
5.1566 - return;
5.1567 -
5.1568 - /* 4. if we're the current group, expose pads */
5.1569 - DECODE_BIN_LOCK (group->dbin);
5.1570 - if (!gst_decode_group_expose (group))
5.1571 - GST_WARNING_OBJECT (group->dbin, "Couldn't expose group");
5.1572 - DECODE_BIN_UNLOCK (group->dbin);
5.1573 -}
5.1574 -
5.1575 -static void
5.1576 -gst_decode_group_check_if_drained (GstDecodeGroup * group)
5.1577 -{
5.1578 - GList *tmp;
5.1579 - GstDecodeBin *dbin = group->dbin;
5.1580 - gboolean drained = TRUE;
5.1581 -
5.1582 - GST_LOG ("group : %p", group);
5.1583 -
5.1584 - for (tmp = group->endpads; tmp; tmp = g_list_next (tmp)) {
5.1585 - GstDecodePad *dpad = (GstDecodePad *) tmp->data;
5.1586 -
5.1587 - GST_LOG ("testing dpad %p", dpad);
5.1588 -
5.1589 - if (!dpad->drained) {
5.1590 - drained = FALSE;
5.1591 - break;
5.1592 - }
5.1593 - }
5.1594 -
5.1595 - group->drained = drained;
5.1596 - GST_LOG ("group is drained");
5.1597 -
5.1598 - if (!drained)
5.1599 - return;
5.1600 -
5.1601 - DECODE_BIN_LOCK (dbin);
5.1602 - if ((group == dbin->activegroup) && dbin->groups) {
5.1603 - GST_DEBUG_OBJECT (dbin, "Switching to new group");
5.1604 -
5.1605 - gst_decode_group_hide (group);
5.1606 -
5.1607 - gst_decode_group_expose ((GstDecodeGroup *) dbin->groups->data);
5.1608 - }
5.1609 - DECODE_BIN_UNLOCK (dbin);
5.1610 -}
5.1611 -
5.1612 -/* sort_end_pads:
5.1613 - * GCompareFunc to use with lists of GstPad.
5.1614 - * Sorts pads by mime type.
5.1615 - * First video (raw, then non-raw), then audio (raw, then non-raw),
5.1616 - * then others.
5.1617 - *
5.1618 - * Return: negative if a<b, 0 if a==b, positive if a>b
5.1619 - */
5.1620 -
5.1621 -static gint
5.1622 -sort_end_pads (GstDecodePad * da, GstDecodePad * db)
5.1623 -{
5.1624 - GstPad *a, *b;
5.1625 - gint va, vb;
5.1626 - GstCaps *capsa, *capsb;
5.1627 - GstStructure *sa, *sb;
5.1628 - const gchar *namea, *nameb;
5.1629 -
5.1630 - a = da->pad;
5.1631 - b = db->pad;
5.1632 -
5.1633 - capsa = gst_pad_get_caps (a);
5.1634 - capsb = gst_pad_get_caps (b);
5.1635 -
5.1636 - sa = gst_caps_get_structure ((const GstCaps *) capsa, 0);
5.1637 - sb = gst_caps_get_structure ((const GstCaps *) capsb, 0);
5.1638 -
5.1639 - namea = gst_structure_get_name (sa);
5.1640 - nameb = gst_structure_get_name (sb);
5.1641 -
5.1642 - if (g_strrstr (namea, "video/x-raw-"))
5.1643 - va = 0;
5.1644 - else if (g_strrstr (namea, "video/"))
5.1645 - va = 1;
5.1646 - else if (g_strrstr (namea, "audio/x-raw"))
5.1647 - va = 2;
5.1648 - else if (g_strrstr (namea, "audio/"))
5.1649 - va = 3;
5.1650 - else
5.1651 - va = 4;
5.1652 -
5.1653 - if (g_strrstr (nameb, "video/x-raw-"))
5.1654 - vb = 0;
5.1655 - else if (g_strrstr (nameb, "video/"))
5.1656 - vb = 1;
5.1657 - else if (g_strrstr (nameb, "audio/x-raw"))
5.1658 - vb = 2;
5.1659 - else if (g_strrstr (nameb, "audio/"))
5.1660 - vb = 3;
5.1661 - else
5.1662 - vb = 4;
5.1663 -
5.1664 - gst_caps_unref (capsa);
5.1665 - gst_caps_unref (capsb);
5.1666 -
5.1667 - return va - vb;
5.1668 -}
5.1669 -
5.1670 -/* gst_decode_group_expose:
5.1671 - *
5.1672 - * Expose this group's pads.
5.1673 - *
5.1674 - * Not MT safe, please take the group lock
5.1675 - */
5.1676 -
5.1677 -static gboolean
5.1678 -gst_decode_group_expose (GstDecodeGroup * group)
5.1679 -{
5.1680 - GList *tmp;
5.1681 - GList *next = NULL;
5.1682 -
5.1683 - if (group->dbin->activegroup) {
5.1684 - GST_DEBUG_OBJECT (group->dbin, "A group is already active and exposed");
5.1685 - return TRUE;
5.1686 - }
5.1687 -
5.1688 - if (group->dbin->activegroup == group) {
5.1689 - GST_WARNING ("Group %p is already exposed", group);
5.1690 - return TRUE;
5.1691 - }
5.1692 -
5.1693 - if (!group->dbin->groups
5.1694 - || (group != (GstDecodeGroup *) group->dbin->groups->data)) {
5.1695 - GST_WARNING ("Group %p is not the first group to expose", group);
5.1696 - return FALSE;
5.1697 - }
5.1698 -
5.1699 - if (group->nbdynamic) {
5.1700 - GST_WARNING ("Group %p still has %d dynamic objects, not exposing yet",
5.1701 - group, group->nbdynamic);
5.1702 - return FALSE;
5.1703 - }
5.1704 -
5.1705 - GST_LOG ("Exposing group %p", group);
5.1706 -
5.1707 - /* re-order pads : video, then audio, then others */
5.1708 - group->endpads = g_list_sort (group->endpads, (GCompareFunc) sort_end_pads);
5.1709 -
5.1710 - /* Expose pads */
5.1711 -
5.1712 - for (tmp = group->endpads; tmp; tmp = next) {
5.1713 - GstDecodePad *dpad = (GstDecodePad *) tmp->data;
5.1714 - gchar *padname;
5.1715 - GstPad *ghost;
5.1716 -
5.1717 - next = g_list_next (tmp);
5.1718 -
5.1719 - /* 1. ghost pad */
5.1720 - padname = g_strdup_printf ("src%d", group->dbin->nbpads);
5.1721 - group->dbin->nbpads++;
5.1722 -
5.1723 - GST_LOG_OBJECT (group->dbin, "About to expose pad %s:%s",
5.1724 - GST_DEBUG_PAD_NAME (dpad->pad));
5.1725 -
5.1726 - ghost = gst_ghost_pad_new (padname, dpad->pad);
5.1727 - gst_pad_set_active (ghost, TRUE);
5.1728 - gst_element_add_pad (GST_ELEMENT (group->dbin), ghost);
5.1729 - group->ghosts = g_list_append (group->ghosts, ghost);
5.1730 -
5.1731 - g_free (padname);
5.1732 -
5.1733 - /* 2. emit signal */
5.1734 - GST_DEBUG_OBJECT (group->dbin, "emitting new-decoded-pad");
5.1735 - g_signal_emit (G_OBJECT (group->dbin),
5.1736 - gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD], 0, ghost,
5.1737 - (next == NULL));
5.1738 - GST_DEBUG_OBJECT (group->dbin, "emitted new-decoded-pad");
5.1739 -
5.1740 - /* 3. Unblock internal pad */
5.1741 - GST_DEBUG_OBJECT (dpad->pad, "unblocking");
5.1742 - gst_pad_set_blocked_async (dpad->pad, FALSE,
5.1743 - (GstPadBlockCallback) source_pad_blocked_cb, dpad);
5.1744 - GST_DEBUG_OBJECT (dpad->pad, "unblocked");
5.1745 -
5.1746 - }
5.1747 -
5.1748 - group->dbin->activegroup = group;
5.1749 -
5.1750 - /* pop off the first group */
5.1751 - group->dbin->groups =
5.1752 - g_list_delete_link (group->dbin->groups, group->dbin->groups);
5.1753 -
5.1754 - remove_fakesink (group->dbin);
5.1755 -
5.1756 - group->exposed = TRUE;
5.1757 -
5.1758 - GST_LOG_OBJECT (group->dbin, "signalling no-more-pads");
5.1759 - gst_element_no_more_pads (GST_ELEMENT (group->dbin));
5.1760 -
5.1761 - GST_LOG_OBJECT (group->dbin, "Group %p exposed", group);
5.1762 - return TRUE;
5.1763 -}
5.1764 -
5.1765 -static void
5.1766 -gst_decode_group_hide (GstDecodeGroup * group)
5.1767 -{
5.1768 - GList *tmp;
5.1769 -
5.1770 - GST_LOG ("Hiding group %p", group);
5.1771 -
5.1772 - if (group != group->dbin->activegroup) {
5.1773 - GST_WARNING ("This group is not the active one, aborting");
5.1774 - return;
5.1775 - }
5.1776 -
5.1777 - GROUP_MUTEX_LOCK (group);
5.1778 -
5.1779 - /* Remove ghost pads */
5.1780 - for (tmp = group->ghosts; tmp; tmp = g_list_next (tmp))
5.1781 - gst_element_remove_pad (GST_ELEMENT (group->dbin), (GstPad *) tmp->data);
5.1782 -
5.1783 - g_list_free (group->ghosts);
5.1784 - group->ghosts = NULL;
5.1785 -
5.1786 - group->exposed = FALSE;
5.1787 -
5.1788 - GROUP_MUTEX_UNLOCK (group);
5.1789 -
5.1790 - group->dbin->activegroup = NULL;
5.1791 - group->dbin->oldgroups = g_list_append (group->dbin->oldgroups, group);
5.1792 -}
5.1793 -
5.1794 -static void
5.1795 -deactivate_free_recursive (GstDecodeGroup * group, GstElement * element)
5.1796 -{
5.1797 - GstIterator *it;
5.1798 - GstIteratorResult res;
5.1799 - gpointer point;
5.1800 -
5.1801 - GST_LOG ("element:%s", GST_ELEMENT_NAME (element));
5.1802 -
5.1803 - /* call on downstream elements */
5.1804 - it = gst_element_iterate_src_pads (element);
5.1805 -
5.1806 -restart:
5.1807 -
5.1808 - while (1) {
5.1809 - res = gst_iterator_next (it, &point);
5.1810 - switch (res) {
5.1811 - case GST_ITERATOR_DONE:
5.1812 - goto done;
5.1813 - case GST_ITERATOR_RESYNC:
5.1814 - gst_iterator_resync (it);
5.1815 - goto restart;
5.1816 - case GST_ITERATOR_ERROR:
5.1817 - {
5.1818 - GST_WARNING ("Had an error while iterating source pads of element: %s",
5.1819 - GST_ELEMENT_NAME (element));
5.1820 - goto beach;
5.1821 - }
5.1822 - case GST_ITERATOR_OK:
5.1823 - {
5.1824 - GstPad *pad = GST_PAD (point);
5.1825 - GstPad *peerpad = NULL;
5.1826 -
5.1827 - if ((peerpad = gst_pad_get_peer (pad))) {
5.1828 - GstObject *parent = gst_pad_get_parent (peerpad);
5.1829 -
5.1830 - if (parent && GST_IS_ELEMENT (parent))
5.1831 - deactivate_free_recursive (group, GST_ELEMENT (parent));
5.1832 - if (parent)
5.1833 - gst_object_unref (parent);
5.1834 - }
5.1835 - }
5.1836 - break;
5.1837 - default:
5.1838 - break;
5.1839 - }
5.1840 - }
5.1841 -
5.1842 -done:
5.1843 - gst_element_set_state (element, GST_STATE_NULL);
5.1844 - gst_bin_remove (GST_BIN (group->dbin), element);
5.1845 -
5.1846 -beach:
5.1847 - gst_iterator_free (it);
5.1848 -
5.1849 - return;
5.1850 -}
5.1851 -
5.1852 -static void
5.1853 -gst_decode_group_free (GstDecodeGroup * group)
5.1854 -{
5.1855 - GList *tmp;
5.1856 -
5.1857 - GST_LOG ("group %p", group);
5.1858 -
5.1859 - GROUP_MUTEX_LOCK (group);
5.1860 - /* Clear all GstDecodePad */
5.1861 - for (tmp = group->endpads; tmp; tmp = g_list_next (tmp)) {
5.1862 - GstDecodePad *dpad = (GstDecodePad *) tmp->data;
5.1863 -
5.1864 - g_free (dpad);
5.1865 - }
5.1866 - g_list_free (group->endpads);
5.1867 - group->endpads = NULL;
5.1868 -
5.1869 - /* disconnect signal handlers on multiqueue */
5.1870 - g_signal_handler_disconnect (group->multiqueue, group->underrunsig);
5.1871 - g_signal_handler_disconnect (group->multiqueue, group->overrunsig);
5.1872 -
5.1873 - /* remove all elements */
5.1874 - deactivate_free_recursive (group, group->multiqueue);
5.1875 -
5.1876 - GROUP_MUTEX_UNLOCK (group);
5.1877 -
5.1878 - g_mutex_free (group->lock);
5.1879 - g_free (group);
5.1880 -}
5.1881 -
5.1882 -/* gst_decode_group_set_complete:
5.1883 - *
5.1884 - * Mark the group as complete. This means no more streams will be controlled
5.1885 - * through this group.
5.1886 - *
5.1887 - * MT safe
5.1888 - */
5.1889 -static void
5.1890 -gst_decode_group_set_complete (GstDecodeGroup * group)
5.1891 -{
5.1892 - GST_LOG_OBJECT (group->dbin, "Setting group %p to COMPLETE", group);
5.1893 -
5.1894 - GROUP_MUTEX_LOCK (group);
5.1895 - group->complete = TRUE;
5.1896 - gst_decode_group_check_if_blocked (group);
5.1897 - GROUP_MUTEX_UNLOCK (group);
5.1898 -}
5.1899 -
5.1900 -
5.1901 -
5.1902 -/*************************
5.1903 - * GstDecodePad functions
5.1904 - *************************/
5.1905 -
5.1906 -static void
5.1907 -source_pad_blocked_cb (GstPad * pad, gboolean blocked, GstDecodePad * dpad)
5.1908 -{
5.1909 - GST_LOG_OBJECT (pad, "blocked:%d , dpad:%p, dpad->group:%p",
5.1910 - blocked, dpad, dpad->group);
5.1911 -
5.1912 - /* Update this GstDecodePad status */
5.1913 - dpad->blocked = blocked;
5.1914 -
5.1915 - if (blocked) {
5.1916 - GROUP_MUTEX_LOCK (dpad->group);
5.1917 - gst_decode_group_check_if_blocked (dpad->group);
5.1918 - GROUP_MUTEX_UNLOCK (dpad->group);
5.1919 - }
5.1920 -}
5.1921 -
5.1922 -static gboolean
5.1923 -source_pad_event_probe (GstPad * pad, GstEvent * event, GstDecodePad * dpad)
5.1924 -{
5.1925 - GST_LOG_OBJECT (pad, "%s dpad:%p", GST_EVENT_TYPE_NAME (event), dpad);
5.1926 -
5.1927 - if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) {
5.1928 - /* Set our pad as drained */
5.1929 - dpad->drained = TRUE;
5.1930 -
5.1931 - /* Check if all pads are drained */
5.1932 - gst_decode_group_check_if_drained (dpad->group);
5.1933 - }
5.1934 -
5.1935 - return TRUE;
5.1936 -}
5.1937 -
5.1938 -/*gst_decode_pad_new:
5.1939 - *
5.1940 - * Creates a new GstDecodePad for the given pad.
5.1941 - * If block is TRUE, Sets the pad blocking asynchronously
5.1942 - */
5.1943 -
5.1944 -static GstDecodePad *
5.1945 -gst_decode_pad_new (GstDecodeGroup * group, GstPad * pad, gboolean block)
5.1946 -{
5.1947 - GstDecodePad *dpad;
5.1948 -
5.1949 - dpad = g_new0 (GstDecodePad, 1);
5.1950 - dpad->pad = pad;
5.1951 - dpad->group = group;
5.1952 - dpad->blocked = FALSE;
5.1953 - dpad->drained = TRUE;
5.1954 -
5.1955 - if (block)
5.1956 - gst_pad_set_blocked_async (pad, TRUE,
5.1957 - (GstPadBlockCallback) source_pad_blocked_cb, dpad);
5.1958 - gst_pad_add_event_probe (pad, G_CALLBACK (source_pad_event_probe), dpad);
5.1959 - return dpad;
5.1960 -}
5.1961 -
5.1962 -
5.1963 -/*****
5.1964 - * Element add/remove
5.1965 - *****/
5.1966 -
5.1967 -/*
5.1968 - * add_fakesink / remove_fakesink
5.1969 - *
5.1970 - * We use a sink so that the parent ::change_state returns GST_STATE_CHANGE_ASYNC
5.1971 - * when that sink is present (since it's not connected to anything it will
5.1972 - * always return GST_STATE_CHANGE_ASYNC).
5.1973 - *
5.1974 - * But this is an ugly way of achieving this goal.
5.1975 - * Ideally, we shouldn't use a sink and just return GST_STATE_CHANGE_ASYNC in
5.1976 - * our ::change_state if we have not exposed the active group.
5.1977 - * We also need to override ::get_state to fake the asynchronous behaviour.
5.1978 - * Once the active group is exposed, we would then post a
5.1979 - * GST_MESSAGE_STATE_DIRTY and return GST_STATE_CHANGE_SUCCESS (which will call
5.1980 - * ::get_state .
5.1981 - */
5.1982 -
5.1983 -static gboolean
5.1984 -add_fakesink (GstDecodeBin * decode_bin)
5.1985 -{
5.1986 - GST_DEBUG_OBJECT (decode_bin, "Adding the fakesink");
5.1987 -
5.1988 - if (decode_bin->fakesink)
5.1989 - return TRUE;
5.1990 -
5.1991 - decode_bin->fakesink =
5.1992 - gst_element_factory_make ("fakesink", "async-fakesink");
5.1993 - if (!decode_bin->fakesink)
5.1994 - goto no_fakesink;
5.1995 -
5.1996 - /* hacky, remove sink flag, we don't want our decodebin to become a sink
5.1997 - * just because we add a fakesink element to make us ASYNC */
5.1998 - GST_OBJECT_FLAG_UNSET (decode_bin->fakesink, GST_ELEMENT_IS_SINK);
5.1999 -
5.2000 - if (!gst_bin_add (GST_BIN (decode_bin), decode_bin->fakesink))
5.2001 - goto could_not_add;
5.2002 -
5.2003 - return TRUE;
5.2004 -
5.2005 - /* ERRORS */
5.2006 -no_fakesink:
5.2007 - {
5.2008 - g_warning ("can't find fakesink element, decodebin will not work");
5.2009 - return FALSE;
5.2010 - }
5.2011 -could_not_add:
5.2012 - {
5.2013 - g_warning ("Could not add fakesink to decodebin, decodebin will not work");
5.2014 - gst_object_unref (decode_bin->fakesink);
5.2015 - decode_bin->fakesink = NULL;
5.2016 - return FALSE;
5.2017 - }
5.2018 -}
5.2019 -
5.2020 -static void
5.2021 -remove_fakesink (GstDecodeBin * decode_bin)
5.2022 -{
5.2023 - if (decode_bin->fakesink == NULL)
5.2024 - return;
5.2025 -
5.2026 - GST_DEBUG_OBJECT (decode_bin, "Removing the fakesink");
5.2027 -
5.2028 - gst_element_set_state (decode_bin->fakesink, GST_STATE_NULL);
5.2029 - gst_bin_remove (GST_BIN (decode_bin), decode_bin->fakesink);
5.2030 - decode_bin->fakesink = NULL;
5.2031 -
5.2032 - gst_element_post_message (GST_ELEMENT_CAST (decode_bin),
5.2033 - gst_message_new_state_dirty (GST_OBJECT_CAST (decode_bin)));
5.2034 -}
5.2035 -
5.2036 -/*****
5.2037 - * convenience functions
5.2038 - *****/
5.2039 -
5.2040 -/* find_sink_pad
5.2041 - *
5.2042 - * Returns the first sink pad of the given element, or NULL if it doesn't have
5.2043 - * any.
5.2044 - */
5.2045 -
5.2046 -static GstPad *
5.2047 -find_sink_pad (GstElement * element)
5.2048 -{
5.2049 - GstIterator *it;
5.2050 - GstPad *pad = NULL;
5.2051 - gpointer point;
5.2052 -
5.2053 - it = gst_element_iterate_sink_pads (element);
5.2054 -
5.2055 - if ((gst_iterator_next (it, &point)) == GST_ITERATOR_OK)
5.2056 - pad = (GstPad *) point;
5.2057 -
5.2058 - gst_iterator_free (it);
5.2059 -
5.2060 - return pad;
5.2061 -}
5.2062 -
5.2063 -static GstStateChangeReturn
5.2064 -gst_decode_bin_change_state (GstElement * element, GstStateChange transition)
5.2065 -{
5.2066 - GstStateChangeReturn ret;
5.2067 - GstDecodeBin *dbin = GST_DECODE_BIN (element);
5.2068 -
5.2069 - switch (transition) {
5.2070 - case GST_STATE_CHANGE_NULL_TO_READY:
5.2071 - if (dbin->typefind == NULL)
5.2072 - goto missing_typefind;
5.2073 - break;
5.2074 - case GST_STATE_CHANGE_READY_TO_PAUSED:{
5.2075 - if (!add_fakesink (dbin))
5.2076 - goto missing_fakesink;
5.2077 - break;
5.2078 - }
5.2079 - default:
5.2080 - break;
5.2081 - }
5.2082 -
5.2083 - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
5.2084 -
5.2085 - /* FIXME : put some cleanup functions here.. if needed */
5.2086 -
5.2087 - return ret;
5.2088 -
5.2089 -/* ERRORS */
5.2090 -missing_typefind:
5.2091 - {
5.2092 - GST_ELEMENT_ERROR (dbin, CORE, MISSING_PLUGIN, (NULL), ("no typefind!"));
5.2093 - return GST_STATE_CHANGE_FAILURE;
5.2094 - }
5.2095 -missing_fakesink:
5.2096 - {
5.2097 - GST_ELEMENT_ERROR (dbin, CORE, MISSING_PLUGIN, (NULL), ("no fakesink!"));
5.2098 - return GST_STATE_CHANGE_FAILURE;
5.2099 - }
5.2100 -}
5.2101 -
5.2102 -static gboolean
5.2103 -plugin_init (GstPlugin * plugin)
5.2104 -{
5.2105 - GST_DEBUG_CATEGORY_INIT (gst_decode_bin_debug, "decodebin2", 0,
5.2106 - "decoder bin");
5.2107 -
5.2108 - return gst_element_register (plugin, "decodebin2", GST_RANK_NONE,
5.2109 - GST_TYPE_DECODE_BIN);
5.2110 -}
5.2111 -
5.2112 -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
5.2113 - GST_VERSION_MINOR,
5.2114 - "decodebin2",
5.2115 - "decoder bin newer version", plugin_init, VERSION, GST_LICENSE,
5.2116 - GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
6.1 --- a/gst-gmyth/decodebin2/gstplay-marshal.c Tue Sep 18 21:01:18 2007 +0100
6.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
6.3 @@ -1,167 +0,0 @@
6.4 -#include "gstplay-marshal.h"
6.5 -
6.6 -#include <glib-object.h>
6.7 -
6.8 -
6.9 -#ifdef G_ENABLE_DEBUG
6.10 -#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
6.11 -#define g_marshal_value_peek_char(v) g_value_get_char (v)
6.12 -#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
6.13 -#define g_marshal_value_peek_int(v) g_value_get_int (v)
6.14 -#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
6.15 -#define g_marshal_value_peek_long(v) g_value_get_long (v)
6.16 -#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
6.17 -#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
6.18 -#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
6.19 -#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
6.20 -#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
6.21 -#define g_marshal_value_peek_float(v) g_value_get_float (v)
6.22 -#define g_marshal_value_peek_double(v) g_value_get_double (v)
6.23 -#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
6.24 -#define g_marshal_value_peek_param(v) g_value_get_param (v)
6.25 -#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
6.26 -#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
6.27 -#define g_marshal_value_peek_object(v) g_value_get_object (v)
6.28 -#else /* !G_ENABLE_DEBUG */
6.29 -/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
6.30 - * Do not access GValues directly in your code. Instead, use the
6.31 - * g_value_get_*() functions
6.32 - */
6.33 -#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
6.34 -#define g_marshal_value_peek_char(v) (v)->data[0].v_int
6.35 -#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
6.36 -#define g_marshal_value_peek_int(v) (v)->data[0].v_int
6.37 -#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
6.38 -#define g_marshal_value_peek_long(v) (v)->data[0].v_long
6.39 -#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
6.40 -#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
6.41 -#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
6.42 -#define g_marshal_value_peek_enum(v) (v)->data[0].v_long
6.43 -#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
6.44 -#define g_marshal_value_peek_float(v) (v)->data[0].v_float
6.45 -#define g_marshal_value_peek_double(v) (v)->data[0].v_double
6.46 -#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
6.47 -#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
6.48 -#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
6.49 -#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
6.50 -#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
6.51 -#endif /* !G_ENABLE_DEBUG */
6.52 -
6.53 -
6.54 -/* BOOLEAN:OBJECT (gstplay-marshal.list:1) */
6.55 -void
6.56 -gst_play_marshal_BOOLEAN__OBJECT (GClosure *closure,
6.57 - GValue *return_value,
6.58 - guint n_param_values,
6.59 - const GValue *param_values,
6.60 - gpointer invocation_hint,
6.61 - gpointer marshal_data)
6.62 -{
6.63 - typedef gboolean (*GMarshalFunc_BOOLEAN__OBJECT) (gpointer data1,
6.64 - gpointer arg_1,
6.65 - gpointer data2);
6.66 - register GMarshalFunc_BOOLEAN__OBJECT callback;
6.67 - register GCClosure *cc = (GCClosure*) closure;
6.68 - register gpointer data1, data2;
6.69 - gboolean v_return;
6.70 -
6.71 - g_return_if_fail (return_value != NULL);
6.72 - g_return_if_fail (n_param_values == 2);
6.73 -
6.74 - if (G_CCLOSURE_SWAP_DATA (closure))
6.75 - {
6.76 - data1 = closure->data;
6.77 - data2 = g_value_peek_pointer (param_values + 0);
6.78 - }
6.79 - else
6.80 - {
6.81 - data1 = g_value_peek_pointer (param_values + 0);
6.82 - data2 = closure->data;
6.83 - }
6.84 - callback = (GMarshalFunc_BOOLEAN__OBJECT) (marshal_data ? marshal_data : cc->callback);
6.85 -
6.86 - v_return = callback (data1,
6.87 - g_marshal_value_peek_object (param_values + 1),
6.88 - data2);
6.89 -
6.90 - g_value_set_boolean (return_value, v_return);
6.91 -}
6.92 -
6.93 -/* VOID:OBJECT,BOOLEAN (gstplay-marshal.list:2) */
6.94 -void
6.95 -gst_play_marshal_VOID__OBJECT_BOOLEAN (GClosure *closure,
6.96 - GValue *return_value,
6.97 - guint n_param_values,
6.98 - const GValue *param_values,
6.99 - gpointer invocation_hint,
6.100 - gpointer marshal_data)
6.101 -{
6.102 - typedef void (*GMarshalFunc_VOID__OBJECT_BOOLEAN) (gpointer data1,
6.103 - gpointer arg_1,
6.104 - gboolean arg_2,
6.105 - gpointer data2);
6.106 - register GMarshalFunc_VOID__OBJECT_BOOLEAN callback;
6.107 - register GCClosure *cc = (GCClosure*) closure;
6.108 - register gpointer data1, data2;
6.109 -
6.110 - g_return_if_fail (n_param_values == 3);
6.111 -
6.112 - if (G_CCLOSURE_SWAP_DATA (closure))
6.113 - {
6.114 - data1 = closure->data;
6.115 - data2 = g_value_peek_pointer (param_values + 0);
6.116 - }
6.117 - else
6.118 - {
6.119 - data1 = g_value_peek_pointer (param_values + 0);
6.120 - data2 = closure->data;
6.121 - }
6.122 - callback = (GMarshalFunc_VOID__OBJECT_BOOLEAN) (marshal_data ? marshal_data : cc->callback);
6.123 -
6.124 - callback (data1,
6.125 - g_marshal_value_peek_object (param_values + 1),
6.126 - g_marshal_value_peek_boolean (param_values + 2),
6.127 - data2);
6.128 -}
6.129 -
6.130 -/* BOOLEAN:OBJECT,POINTER (gstplay-marshal.list:3) */
6.131 -void
6.132 -gst_play_marshal_BOOLEAN__OBJECT_POINTER (GClosure *closure,
6.133 - GValue *return_value,
6.134 - guint n_param_values,
6.135 - const GValue *param_values,
6.136 - gpointer invocation_hint,
6.137 - gpointer marshal_data)
6.138 -{
6.139 - typedef gboolean (*GMarshalFunc_BOOLEAN__OBJECT_POINTER) (gpointer data1,
6.140 - gpointer arg_1,
6.141 - gpointer arg_2,
6.142 - gpointer data2);
6.143 - register GMarshalFunc_BOOLEAN__OBJECT_POINTER callback;
6.144 - register GCClosure *cc = (GCClosure*) closure;
6.145 - register gpointer data1, data2;
6.146 - gboolean v_return;
6.147 -
6.148 - g_return_if_fail (return_value != NULL);
6.149 - g_return_if_fail (n_param_values == 3);
6.150 -
6.151 - if (G_CCLOSURE_SWAP_DATA (closure))
6.152 - {
6.153 - data1 = closure->data;
6.154 - data2 = g_value_peek_pointer (param_values + 0);
6.155 - }
6.156 - else
6.157 - {
6.158 - data1 = g_value_peek_pointer (param_values + 0);
6.159 - data2 = closure->data;
6.160 - }
6.161 - callback = (GMarshalFunc_BOOLEAN__OBJECT_POINTER) (marshal_data ? marshal_data : cc->callback);
6.162 -
6.163 - v_return = callback (data1,
6.164 - g_marshal_value_peek_object (param_values + 1),
6.165 - g_marshal_value_peek_pointer (param_values + 2),
6.166 - data2);
6.167 -
6.168 - g_value_set_boolean (return_value, v_return);
6.169 -}
6.170 -
7.1 --- a/gst-gmyth/decodebin2/gstplay-marshal.h Tue Sep 18 21:01:18 2007 +0100
7.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
7.3 @@ -1,36 +0,0 @@
7.4 -
7.5 -#ifndef __gst_play_marshal_MARSHAL_H__
7.6 -#define __gst_play_marshal_MARSHAL_H__
7.7 -
7.8 -#include <glib-object.h>
7.9 -
7.10 -G_BEGIN_DECLS
7.11 -
7.12 -/* BOOLEAN:OBJECT (gstplay-marshal.list:1) */
7.13 -extern void gst_play_marshal_BOOLEAN__OBJECT (GClosure *closure,
7.14 - GValue *return_value,
7.15 - guint n_param_values,
7.16 - const GValue *param_values,
7.17 - gpointer invocation_hint,
7.18 - gpointer marshal_data);
7.19 -
7.20 -/* VOID:OBJECT,BOOLEAN (gstplay-marshal.list:2) */
7.21 -extern void gst_play_marshal_VOID__OBJECT_BOOLEAN (GClosure *closure,
7.22 - GValue *return_value,
7.23 - guint n_param_values,
7.24 - const GValue *param_values,
7.25 - gpointer invocation_hint,
7.26 - gpointer marshal_data);
7.27 -
7.28 -/* BOOLEAN:OBJECT,POINTER (gstplay-marshal.list:3) */
7.29 -extern void gst_play_marshal_BOOLEAN__OBJECT_POINTER (GClosure *closure,
7.30 - GValue *return_value,
7.31 - guint n_param_values,
7.32 - const GValue *param_values,
7.33 - gpointer invocation_hint,
7.34 - gpointer marshal_data);
7.35 -
7.36 -G_END_DECLS
7.37 -
7.38 -#endif /* __gst_play_marshal_MARSHAL_H__ */
7.39 -
8.1 --- a/gst-gmyth/multiqueue/Makefile.am Tue Sep 18 21:01:18 2007 +0100
8.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
8.3 @@ -1,24 +0,0 @@
8.4 -plugin_LTLIBRARIES = libgstmultiqueue.la
8.5 -
8.6 -libgstmultiqueue_la_SOURCES = \
8.7 - gstmultiqueue.c \
8.8 - gstdataqueue.c
8.9 -
8.10 -libgstmultiqueue_la_CFLAGS = \
8.11 - $(GST_CFLAGS) \
8.12 - $(GST_BASE_CFLAGS) \
8.13 - $(GST_PLUGINS_BASE_CFLAGS)
8.14 -
8.15 -libgstmultiqueue_la_LIBADD = \
8.16 - $(GST_LIBS_LIBS)
8.17 -
8.18 -libgstmultiqueue_la_LDFLAGS = \
8.19 - $(GST_LIBS) \
8.20 - $(GST_PLUGIN_LDFLAGS) \
8.21 - $(GST_BASE_LIBS) \
8.22 - $(GST_PLUGINS_BASE_LIBS)
8.23 -
8.24 -noinst_HEADERS = \
8.25 - gstmultiqueue.h \
8.26 - gstdataqueue.h
8.27 -
9.1 --- a/gst-gmyth/multiqueue/gstdataqueue.c Tue Sep 18 21:01:18 2007 +0100
9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
9.3 @@ -1,628 +0,0 @@
9.4 -/* GStreamer
9.5 - * Copyright (C) 2006 Edward Hervey <edward@fluendo.com>
9.6 - *
9.7 - * gstdataqueue.c:
9.8 - *
9.9 - * This library is free software; you can redistribute it and/or
9.10 - * modify it under the terms of the GNU Library General Public
9.11 - * License as published by the Free Software Foundation; either
9.12 - * version 2 of the License, or (at your option) any later version.
9.13 - *
9.14 - * This library is distributed in the hope that it will be useful,
9.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
9.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9.17 - * Library General Public License for more details.
9.18 - *
9.19 - * You should have received a copy of the GNU Library General Public
9.20 - * License along with this library; if not, write to the
9.21 - * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
9.22 - * Boston, MA 02111-1307, USA.
9.23 - */
9.24 -
9.25 -/**
9.26 - * SECTION:gstdataqueue
9.27 - * @short_description: Threadsafe queueing object
9.28 - *
9.29 - * #GstDataQueue is an object that handles threadsafe queueing of objects. It
9.30 - * also provides size-related functionality. This object should be used for
9.31 - * any #GstElement that wishes to provide some sort of queueing functionality.
9.32 - */
9.33 -
9.34 -#include <gst/gst.h>
9.35 -#include "gstdataqueue.h"
9.36 -
9.37 -GST_DEBUG_CATEGORY_STATIC (data_queue_debug);
9.38 -#define GST_CAT_DEFAULT (data_queue_debug)
9.39 -GST_DEBUG_CATEGORY_STATIC (data_queue_dataflow);
9.40 -
9.41 -
9.42 -/* Queue signals and args */
9.43 -enum
9.44 -{
9.45 - SIGNAL_EMPTY,
9.46 - SIGNAL_FULL,
9.47 - LAST_SIGNAL
9.48 -};
9.49 -
9.50 -enum
9.51 -{
9.52 - ARG_0,
9.53 - ARG_CUR_LEVEL_VISIBLE,
9.54 - ARG_CUR_LEVEL_BYTES,
9.55 - ARG_CUR_LEVEL_TIME
9.56 - /* FILL ME */
9.57 -};
9.58 -
9.59 -#define GST_DATA_QUEUE_MUTEX_LOCK(q) G_STMT_START { \
9.60 - GST_CAT_LOG (data_queue_dataflow, \
9.61 - "locking qlock from thread %p", \
9.62 - g_thread_self ()); \
9.63 - g_mutex_lock (q->qlock); \
9.64 - GST_CAT_LOG (data_queue_dataflow, \
9.65 - "locked qlock from thread %p", \
9.66 - g_thread_self ()); \
9.67 -} G_STMT_END
9.68 -
9.69 -#define GST_DATA_QUEUE_MUTEX_LOCK_CHECK(q, label) G_STMT_START { \
9.70 - GST_DATA_QUEUE_MUTEX_LOCK (q); \
9.71 - if (q->flushing) \
9.72 - goto label; \
9.73 - } G_STMT_END
9.74 -
9.75 -#define GST_DATA_QUEUE_MUTEX_UNLOCK(q) G_STMT_START { \
9.76 - GST_CAT_LOG (data_queue_dataflow, \
9.77 - "unlocking qlock from thread %p", \
9.78 - g_thread_self ()); \
9.79 - g_mutex_unlock (q->qlock); \
9.80 -} G_STMT_END
9.81 -
9.82 -#define STATUS(q, msg) \
9.83 - GST_CAT_LOG (data_queue_dataflow, \
9.84 - "queue:%p " msg ": %u visible items, %u " \
9.85 - "bytes, %"G_GUINT64_FORMAT \
9.86 - " ns, %u elements", \
9.87 - queue, \
9.88 - q->cur_level.visible, \
9.89 - q->cur_level.bytes, \
9.90 - q->cur_level.time, \
9.91 - q->queue->length)
9.92 -
9.93 -static void gst_data_queue_base_init (GstDataQueueClass * klass);
9.94 -static void gst_data_queue_class_init (GstDataQueueClass * klass);
9.95 -static void gst_data_queue_init (GstDataQueue * queue);
9.96 -static void gst_data_queue_finalize (GObject * object);
9.97 -
9.98 -static void gst_data_queue_set_property (GObject * object,
9.99 - guint prop_id, const GValue * value, GParamSpec * pspec);
9.100 -static void gst_data_queue_get_property (GObject * object,
9.101 - guint prop_id, GValue * value, GParamSpec * pspec);
9.102 -
9.103 -static GObjectClass *parent_class = NULL;
9.104 -static guint gst_data_queue_signals[LAST_SIGNAL] = { 0 };
9.105 -
9.106 -GType
9.107 -gst_data_queue_get_type (void)
9.108 -{
9.109 - static GType queue_type = 0;
9.110 -
9.111 - if (!queue_type) {
9.112 - static const GTypeInfo queue_info = {
9.113 - sizeof (GstDataQueueClass),
9.114 - (GBaseInitFunc) gst_data_queue_base_init,
9.115 - NULL,
9.116 - (GClassInitFunc) gst_data_queue_class_init,
9.117 - NULL,
9.118 - NULL,
9.119 - sizeof (GstDataQueue),
9.120 - 0,
9.121 - (GInstanceInitFunc) gst_data_queue_init,
9.122 - NULL
9.123 - };
9.124 -
9.125 - queue_type = g_type_register_static (G_TYPE_OBJECT,
9.126 - "GstDataQueue", &queue_info, 0);
9.127 - GST_DEBUG_CATEGORY_INIT (data_queue_debug, "dataqueue", 0,
9.128 - "data queue object");
9.129 - GST_DEBUG_CATEGORY_INIT (data_queue_dataflow, "data_queue_dataflow", 0,
9.130 - "dataflow inside the data queue object");
9.131 - }
9.132 -
9.133 - return queue_type;
9.134 -}
9.135 -
9.136 -static void
9.137 -gst_data_queue_base_init (GstDataQueueClass * klass)
9.138 -{
9.139 - /* Do we need anything here ?? */
9.140 - return;
9.141 -}
9.142 -
9.143 -static void
9.144 -gst_data_queue_class_init (GstDataQueueClass * klass)
9.145 -{
9.146 - GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
9.147 -
9.148 - parent_class = g_type_class_peek_parent (klass);
9.149 -
9.150 - gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_data_queue_set_property);
9.151 - gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_data_queue_get_property);
9.152 -
9.153 - /* signals */
9.154 - /**
9.155 - * GstDataQueue::empty:
9.156 - * @queue: the queue instance
9.157 - *
9.158 - * Reports that the queue became empty (empty).
9.159 - * A queue is empty if the total amount of visible items inside it (num-visible, time,
9.160 - * size) is lower than the boundary values which can be set through the GObject
9.161 - * properties.
9.162 - */
9.163 - gst_data_queue_signals[SIGNAL_EMPTY] =
9.164 - g_signal_new ("empty", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
9.165 - G_STRUCT_OFFSET (GstDataQueueClass, empty), NULL, NULL,
9.166 - g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
9.167 -
9.168 - /**
9.169 - * GstDataQueue::full:
9.170 - * @queue: the queue instance
9.171 - *
9.172 - * Reports that the queue became full (full).
9.173 - * A queue is full if the total amount of data inside it (num-visible, time,
9.174 - * size) is higher than the boundary values which can be set through the GObject
9.175 - * properties.
9.176 - */
9.177 - gst_data_queue_signals[SIGNAL_FULL] =
9.178 - g_signal_new ("full", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
9.179 - G_STRUCT_OFFSET (GstDataQueueClass, full), NULL, NULL,
9.180 - g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
9.181 -
9.182 - /* properties */
9.183 - g_object_class_install_property (gobject_class, ARG_CUR_LEVEL_BYTES,
9.184 - g_param_spec_uint ("current-level-bytes", "Current level (kB)",
9.185 - "Current amount of data in the queue (bytes)",
9.186 - 0, G_MAXUINT, 0, G_PARAM_READABLE));
9.187 - g_object_class_install_property (gobject_class, ARG_CUR_LEVEL_VISIBLE,
9.188 - g_param_spec_uint ("current-level-visible",
9.189 - "Current level (visible items)",
9.190 - "Current number of visible items in the queue", 0, G_MAXUINT, 0,
9.191 - G_PARAM_READABLE));
9.192 - g_object_class_install_property (gobject_class, ARG_CUR_LEVEL_TIME,
9.193 - g_param_spec_uint64 ("current-level-time", "Current level (ns)",
9.194 - "Current amount of data in the queue (in ns)", 0, G_MAXUINT64, 0,
9.195 - G_PARAM_READABLE));
9.196 -
9.197 - /* set several parent class virtual functions */
9.198 - gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_data_queue_finalize);
9.199 -
9.200 -}
9.201 -
9.202 -static void
9.203 -gst_data_queue_init (GstDataQueue * queue)
9.204 -{
9.205 - queue->cur_level.visible = 0; /* no content */
9.206 - queue->cur_level.bytes = 0; /* no content */
9.207 - queue->cur_level.time = 0; /* no content */
9.208 -
9.209 - queue->checkfull = NULL;
9.210 -
9.211 - queue->qlock = g_mutex_new ();
9.212 - queue->item_add = g_cond_new ();
9.213 - queue->item_del = g_cond_new ();
9.214 - queue->queue = g_queue_new ();
9.215 -
9.216 - GST_DEBUG ("initialized queue's not_empty & not_full conditions");
9.217 -}
9.218 -
9.219 -/**
9.220 - * gst_data_queue_new:
9.221 - * @checkfull: the callback used to tell if the element considers the queue full
9.222 - * or not.
9.223 - * @checkdata: a #gpointer that will be given in the @checkfull callback.
9.224 - *
9.225 - * Returns: a new #GstDataQueue.
9.226 - */
9.227 -
9.228 -GstDataQueue *
9.229 -gst_data_queue_new (GstDataQueueCheckFullFunction checkfull, gpointer checkdata)
9.230 -{
9.231 - GstDataQueue *ret;
9.232 -
9.233 - g_return_val_if_fail (checkfull != NULL, NULL);
9.234 -
9.235 - ret = g_object_new (GST_TYPE_DATA_QUEUE, NULL);
9.236 - ret->checkfull = checkfull;
9.237 - ret->checkdata = checkdata;
9.238 -
9.239 - return ret;
9.240 -}
9.241 -
9.242 -static void
9.243 -gst_data_queue_cleanup (GstDataQueue * queue)
9.244 -{
9.245 - while (!g_queue_is_empty (queue->queue)) {
9.246 - GstDataQueueItem *item = g_queue_pop_head (queue->queue);
9.247 -
9.248 - /* Just call the destroy notify on the item */
9.249 - item->destroy (item);
9.250 - }
9.251 - queue->cur_level.visible = 0;
9.252 - queue->cur_level.bytes = 0;
9.253 - queue->cur_level.time = 0;
9.254 -}
9.255 -
9.256 -/* called only once, as opposed to dispose */
9.257 -static void
9.258 -gst_data_queue_finalize (GObject * object)
9.259 -{
9.260 - GstDataQueue *queue = GST_DATA_QUEUE (object);
9.261 -
9.262 - GST_DEBUG ("finalizing queue");
9.263 -
9.264 - gst_data_queue_cleanup (queue);
9.265 - g_queue_free (queue->queue);
9.266 -
9.267 - GST_DEBUG ("free mutex");
9.268 - g_mutex_free (queue->qlock);
9.269 - GST_DEBUG ("done free mutex");
9.270 -
9.271 - g_cond_free (queue->item_add);
9.272 - g_cond_free (queue->item_del);
9.273 -
9.274 - G_OBJECT_CLASS (parent_class)->finalize (object);
9.275 -}
9.276 -
9.277 -static void
9.278 -gst_data_queue_locked_flush (GstDataQueue * queue)
9.279 -{
9.280 - STATUS (queue, "before flushing");
9.281 - gst_data_queue_cleanup (queue);
9.282 - STATUS (queue, "after flushing");
9.283 - /* we deleted something... */
9.284 - g_cond_signal (queue->item_del);
9.285 -}
9.286 -
9.287 -static gboolean
9.288 -gst_data_queue_locked_is_empty (GstDataQueue * queue)
9.289 -{
9.290 - return (queue->queue->length == 0);
9.291 -}
9.292 -
9.293 -static gboolean
9.294 -gst_data_queue_locked_is_full (GstDataQueue * queue)
9.295 -{
9.296 - return queue->checkfull (queue, queue->cur_level.visible,
9.297 - queue->cur_level.bytes, queue->cur_level.time, queue->checkdata);
9.298 -}
9.299 -
9.300 -/**
9.301 - * gst_data_queue_flush:
9.302 - * @queue: a #GstDataQueue.
9.303 - *
9.304 - * Flushes all the contents of the @queue. Any call to #gst_data_queue_pull and
9.305 - * #gst_data_queue_pop will be released.
9.306 - * MT safe.
9.307 - */
9.308 -void
9.309 -gst_data_queue_flush (GstDataQueue * queue)
9.310 -{
9.311 - GST_DEBUG ("queue:%p", queue);
9.312 - GST_DATA_QUEUE_MUTEX_LOCK (queue);
9.313 - gst_data_queue_locked_flush (queue);
9.314 - GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
9.315 -}
9.316 -
9.317 -/**
9.318 - * gst_data_queue_is_empty:
9.319 - * @queue: a #GstDataQueue.
9.320 - *
9.321 - * Queries if there are any items in the @queue.
9.322 - * MT safe.
9.323 - *
9.324 - * Returns: #TRUE if @queue is empty.
9.325 - */
9.326 -gboolean
9.327 -gst_data_queue_is_empty (GstDataQueue * queue)
9.328 -{
9.329 - gboolean res;
9.330 -
9.331 - GST_DATA_QUEUE_MUTEX_LOCK (queue);
9.332 - res = gst_data_queue_locked_is_empty (queue);
9.333 - GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
9.334 -
9.335 - return res;
9.336 -}
9.337 -
9.338 -/**
9.339 - * gst_data_queue_is_full:
9.340 - * @queue: a #GstDataQueue.
9.341 - *
9.342 - * Queries if @queue is full. This check will be done using the
9.343 - * #GstDataQueueCheckFullCallback registered with @queue.
9.344 - * MT safe.
9.345 - *
9.346 - * Returns: #TRUE if @queue is full.
9.347 - */
9.348 -gboolean
9.349 -gst_data_queue_is_full (GstDataQueue * queue)
9.350 -{
9.351 - gboolean res;
9.352 -
9.353 - GST_DATA_QUEUE_MUTEX_LOCK (queue);
9.354 - res = gst_data_queue_locked_is_full (queue);
9.355 - GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
9.356 -
9.357 - return res;
9.358 -}
9.359 -
9.360 -/**
9.361 - * gst_data_queue_set_flushing:
9.362 - * @queue: a #GstDataQueue.
9.363 - * @flushing: a #gboolean stating if the queue will be flushing or not.
9.364 - *
9.365 - * Sets the queue to flushing state if @flushing is #TRUE. If set to flushing
9.366 - * state, any incoming data on the @queue will be discarded. Any call currently
9.367 - * blocking on #gst_data_queue_push or #gst_data_queue_pop will return straight
9.368 - * away with a return value of #FALSE. While the @queue is in flushing state,
9.369 - * all calls to those two functions will return #FALSE.
9.370 - *
9.371 - * MT Safe.
9.372 - */
9.373 -void
9.374 -gst_data_queue_set_flushing (GstDataQueue * queue, gboolean flushing)
9.375 -{
9.376 - GST_DEBUG ("queue:%p , flushing:%d", queue, flushing);
9.377 -
9.378 - GST_DATA_QUEUE_MUTEX_LOCK (queue);
9.379 - queue->flushing = flushing;
9.380 - if (flushing) {
9.381 - /* release push/pop functions */
9.382 - g_cond_signal (queue->item_add);
9.383 - g_cond_signal (queue->item_del);
9.384 - }
9.385 - GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
9.386 -}
9.387 -
9.388 -/**
9.389 - * gst_data_queue_push:
9.390 - * @queue: a #GstDataQueue.
9.391 - * @item: a #GstDataQueueItem.
9.392 - *
9.393 - * Pushes a #GstDataQueueItem (or a structure that begins with the same fields)
9.394 - * on the @queue. If the @queue is full, the call will block until space is
9.395 - * available, OR the @queue is set to flushing state.
9.396 - * MT safe.
9.397 - *
9.398 - * Note that this function has slightly different semantics than gst_pad_push()
9.399 - * and gst_pad_push_event(): this function only takes ownership of @item and
9.400 - * the #GstMiniObject contained in @item if the push was successful. If FALSE
9.401 - * is returned, the caller is responsible for freeing @item and its contents.
9.402 - *
9.403 - * Returns: #TRUE if the @item was successfully pushed on the @queue.
9.404 - */
9.405 -gboolean
9.406 -gst_data_queue_push (GstDataQueue * queue, GstDataQueueItem * item)
9.407 -{
9.408 - g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE);
9.409 - g_return_val_if_fail (item != NULL, FALSE);
9.410 -
9.411 - GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing);
9.412 -
9.413 - STATUS (queue, "before pushing");
9.414 -
9.415 - /* We ALWAYS need to check for queue fillness */
9.416 - if (gst_data_queue_locked_is_full (queue)) {
9.417 - GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
9.418 - g_signal_emit (G_OBJECT (queue), gst_data_queue_signals[SIGNAL_FULL], 0);
9.419 - GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing);
9.420 -
9.421 - /* signal might have removed some items */
9.422 - while (gst_data_queue_locked_is_full (queue)) {
9.423 - g_cond_wait (queue->item_del, queue->qlock);
9.424 - if (queue->flushing)
9.425 - goto flushing;
9.426 - }
9.427 - }
9.428 -
9.429 - g_queue_push_tail (queue->queue, item);
9.430 -
9.431 - if (item->visible)
9.432 - queue->cur_level.visible++;
9.433 - queue->cur_level.bytes += item->size;
9.434 - queue->cur_level.time += item->duration;
9.435 -
9.436 - STATUS (queue, "after pushing");
9.437 - g_cond_signal (queue->item_add);
9.438 -
9.439 - GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
9.440 -
9.441 - return TRUE;
9.442 -
9.443 - /* ERRORS */
9.444 -flushing:
9.445 - {
9.446 - GST_DEBUG ("queue:%p, we are flushing", queue);
9.447 - GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
9.448 - return FALSE;
9.449 - }
9.450 -}
9.451 -
9.452 -/**
9.453 - * gst_data_queue_pop:
9.454 - * @queue: a #GstDataQueue.
9.455 - * @item: pointer to store the returned #GstDataQueueItem.
9.456 - *
9.457 - * Retrieves the first @item available on the @queue. If the queue is currently
9.458 - * empty, the call will block until at least one item is available, OR the
9.459 - * @queue is set to the flushing state.
9.460 - * MT safe.
9.461 - *
9.462 - * Returns: #TRUE if an @item was successfully retrieved from the @queue.
9.463 - */
9.464 -gboolean
9.465 -gst_data_queue_pop (GstDataQueue * queue, GstDataQueueItem ** item)
9.466 -{
9.467 - g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE);
9.468 - g_return_val_if_fail (item != NULL, FALSE);
9.469 -
9.470 - GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing);
9.471 -
9.472 - STATUS (queue, "before popping");
9.473 -
9.474 - if (gst_data_queue_locked_is_empty (queue)) {
9.475 - GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
9.476 - g_signal_emit (G_OBJECT (queue), gst_data_queue_signals[SIGNAL_EMPTY], 0);
9.477 - GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing);
9.478 -
9.479 - while (gst_data_queue_locked_is_empty (queue)) {
9.480 - g_cond_wait (queue->item_add, queue->qlock);
9.481 - if (queue->flushing)
9.482 - goto flushing;
9.483 - }
9.484 - }
9.485 -
9.486 - /* Get the item from the GQueue */
9.487 - *item = g_queue_pop_head (queue->queue);
9.488 -
9.489 - /* update current level counter */
9.490 - if ((*item)->visible)
9.491 - queue->cur_level.visible--;
9.492 - queue->cur_level.bytes -= (*item)->size;
9.493 - queue->cur_level.time -= (*item)->duration;
9.494 -
9.495 - STATUS (queue, "after popping");
9.496 - g_cond_signal (queue->item_del);
9.497 -
9.498 - GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
9.499 -
9.500 - return TRUE;
9.501 -
9.502 - /* ERRORS */
9.503 -flushing:
9.504 - {
9.505 - GST_DEBUG ("queue:%p, we are flushing", queue);
9.506 - GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
9.507 - return FALSE;
9.508 - }
9.509 -}
9.510 -
9.511 -/**
9.512 - * gst_data_queue_drop_head:
9.513 - * @queue: The #GstDataQueue to drop an item from.
9.514 - * @type: The #GType of the item to drop.
9.515 - *
9.516 - * Pop and unref the head-most #GstMiniObject with the given #GType.
9.517 - *
9.518 - * Returns: TRUE if an element was removed.
9.519 - */
9.520 -gboolean
9.521 -gst_data_queue_drop_head (GstDataQueue * queue, GType type)
9.522 -{
9.523 - gboolean res = FALSE;
9.524 - GList *item;
9.525 - GstDataQueueItem *leak = NULL;
9.526 -
9.527 - g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE);
9.528 -
9.529 - GST_DEBUG ("queue:%p", queue);
9.530 -
9.531 - GST_DATA_QUEUE_MUTEX_LOCK (queue);
9.532 - for (item = g_queue_peek_head_link (queue->queue); item; item = item->next) {
9.533 - GstDataQueueItem *tmp = (GstDataQueueItem *) item->data;
9.534 -
9.535 - if (G_TYPE_CHECK_INSTANCE_TYPE (tmp->object, type)) {
9.536 - leak = tmp;
9.537 - break;
9.538 - }
9.539 - }
9.540 -
9.541 - if (!leak)
9.542 - goto done;
9.543 -
9.544 - g_queue_delete_link (queue->queue, item);
9.545 -
9.546 - if (leak->visible)
9.547 - queue->cur_level.visible--;
9.548 - queue->cur_level.bytes -= leak->size;
9.549 - queue->cur_level.time -= leak->duration;
9.550 -
9.551 - leak->destroy (leak);
9.552 -
9.553 - res = TRUE;
9.554 -
9.555 -done:
9.556 - GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
9.557 -
9.558 - GST_DEBUG ("queue:%p , res:%d", queue, res);
9.559 -
9.560 - return res;
9.561 -}
9.562 -
9.563 -/**
9.564 - * gst_data_queue_limits_changed:
9.565 - * @queue: The #GstDataQueue
9.566 - *
9.567 - * Inform the queue that the limits for the fullness check have changed and that
9.568 - * any blocking gst_data_queue_push() should be unblocked to recheck the limts.
9.569 - */
9.570 -void
9.571 -gst_data_queue_limits_changed (GstDataQueue * queue)
9.572 -{
9.573 - g_return_if_fail (GST_IS_DATA_QUEUE (queue));
9.574 -
9.575 - GST_DATA_QUEUE_MUTEX_LOCK (queue);
9.576 - GST_DEBUG ("signal del");
9.577 - g_cond_signal (queue->item_del);
9.578 - GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
9.579 -}
9.580 -
9.581 -/**
9.582 - * gst_data_queue_get_level:
9.583 - * @queue: The #GstDataQueue
9.584 - * @level: the location to store the result
9.585 - *
9.586 - * Get the current level of the queue.
9.587 - */
9.588 -void
9.589 -gst_data_queue_get_level (GstDataQueue * queue, GstDataQueueSize * level)
9.590 -{
9.591 - level->visible = queue->cur_level.visible;
9.592 - level->bytes = queue->cur_level.bytes;
9.593 - level->time = queue->cur_level.time;
9.594 -}
9.595 -
9.596 -static void
9.597 -gst_data_queue_set_property (GObject * object,
9.598 - guint prop_id, const GValue * value, GParamSpec * pspec)
9.599 -{
9.600 - switch (prop_id) {
9.601 - default:
9.602 - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
9.603 - break;
9.604 - }
9.605 -}
9.606 -
9.607 -static void
9.608 -gst_data_queue_get_property (GObject * object,
9.609 - guint prop_id, GValue * value, GParamSpec * pspec)
9.610 -{
9.611 - GstDataQueue *queue = GST_DATA_QUEUE (object);
9.612 -
9.613 - GST_DATA_QUEUE_MUTEX_LOCK (queue);
9.614 -
9.615 - switch (prop_id) {
9.616 - case ARG_CUR_LEVEL_BYTES:
9.617 - g_value_set_uint (value, queue->cur_level.bytes);
9.618 - break;
9.619 - case ARG_CUR_LEVEL_VISIBLE:
9.620 - g_value_set_uint (value, queue->cur_level.visible);
9.621 - break;
9.622 - case ARG_CUR_LEVEL_TIME:
9.623 - g_value_set_uint64 (value, queue->cur_level.time);
9.624 - break;
9.625 - default:
9.626 - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
9.627 - break;
9.628 - }
9.629 -
9.630 - GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
9.631 -}
10.1 --- a/gst-gmyth/multiqueue/gstdataqueue.h Tue Sep 18 21:01:18 2007 +0100
10.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
10.3 @@ -1,159 +0,0 @@
10.4 -/* GStreamer
10.5 - * Copyright (C) 2006 Edward Hervey <edward@fluendo.com>
10.6 - *
10.7 - * gstdataqueue.h:
10.8 - *
10.9 - * This library is free software; you can redistribute it and/or
10.10 - * modify it under the terms of the GNU Library General Public
10.11 - * License as published by the Free Software Foundation; either
10.12 - * version 2 of the License, or (at your option) any later version.
10.13 - *
10.14 - * This library is distributed in the hope that it will be useful,
10.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
10.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10.17 - * Library General Public License for more details.
10.18 - *
10.19 - * You should have received a copy of the GNU Library General Public
10.20 - * License along with this library; if not, write to the
10.21 - * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
10.22 - * Boston, MA 02111-1307, USA.
10.23 - */
10.24 -
10.25 -
10.26 -#ifndef __GST_DATA_QUEUE_H__
10.27 -#define __GST_DATA_QUEUE_H__
10.28 -
10.29 -#include <gst/gst.h>
10.30 -
10.31 -G_BEGIN_DECLS
10.32 -#define GST_TYPE_DATA_QUEUE \
10.33 - (gst_data_queue_get_type())
10.34 -#define GST_DATA_QUEUE(obj) \
10.35 - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DATA_QUEUE,GstDataQueue))
10.36 -#define GST_DATA_QUEUE_CLASS(klass) \
10.37 - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DATA_QUEUE,GstDataQueueClass))
10.38 -#define GST_IS_DATA_QUEUE(obj) \
10.39 - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DATA_QUEUE))
10.40 -#define GST_IS_DATA_QUEUE_CLASS(klass) \
10.41 - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DATA_QUEUE))
10.42 -typedef struct _GstDataQueue GstDataQueue;
10.43 -typedef struct _GstDataQueueClass GstDataQueueClass;
10.44 -typedef struct _GstDataQueueSize GstDataQueueSize;
10.45 -typedef struct _GstDataQueueItem GstDataQueueItem;
10.46 -
10.47 -/**
10.48 - * GstDataQueueItem:
10.49 - * @object: the #GstMiniObject to queue.
10.50 - * @size: the size in bytes of the miniobject.
10.51 - * @duration: the duration in #GstClockTime of the miniobject. Can not be
10.52 - * #GST_CLOCK_TIME_NONE.
10.53 - * @visible: #TRUE if @object should be considered as a visible object.
10.54 - * @destroy: The #GDestroyNotify function to use to free the #GstDataQueueItem.
10.55 - * This function should also drop the reference to @object the owner of the
10.56 - * #GstDataQueueItem is assumed to hold.
10.57 - *
10.58 - * Structure used by #GstDataQueue. You can supply a different structure, as
10.59 - * long as the top of the structure is identical to this structure.
10.60 - */
10.61 -
10.62 -struct _GstDataQueueItem
10.63 -{
10.64 - GstMiniObject *object;
10.65 - guint size;
10.66 - guint64 duration;
10.67 - gboolean visible;
10.68 -
10.69 - /* user supplied destroy function */
10.70 - GDestroyNotify destroy;
10.71 -};
10.72 -
10.73 -/**
10.74 - * GstDataQueueSize:
10.75 - * @visible: number of buffers
10.76 - * @bytes: number of bytes
10.77 - * @time: amount of time
10.78 - *
10.79 - * Structure describing the size of a queue.
10.80 - */
10.81 -struct _GstDataQueueSize
10.82 -{
10.83 - guint visible;
10.84 - guint bytes;
10.85 - guint64 time;
10.86 -};
10.87 -
10.88 -/**
10.89 - * GstDataQueueCheckFullFunction:
10.90 - * @queue: a #GstDataQueue.
10.91 - * @visible: The number of visible items currently in the queue.
10.92 - * @bytes: The amount of bytes currently in the queue.
10.93 - * @time: The accumulated duration of the items currently in the queue.
10.94 - * @checkdata: The #gpointer registered when the #GstDataQueue was created.
10.95 - *
10.96 - * The prototype of the function used to inform the queue that it should be
10.97 - * considered as full.
10.98 - *
10.99 - * Returns: #TRUE if the queue should be considered full.
10.100 - */
10.101 -typedef gboolean (*GstDataQueueCheckFullFunction) (GstDataQueue * queue,
10.102 - guint visible, guint bytes, guint64 time, gpointer checkdata);
10.103 -
10.104 -/**
10.105 - * GstDataQueue:
10.106 - *
10.107 - * Opaque #GstDataQueue structure.
10.108 - */
10.109 -struct _GstDataQueue
10.110 -{
10.111 - GObject object;
10.112 -
10.113 - /*< private > */
10.114 - /* the queue of data we're keeping our grubby hands on */
10.115 - GQueue *queue;
10.116 -
10.117 - GstDataQueueSize cur_level; /* size of the queue */
10.118 - GstDataQueueCheckFullFunction checkfull; /* Callback to check if the queue is full */
10.119 - gpointer *checkdata;
10.120 -
10.121 - GMutex *qlock; /* lock for queue (vs object lock) */
10.122 - GCond *item_add; /* signals buffers now available for reading */
10.123 - GCond *item_del; /* signals space now available for writing */
10.124 - gboolean flushing; /* indicates whether conditions where signalled because
10.125 - * of external flushing */
10.126 -
10.127 - gpointer _gst_reserved[GST_PADDING];
10.128 -};
10.129 -
10.130 -struct _GstDataQueueClass
10.131 -{
10.132 - GObjectClass parent_class;
10.133 -
10.134 - /* signals */
10.135 - void (*empty) (GstDataQueue * queue);
10.136 - void (*full) (GstDataQueue * queue);
10.137 -
10.138 - gpointer _gst_reserved[GST_PADDING];
10.139 -};
10.140 -
10.141 -GType gst_data_queue_get_type (void);
10.142 -
10.143 -GstDataQueue * gst_data_queue_new (GstDataQueueCheckFullFunction checkfull,
10.144 - gpointer checkdata);
10.145 -
10.146 -gboolean gst_data_queue_push (GstDataQueue * queue, GstDataQueueItem * item);
10.147 -gboolean gst_data_queue_pop (GstDataQueue * queue, GstDataQueueItem ** item);
10.148 -
10.149 -void gst_data_queue_flush (GstDataQueue * queue);
10.150 -void gst_data_queue_set_flushing (GstDataQueue * queue, gboolean flushing);
10.151 -
10.152 -gboolean gst_data_queue_drop_head (GstDataQueue * queue, GType type);
10.153 -
10.154 -gboolean gst_data_queue_is_full (GstDataQueue * queue);
10.155 -gboolean gst_data_queue_is_empty (GstDataQueue * queue);
10.156 -
10.157 -void gst_data_queue_get_level (GstDataQueue * queue, GstDataQueueSize *level);
10.158 -void gst_data_queue_limits_changed (GstDataQueue * queue);
10.159 -
10.160 -G_END_DECLS
10.161 -
10.162 -#endif /* __GST_DATA_QUEUE_H__ */
11.1 --- a/gst-gmyth/multiqueue/gstmultiqueue.c Tue Sep 18 21:01:18 2007 +0100
11.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
11.3 @@ -1,1397 +0,0 @@
11.4 -/* GStreamer
11.5 - * Copyright (C) 2006 Edward Hervey <edward@fluendo.com>
11.6 - * Copyright (C) 2007 Jan Schmidt <jan@fluendo.com>
11.7 - * Copyright (C) 2007 Wim Taymans <wim@fluendo.com>
11.8 - *
11.9 - * gstmultiqueue.c:
11.10 - *
11.11 - * This library is free software; you can redistribute it and/or
11.12 - * modify it under the terms of the GNU Library General Public
11.13 - * License as published by the Free Software Foundation; either
11.14 - * version 2 of the License, or (at your option) any later version.
11.15 - *
11.16 - * This library is distributed in the hope that it will be useful,
11.17 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
11.18 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11.19 - * Library General Public License for more details.
11.20 - *
11.21 - * You should have received a copy of the GNU Library General Public
11.22 - * License along with this library; if not, write to the
11.23 - * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
11.24 - * Boston, MA 02111-1307, USA.
11.25 - */
11.26 -
11.27 -#ifdef HAVE_CONFIG_H
11.28 -# include "config.h"
11.29 -#endif
11.30 -
11.31 -#include <gst/gst.h>
11.32 -#include "gstmultiqueue.h"
11.33 -
11.34 -/**
11.35 - * GstSingleQueue:
11.36 - * @sinkpad: associated sink #GstPad
11.37 - * @srcpad: associated source #GstPad
11.38 - *
11.39 - * Structure containing all information and properties about
11.40 - * a single queue.
11.41 - */
11.42 -typedef struct _GstSingleQueue GstSingleQueue;
11.43 -
11.44 -struct _GstSingleQueue
11.45 -{
11.46 - /* unique identifier of the queue */
11.47 - guint id;
11.48 -
11.49 - GstMultiQueue *mqueue;
11.50 -
11.51 - GstPad *sinkpad;
11.52 - GstPad *srcpad;
11.53 -
11.54 - /* flowreturn of previous srcpad push */
11.55 - GstFlowReturn srcresult;
11.56 - GstSegment sink_segment;
11.57 - GstSegment src_segment;
11.58 -
11.59 - /* queue of data */
11.60 - GstDataQueue *queue;
11.61 - GstDataQueueSize max_size, extra_size;
11.62 - GstClockTime cur_time;
11.63 - gboolean is_eos;
11.64 - gboolean inextra; /* TRUE if the queue is currently in extradata mode */
11.65 -
11.66 - /* Protected by global lock */
11.67 - guint32 nextid; /* ID of the next object waiting to be pushed */
11.68 - guint32 oldid; /* ID of the last object pushed (last in a series) */
11.69 - GCond *turn; /* SingleQueue turn waiting conditional */
11.70 -};
11.71 -
11.72 -
11.73 -/* Extension of GstDataQueueItem structure for our usage */
11.74 -typedef struct _GstMultiQueueItem GstMultiQueueItem;
11.75 -
11.76 -struct _GstMultiQueueItem
11.77 -{
11.78 - GstMiniObject *object;
11.79 - guint size;
11.80 - guint64 duration;
11.81 - gboolean visible;
11.82 -
11.83 - GDestroyNotify destroy;
11.84 - guint32 posid;
11.85 -};
11.86 -
11.87 -static GstSingleQueue *gst_single_queue_new (GstMultiQueue * mqueue);
11.88 -static void gst_single_queue_free (GstSingleQueue * squeue);
11.89 -
11.90 -static void wake_up_next_non_linked (GstMultiQueue * mq);
11.91 -static void compute_high_id (GstMultiQueue * mq);
11.92 -
11.93 -static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink%d",
11.94 - GST_PAD_SINK,
11.95 - GST_PAD_REQUEST,
11.96 - GST_STATIC_CAPS_ANY);
11.97 -
11.98 -static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src%d",
11.99 - GST_PAD_SRC,
11.100 - GST_PAD_SOMETIMES,
11.101 - GST_STATIC_CAPS_ANY);
11.102 -
11.103 -GST_DEBUG_CATEGORY_STATIC (multi_queue_debug);
11.104 -#define GST_CAT_DEFAULT (multi_queue_debug)
11.105 -
11.106 -/* default limits, we try to keep up to 2 seconds of data and if there is not
11.107 - * time, up to 10 MB. The number of buffers is dynamically scaled to make sure
11.108 - * there is data in the queues. Normally, the byte and time limits are not hit
11.109 - * in theses conditions. */
11.110 -#define DEFAULT_MAX_SIZE_BYTES 10 * 1024 * 1024 /* 10 MB */
11.111 -#define DEFAULT_MAX_SIZE_BUFFERS 5
11.112 -#define DEFAULT_MAX_SIZE_TIME 2 * GST_SECOND
11.113 -
11.114 -/* second limits. When we hit one of the above limits we are probably dealing
11.115 - * with a badly muxed file and we scale the limits to these emergency values.
11.116 - * This is currently not yet implemented. */
11.117 -#define DEFAULT_EXTRA_SIZE_BYTES 10 * 1024 * 1024 /* 10 MB */
11.118 -#define DEFAULT_EXTRA_SIZE_BUFFERS 5
11.119 -#define DEFAULT_EXTRA_SIZE_TIME 3 * GST_SECOND
11.120 -
11.121 -/* Signals and args */
11.122 -enum
11.123 -{
11.124 - SIGNAL_UNDERRUN,
11.125 - SIGNAL_OVERRUN,
11.126 - LAST_SIGNAL
11.127 -};
11.128 -
11.129 -enum
11.130 -{
11.131 - ARG_0,
11.132 - ARG_EXTRA_SIZE_BYTES,
11.133 - ARG_EXTRA_SIZE_BUFFERS,
11.134 - ARG_EXTRA_SIZE_TIME,
11.135 - ARG_MAX_SIZE_BYTES,
11.136 - ARG_MAX_SIZE_BUFFERS,
11.137 - ARG_MAX_SIZE_TIME,
11.138 -};
11.139 -
11.140 -
11.141 -static const GstElementDetails gst_multiqueue_details =
11.142 -GST_ELEMENT_DETAILS ("MultiQueue",
11.143 - "Generic",
11.144 - "Multiple data queue",
11.145 - "Edward Hervey <edward@fluendo.com>");
11.146 -
11.147 -
11.148 -#define GST_MULTI_QUEUE_MUTEX_LOCK(q) G_STMT_START { \
11.149 - g_mutex_lock (q->qlock); \
11.150 -} G_STMT_END
11.151 -
11.152 -#define GST_MULTI_QUEUE_MUTEX_UNLOCK(q) G_STMT_START { \
11.153 - g_mutex_unlock (q->qlock); \
11.154 -} G_STMT_END
11.155 -
11.156 -static void gst_multi_queue_finalize (GObject * object);
11.157 -static void gst_multi_queue_set_property (GObject * object,
11.158 - guint prop_id, const GValue * value, GParamSpec * pspec);
11.159 -static void gst_multi_queue_get_property (GObject * object,
11.160 - guint prop_id, GValue * value, GParamSpec * pspec);
11.161 -
11.162 -static GstPad *gst_multi_queue_request_new_pad (GstElement * element,
11.163 - GstPadTemplate * temp, const gchar * name);
11.164 -static void gst_multi_queue_release_pad (GstElement * element, GstPad * pad);
11.165 -
11.166 -static void gst_multi_queue_loop (GstPad * pad);
11.167 -
11.168 -#define _do_init(bla) \
11.169 - GST_DEBUG_CATEGORY_INIT (multi_queue_debug, "multiqueue", 0, "multiqueue element");
11.170 -
11.171 -GST_BOILERPLATE_FULL (GstMultiQueue, gst_multi_queue, GstElement,
11.172 - GST_TYPE_ELEMENT, _do_init);
11.173 -
11.174 -static guint gst_multi_queue_signals[LAST_SIGNAL] = { 0 };
11.175 -
11.176 -
11.177 -
11.178 -static void
11.179 -gst_multi_queue_base_init (gpointer g_class)
11.180 -{
11.181 - GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
11.182 -
11.183 - gst_element_class_set_details (gstelement_class, &gst_multiqueue_details);
11.184 - gst_element_class_add_pad_template (gstelement_class,
11.185 - gst_static_pad_template_get (&sinktemplate));
11.186 - gst_element_class_add_pad_template (gstelement_class,
11.187 - gst_static_pad_template_get (&srctemplate));
11.188 -}
11.189 -
11.190 -static void
11.191 -gst_multi_queue_class_init (GstMultiQueueClass * klass)
11.192 -{
11.193 - GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
11.194 - GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
11.195 -
11.196 - gobject_class->set_property =
11.197 - GST_DEBUG_FUNCPTR (gst_multi_queue_set_property);
11.198 - gobject_class->get_property =
11.199 - GST_DEBUG_FUNCPTR (gst_multi_queue_get_property);
11.200 -
11.201 - /* SIGNALS */
11.202 - gst_multi_queue_signals[SIGNAL_UNDERRUN] =
11.203 - g_signal_new ("underrun", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
11.204 - G_STRUCT_OFFSET (GstMultiQueueClass, underrun), NULL, NULL,
11.205 - g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
11.206 -
11.207 - gst_multi_queue_signals[SIGNAL_OVERRUN] =
11.208 - g_signal_new ("overrun", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
11.209 - G_STRUCT_OFFSET (GstMultiQueueClass, overrun), NULL, NULL,
11.210 - g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
11.211 -
11.212 - /* PROPERTIES */
11.213 -
11.214 - g_object_class_install_property (gobject_class, ARG_MAX_SIZE_BYTES,
11.215 - g_param_spec_uint ("max-size-bytes", "Max. size (kB)",
11.216 - "Max. amount of data in the queue (bytes, 0=disable)",
11.217 - 0, G_MAXUINT, DEFAULT_MAX_SIZE_BYTES, G_PARAM_READWRITE));
11.218 - g_object_class_install_property (gobject_class, ARG_MAX_SIZE_BUFFERS,
11.219 - g_param_spec_uint ("max-size-buffers", "Max. size (buffers)",
11.220 - "Max. number of buffers in the queue (0=disable)",
11.221 - 0, G_MAXUINT, DEFAULT_MAX_SIZE_BUFFERS, G_PARAM_READWRITE));
11.222 - g_object_class_install_property (gobject_class, ARG_MAX_SIZE_TIME,
11.223 - g_param_spec_uint64 ("max-size-time", "Max. size (ns)",
11.224 - "Max. amount of data in the queue (in ns, 0=disable)",
11.225 - 0, G_MAXUINT64, DEFAULT_MAX_SIZE_TIME, G_PARAM_READWRITE));
11.226 -
11.227 - g_object_class_install_property (gobject_class, ARG_EXTRA_SIZE_BYTES,
11.228 - g_param_spec_uint ("extra-size-bytes", "Extra Size (kB)",
11.229 - "Amount of data the queues can grow if one of them is empty (bytes, 0=disable)",
11.230 - 0, G_MAXUINT, DEFAULT_EXTRA_SIZE_BYTES, G_PARAM_READWRITE));
11.231 - g_object_class_install_property (gobject_class, ARG_EXTRA_SIZE_BUFFERS,
11.232 - g_param_spec_uint ("extra-size-buffers", "Extra Size (buffers)",
11.233 - "Amount of buffers the queues can grow if one of them is empty (0=disable)",
11.234 - 0, G_MAXUINT, DEFAULT_EXTRA_SIZE_BUFFERS, G_PARAM_READWRITE));
11.235 - g_object_class_install_property (gobject_class, ARG_EXTRA_SIZE_TIME,
11.236 - g_param_spec_uint64 ("extra-size-time", "Extra Size (ns)",
11.237 - "Amount of time the queues can grow if one of them is empty (in ns, 0=disable)",
11.238 - 0, G_MAXUINT64, DEFAULT_EXTRA_SIZE_TIME, G_PARAM_READWRITE));
11.239 -
11.240 - gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_multi_queue_finalize);
11.241 -
11.242 - gstelement_class->request_new_pad =
11.243 - GST_DEBUG_FUNCPTR (gst_multi_queue_request_new_pad);
11.244 - gstelement_class->release_pad =
11.245 - GST_DEBUG_FUNCPTR (gst_multi_queue_release_pad);
11.246 -}
11.247 -
11.248 -static void
11.249 -gst_multi_queue_init (GstMultiQueue * mqueue, GstMultiQueueClass * klass)
11.250 -{
11.251 - mqueue->nbqueues = 0;
11.252 - mqueue->queues = NULL;
11.253 -
11.254 - mqueue->max_size.bytes = DEFAULT_MAX_SIZE_BYTES;
11.255 - mqueue->max_size.visible = DEFAULT_MAX_SIZE_BUFFERS;
11.256 - mqueue->max_size.time = DEFAULT_MAX_SIZE_TIME;
11.257 -
11.258 - mqueue->extra_size.bytes = DEFAULT_EXTRA_SIZE_BYTES;
11.259 - mqueue->extra_size.visible = DEFAULT_EXTRA_SIZE_BUFFERS;
11.260 - mqueue->extra_size.time = DEFAULT_EXTRA_SIZE_TIME;
11.261 -
11.262 - mqueue->counter = 1;
11.263 - mqueue->highid = -1;
11.264 - mqueue->nextnotlinked = -1;
11.265 -
11.266 - mqueue->qlock = g_mutex_new ();
11.267 -}
11.268 -
11.269 -static void
11.270 -gst_multi_queue_finalize (GObject * object)
11.271 -{
11.272 - GstMultiQueue *mqueue = GST_MULTI_QUEUE (object);
11.273 -
11.274 - g_list_foreach (mqueue->queues, (GFunc) gst_single_queue_free, NULL);
11.275 - g_list_free (mqueue->queues);
11.276 - mqueue->queues = NULL;
11.277 -
11.278 - /* free/unref instance data */
11.279 - g_mutex_free (mqueue->qlock);
11.280 -
11.281 - G_OBJECT_CLASS (parent_class)->finalize (object);
11.282 -}
11.283 -
11.284 -
11.285 -
11.286 -#define SET_CHILD_PROPERTY(mq,format) G_STMT_START { \
11.287 - GList * tmp = mq->queues; \
11.288 - while (tmp) { \
11.289 - GstSingleQueue *q = (GstSingleQueue*)tmp->data; \
11.290 - q->max_size.format = mq->max_size.format; \
11.291 - tmp = g_list_next(tmp); \
11.292 - }; \
11.293 -} G_STMT_END
11.294 -
11.295 -static void
11.296 -gst_multi_queue_set_property (GObject * object, guint prop_id,
11.297 - const GValue * value, GParamSpec * pspec)
11.298 -{
11.299 - GstMultiQueue *mq = GST_MULTI_QUEUE (object);
11.300 -
11.301 - switch (prop_id) {
11.302 - case ARG_MAX_SIZE_BYTES:
11.303 - mq->max_size.bytes = g_value_get_uint (value);
11.304 - SET_CHILD_PROPERTY (mq, bytes);
11.305 - break;
11.306 - case ARG_MAX_SIZE_BUFFERS:
11.307 - mq->max_size.visible = g_value_get_uint (value);
11.308 - SET_CHILD_PROPERTY (mq, visible);
11.309 - break;
11.310 - case ARG_MAX_SIZE_TIME:
11.311 - mq->max_size.time = g_value_get_uint64 (value);
11.312 - SET_CHILD_PROPERTY (mq, time);
11.313 - break;
11.314 - case ARG_EXTRA_SIZE_BYTES:
11.315 - mq->extra_size.bytes = g_value_get_uint (value);
11.316 - break;
11.317 - case ARG_EXTRA_SIZE_BUFFERS:
11.318 - mq->extra_size.visible = g_value_get_uint (value);
11.319 - break;
11.320 - case ARG_EXTRA_SIZE_TIME:
11.321 - mq->extra_size.time = g_value_get_uint64 (value);
11.322 - break;
11.323 - default:
11.324 - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
11.325 - break;
11.326 - }
11.327 -}
11.328 -
11.329 -static void
11.330 -gst_multi_queue_get_property (GObject * object, guint prop_id,
11.331 - GValue * value, GParamSpec * pspec)
11.332 -{
11.333 - GstMultiQueue *mq = GST_MULTI_QUEUE (object);
11.334 -
11.335 - GST_MULTI_QUEUE_MUTEX_LOCK (mq);
11.336 -
11.337 - switch (prop_id) {
11.338 - case ARG_EXTRA_SIZE_BYTES:
11.339 - g_value_set_uint (value, mq->extra_size.bytes);
11.340 - break;
11.341 - case ARG_EXTRA_SIZE_BUFFERS:
11.342 - g_value_set_uint (value, mq->extra_size.visible);
11.343 - break;
11.344 - case ARG_EXTRA_SIZE_TIME:
11.345 - g_value_set_uint64 (value, mq->extra_size.time);
11.346 - break;
11.347 - case ARG_MAX_SIZE_BYTES:
11.348 - g_value_set_uint (value, mq->max_size.bytes);
11.349 - break;
11.350 - case ARG_MAX_SIZE_BUFFERS:
11.351 - g_value_set_uint (value, mq->max_size.visible);
11.352 - break;
11.353 - case ARG_MAX_SIZE_TIME:
11.354 - g_value_set_uint64 (value, mq->max_size.time);
11.355 - break;
11.356 - default:
11.357 - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
11.358 - break;
11.359 - }
11.360 -
11.361 - GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
11.362 -}
11.363 -
11.364 -GList *
11.365 -gst_multi_queue_get_internal_links (GstPad * pad)
11.366 -{
11.367 - GList *res = NULL;
11.368 - GstMultiQueue *mqueue;
11.369 - GstSingleQueue *sq = NULL;
11.370 - GList *tmp;
11.371 -
11.372 - g_return_val_if_fail (GST_IS_PAD (pad), NULL);
11.373 -
11.374 - mqueue = GST_MULTI_QUEUE (GST_PAD_PARENT (pad));
11.375 - if (!mqueue)
11.376 - goto no_parent;
11.377 -
11.378 - GST_MULTI_QUEUE_MUTEX_LOCK (mqueue);
11.379 - /* Find which single queue it belongs to */
11.380 - for (tmp = mqueue->queues; tmp && !res; tmp = g_list_next (tmp)) {
11.381 - sq = (GstSingleQueue *) tmp->data;
11.382 -
11.383 - if (sq->sinkpad == pad)
11.384 - res = g_list_prepend (res, sq->srcpad);
11.385 - if (sq->srcpad == pad)
11.386 - res = g_list_prepend (res, sq->sinkpad);
11.387 - }
11.388 -
11.389 - if (!res)
11.390 - GST_WARNING_OBJECT (mqueue, "That pad doesn't belong to this element ???");
11.391 - GST_MULTI_QUEUE_MUTEX_UNLOCK (mqueue);
11.392 -
11.393 - return res;
11.394 -
11.395 -no_parent:
11.396 - {
11.397 - GST_DEBUG_OBJECT (pad, "no parent");
11.398 - return NULL;
11.399 - }
11.400 -}
11.401 -
11.402 -
11.403 -/*
11.404 - * GstElement methods
11.405 - */
11.406 -
11.407 -static GstPad *
11.408 -gst_multi_queue_request_new_pad (GstElement * element, GstPadTemplate * temp,
11.409 - const gchar * name)
11.410 -{
11.411 - GstMultiQueue *mqueue = GST_MULTI_QUEUE (element);
11.412 - GstSingleQueue *squeue;
11.413 -
11.414 - GST_LOG_OBJECT (element, "name : %s", name);
11.415 -
11.416 - /* Create a new single queue, add the sink and source pad and return the sink pad */
11.417 - squeue = gst_single_queue_new (mqueue);
11.418 -
11.419 - GST_MULTI_QUEUE_MUTEX_LOCK (mqueue);
11.420 - mqueue->queues = g_list_append (mqueue->queues, squeue);
11.421 - GST_MULTI_QUEUE_MUTEX_UNLOCK (mqueue);
11.422 -
11.423 - /*
11.424 - GST_DEBUG_OBJECT (mqueue, "Returning pad %s:%s",
11.425 - GST_DEBUG_PAD_NAME (squeue->sinkpad));
11.426 - */
11.427 - return squeue->sinkpad;
11.428 -}
11.429 -
11.430 -static void
11.431 -gst_multi_queue_release_pad (GstElement * element, GstPad * pad)
11.432 -{
11.433 - GstMultiQueue *mqueue = GST_MULTI_QUEUE (element);
11.434 - GstSingleQueue *sq = NULL;
11.435 - GList *tmp;
11.436 -
11.437 -// GST_LOG_OBJECT (element, "pad %s:%s", GST_DEBUG_PAD_NAME (pad));
11.438 -
11.439 - GST_MULTI_QUEUE_MUTEX_LOCK (mqueue);
11.440 - /* Find which single queue it belongs to, knowing that it should be a sinkpad */
11.441 - for (tmp = mqueue->queues; tmp; tmp = g_list_next (tmp)) {
11.442 - sq = (GstSingleQueue *) tmp->data;
11.443 -
11.444 - if (sq->sinkpad == pad)
11.445 - break;
11.446 - }
11.447 -
11.448 - if (!tmp) {
11.449 - GST_WARNING_OBJECT (mqueue, "That pad doesn't belong to this element ???");
11.450 - GST_MULTI_QUEUE_MUTEX_UNLOCK (mqueue);
11.451 - return;
11.452 - }
11.453 -
11.454 - /* FIXME: The removal of the singlequeue should probably not happen until it
11.455 - * finishes draining */
11.456 -
11.457 - /* remove it from the list */
11.458 - mqueue->queues = g_list_delete_link (mqueue->queues, tmp);
11.459 -
11.460 - /* FIXME : recompute next-non-linked */
11.461 - GST_MULTI_QUEUE_MUTEX_UNLOCK (mqueue);
11.462 -
11.463 - /* delete SingleQueue */
11.464 - gst_data_queue_set_flushing (sq->queue, TRUE);
11.465 -
11.466 - gst_pad_set_active (sq->srcpad, FALSE);
11.467 - gst_pad_set_active (sq->sinkpad, FALSE);
11.468 - gst_element_remove_pad (element, sq->srcpad);
11.469 - gst_element_remove_pad (element, sq->sinkpad);
11.470 - gst_single_queue_free (sq);
11.471 -}
11.472 -
11.473 -static gboolean
11.474 -gst_single_queue_flush (GstMultiQueue * mq, GstSingleQueue * sq, gboolean flush)
11.475 -{
11.476 - gboolean result;
11.477 -
11.478 - GST_DEBUG_OBJECT (mq, "flush %s queue %d", (flush ? "start" : "stop"),
11.479 - sq->id);
11.480 -
11.481 - if (flush) {
11.482 - sq->srcresult = GST_FLOW_WRONG_STATE;
11.483 - gst_data_queue_set_flushing (sq->queue, TRUE);
11.484 -
11.485 - /* wake up non-linked task */
11.486 - GST_LOG_OBJECT (mq, "SingleQueue %d : waking up eventually waiting task",
11.487 - sq->id);
11.488 - GST_MULTI_QUEUE_MUTEX_LOCK (mq);
11.489 - g_cond_signal (sq->turn);
11.490 - GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
11.491 -
11.492 - GST_LOG_OBJECT (mq, "SingleQueue %d : pausing task", sq->id);
11.493 - result = gst_pad_pause_task (sq->srcpad);
11.494 - } else {
11.495 - gst_data_queue_flush (sq->queue);
11.496 - gst_segment_init (&sq->sink_segment, GST_FORMAT_TIME);
11.497 - gst_segment_init (&sq->src_segment, GST_FORMAT_TIME);
11.498 - /* All pads start off not-linked for a smooth kick-off */
11.499 - sq->srcresult = GST_FLOW_NOT_LINKED;
11.500 - sq->cur_time = 0;
11.501 - sq->max_size.visible = mq->max_size.visible;
11.502 - sq->is_eos = FALSE;
11.503 - sq->inextra = FALSE;
11.504 - sq->nextid = 0;
11.505 - sq->oldid = 0;
11.506 - gst_data_queue_set_flushing (sq->queue, FALSE);
11.507 -
11.508 - GST_LOG_OBJECT (mq, "SingleQueue %d : starting task", sq->id);
11.509 - result =
11.510 - gst_pad_start_task (sq->srcpad, (GstTaskFunction) gst_multi_queue_loop,
11.511 - sq->srcpad);
11.512 - }
11.513 - return result;
11.514 -}
11.515 -
11.516 -/* calculate the diff between running time on the sink and src of the queue.
11.517 - * This is the total amount of time in the queue.
11.518 - * WITH LOCK TAKEN */
11.519 -static void
11.520 -update_time_level (GstMultiQueue * mq, GstSingleQueue * sq)
11.521 -{
11.522 - gint64 sink_time, src_time;
11.523 -
11.524 - sink_time =
11.525 - gst_segment_to_running_time (&sq->sink_segment, GST_FORMAT_TIME,
11.526 - sq->sink_segment.last_stop);
11.527 -
11.528 - src_time = gst_segment_to_running_time (&sq->src_segment, GST_FORMAT_TIME,
11.529 - sq->src_segment.last_stop);
11.530 -
11.531 - GST_DEBUG_OBJECT (mq,
11.532 - "queue %d, sink %" GST_TIME_FORMAT ", src %" GST_TIME_FORMAT, sq->id,
11.533 - GST_TIME_ARGS (sink_time), GST_TIME_ARGS (src_time));
11.534 -
11.535 - /* This allows for streams with out of order timestamping - sometimes the
11.536 - * emerging timestamp is later than the arriving one(s) */
11.537 - if (sink_time >= src_time)
11.538 - sq->cur_time = sink_time - src_time;
11.539 - else
11.540 - sq->cur_time = 0;
11.541 -}
11.542 -
11.543 -/* take a NEWSEGMENT event and apply the values to segment, updating the time
11.544 - * level of queue. */
11.545 -static void
11.546 -apply_segment (GstMultiQueue * mq, GstSingleQueue * sq, GstEvent * event,
11.547 - GstSegment * segment)
11.548 -{
11.549 - gboolean update;
11.550 - GstFormat format;
11.551 - gdouble rate, arate;
11.552 - gint64 start, stop, time;
11.553 -
11.554 - gst_event_parse_new_segment_full (event, &update, &rate, &arate,
11.555 - &format, &start, &stop, &time);
11.556 -
11.557 - /* now configure the values, we use these to track timestamps on the
11.558 - * sinkpad. */
11.559 - if (format != GST_FORMAT_TIME) {
11.560 - /* non-time format, pretent the current time segment is closed with a
11.561 - * 0 start and unknown stop time. */
11.562 - update = FALSE;
11.563 - format = GST_FORMAT_TIME;
11.564 - start = 0;
11.565 - stop = -1;
11.566 - time = 0;
11.567 - }
11.568 -
11.569 - GST_MULTI_QUEUE_MUTEX_LOCK (mq);
11.570 -
11.571 - gst_segment_set_newsegment_full (segment, update,
11.572 - rate, arate, format, start, stop, time);
11.573 -
11.574 - GST_DEBUG_OBJECT (mq,
11.575 - "queue %d, configured NEWSEGMENT %" GST_SEGMENT_FORMAT, sq->id, segment);
11.576 -
11.577 - /* segment can update the time level of the queue */
11.578 - update_time_level (mq, sq);
11.579 -
11.580 - GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
11.581 -}
11.582 -
11.583 -/* take a buffer and update segment, updating the time level of the queue. */
11.584 -static void
11.585 -apply_buffer (GstMultiQueue * mq, GstSingleQueue * sq, GstClockTime timestamp,
11.586 - GstClockTime duration, GstSegment * segment)
11.587 -{
11.588 - GST_MULTI_QUEUE_MUTEX_LOCK (mq);
11.589 -
11.590 - /* if no timestamp is set, assume it's continuous with the previous
11.591 - * time */
11.592 - if (timestamp == GST_CLOCK_TIME_NONE)
11.593 - timestamp = segment->last_stop;
11.594 -
11.595 - /* add duration */
11.596 - if (duration != GST_CLOCK_TIME_NONE)
11.597 - timestamp += duration;
11.598 -
11.599 - GST_DEBUG_OBJECT (mq, "queue %d, last_stop updated to %" GST_TIME_FORMAT,
11.600 - sq->id, GST_TIME_ARGS (timestamp));
11.601 -
11.602 - gst_segment_set_last_stop (segment, GST_FORMAT_TIME, timestamp);
11.603 -
11.604 - /* calc diff with other end */
11.605 - update_time_level (mq, sq);
11.606 - GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
11.607 -}
11.608 -
11.609 -static GstFlowReturn
11.610 -gst_single_queue_push_one (GstMultiQueue * mq, GstSingleQueue * sq,
11.611 - GstMiniObject * object)
11.612 -{
11.613 - GstFlowReturn result = GST_FLOW_OK;
11.614 -
11.615 - if (GST_IS_BUFFER (object)) {
11.616 - GstBuffer *buffer;
11.617 - GstClockTime timestamp, duration;
11.618 -
11.619 - buffer = GST_BUFFER_CAST (object);
11.620 - timestamp = GST_BUFFER_TIMESTAMP (buffer);
11.621 - duration = GST_BUFFER_DURATION (buffer);
11.622 -
11.623 - apply_buffer (mq, sq, timestamp, duration, &sq->src_segment);
11.624 -
11.625 - /* Applying the buffer may have made the queue non-full again, unblock it if needed */
11.626 - gst_data_queue_limits_changed (sq->queue);
11.627 -
11.628 - GST_DEBUG_OBJECT (mq,
11.629 - "SingleQueue %d : Pushing buffer %p with ts %" GST_TIME_FORMAT,
11.630 - sq->id, buffer, GST_TIME_ARGS (timestamp));
11.631 -
11.632 - result = gst_pad_push (sq->srcpad, buffer);
11.633 - } else if (GST_IS_EVENT (object)) {
11.634 - GstEvent *event;
11.635 -
11.636 - event = GST_EVENT_CAST (object);
11.637 -
11.638 - switch (GST_EVENT_TYPE (event)) {
11.639 - case GST_EVENT_EOS:
11.640 - result = GST_FLOW_UNEXPECTED;
11.641 - break;
11.642 - case GST_EVENT_NEWSEGMENT:
11.643 - apply_segment (mq, sq, event, &sq->src_segment);
11.644 - /* Applying the segment may have made the queue non-full again, unblock it if needed */
11.645 - gst_data_queue_limits_changed (sq->queue);
11.646 - break;
11.647 - default:
11.648 - break;
11.649 - }
11.650 -
11.651 - GST_DEBUG_OBJECT (mq,
11.652 - "SingleQueue %d : Pushing event %p of type %s",
11.653 - sq->id, event, GST_EVENT_TYPE_NAME (event));
11.654 -
11.655 - gst_pad_push_event (sq->srcpad, event);
11.656 - } else {
11.657 - g_warning ("Unexpected object in singlequeue %d (refcounting problem?)",
11.658 - sq->id);
11.659 - }
11.660 - return result;
11.661 -
11.662 - /* ERRORS */
11.663 -}
11.664 -
11.665 -static GstMiniObject *
11.666 -gst_multi_queue_item_steal_object (GstMultiQueueItem * item)
11.667 -{
11.668 - GstMiniObject *res;
11.669 -
11.670 - res = item->object;
11.671 - item->object = NULL;
11.672 -
11.673 - return res;
11.674 -}
11.675 -
11.676 -static void
11.677 -gst_multi_queue_item_destroy (GstMultiQueueItem * item)
11.678 -{
11.679 - if (item->object)
11.680 - gst_mini_object_unref (item->object);
11.681 - g_free (item);
11.682 -}
11.683 -
11.684 -/* takes ownership of passed mini object! */
11.685 -static GstMultiQueueItem *
11.686 -gst_multi_queue_item_new (GstMiniObject * object, guint32 curid)
11.687 -{
11.688 - GstMultiQueueItem *item;
11.689 -
11.690 - item = g_new (GstMultiQueueItem, 1);
11.691 - item->object = object;
11.692 - item->destroy = (GDestroyNotify) gst_multi_queue_item_destroy;
11.693 - item->posid = curid;
11.694 -
11.695 - if (GST_IS_BUFFER (object)) {
11.696 - item->size = GST_BUFFER_SIZE (object);
11.697 - item->duration = GST_BUFFER_DURATION (object);
11.698 - if (item->duration == GST_CLOCK_TIME_NONE)
11.699 - item->duration = 0;
11.700 - item->visible = TRUE;
11.701 - } else {
11.702 - item->size = 0;
11.703 - item->duration = 0;
11.704 - item->visible = FALSE;
11.705 - }
11.706 - return item;
11.707 -}
11.708 -
11.709 -/* Each main loop attempts to push buffers until the return value
11.710 - * is not-linked. not-linked pads are not allowed to push data beyond
11.711 - * any linked pads, so they don't 'rush ahead of the pack'.
11.712 - */
11.713 -static void
11.714 -gst_multi_queue_loop (GstPad * pad)
11.715 -{
11.716 - GstSingleQueue *sq;
11.717 - GstMultiQueueItem *item;
11.718 - GstDataQueueItem *sitem;
11.719 - GstMultiQueue *mq;
11.720 - GstMiniObject *object;
11.721 - guint32 newid;
11.722 - guint32 oldid = -1;
11.723 - GstFlowReturn result;
11.724 -
11.725 - sq = (GstSingleQueue *) gst_pad_get_element_private (pad);
11.726 - mq = sq->mqueue;
11.727 -
11.728 - do {
11.729 - GST_DEBUG_OBJECT (mq, "SingleQueue %d : trying to pop an object", sq->id);
11.730 -
11.731 - /* Get something from the queue, blocking until that happens, or we get
11.732 - * flushed */
11.733 - if (!(gst_data_queue_pop (sq->queue, &sitem)))
11.734 - goto out_flushing;
11.735 -
11.736 - item = (GstMultiQueueItem *) sitem;
11.737 - newid = item->posid;
11.738 -
11.739 - /* steal the object and destroy the item */
11.740 - object = gst_multi_queue_item_steal_object (item);
11.741 - gst_multi_queue_item_destroy (item);
11.742 -
11.743 - GST_LOG_OBJECT (mq, "SingleQueue %d : newid:%d , oldid:%d",
11.744 - sq->id, newid, oldid);
11.745 -
11.746 - /* If we're not-linked, we do some extra work because we might need to
11.747 - * wait before pushing. If we're linked but there's a gap in the IDs,
11.748 - * or it's the first loop, or we just passed the previous highid,
11.749 - * we might need to wake some sleeping pad up, so there's extra work
11.750 - * there too */
11.751 - if (sq->srcresult == GST_FLOW_NOT_LINKED ||
11.752 - (oldid == -1) || (newid != (oldid + 1)) || oldid > mq->highid) {
11.753 - GST_LOG_OBJECT (mq, "CHECKING sq->srcresult: %s",
11.754 - gst_flow_get_name (sq->srcresult));
11.755 -
11.756 - GST_MULTI_QUEUE_MUTEX_LOCK (mq);
11.757 -
11.758 - /* Update the nextid so other threads know when to wake us up */
11.759 - sq->nextid = newid;
11.760 -
11.761 - /* Update the oldid (the last ID we output) for highid tracking */
11.762 - if (oldid != -1)
11.763 - sq->oldid = oldid;
11.764 -
11.765 - if (sq->srcresult == GST_FLOW_NOT_LINKED) {
11.766 - /* Go to sleep until it's time to push this buffer */
11.767 -
11.768 - /* Recompute the highid */
11.769 - compute_high_id (mq);
11.770 - while (newid > mq->highid && sq->srcresult == GST_FLOW_NOT_LINKED) {
11.771 - GST_DEBUG_OBJECT (mq, "queue %d sleeping for not-linked wakeup with "
11.772 - "newid %u and highid %u", sq->id, newid, mq->highid);
11.773 -
11.774 -
11.775 - /* Wake up all non-linked pads before we sleep */
11.776 - wake_up_next_non_linked (mq);
11.777 -
11.778 - mq->numwaiting++;
11.779 - g_cond_wait (sq->turn, mq->qlock);
11.780 - mq->numwaiting--;
11.781 -
11.782 - GST_DEBUG_OBJECT (mq, "queue %d woken from sleeping for not-linked "
11.783 - "wakeup with newid %u and highid %u", sq->id, newid, mq->highid);
11.784 - }
11.785 -
11.786 - /* Re-compute the high_id in case someone else pushed */
11.787 - compute_high_id (mq);
11.788 - } else {
11.789 - compute_high_id (mq);
11.790 - /* Wake up all non-linked pads */
11.791 - wake_up_next_non_linked (mq);
11.792 - }
11.793 - /* We're done waiting, we can clear the nextid */
11.794 - sq->nextid = 0;
11.795 -
11.796 - GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
11.797 - }
11.798 -
11.799 - GST_LOG_OBJECT (mq, "BEFORE PUSHING sq->srcresult: %s",
11.800 - gst_flow_get_name (sq->srcresult));
11.801 -
11.802 - /* Try to push out the new object */
11.803 - result = gst_single_queue_push_one (mq, sq, object);
11.804 - sq->srcresult = result;
11.805 -
11.806 - if (result != GST_FLOW_OK && result != GST_FLOW_NOT_LINKED)
11.807 - goto out_flushing;
11.808 -
11.809 - GST_LOG_OBJECT (mq, "AFTER PUSHING sq->srcresult: %s",
11.810 - gst_flow_get_name (sq->srcresult));
11.811 -
11.812 - oldid = newid;
11.813 - }
11.814 - while (TRUE);
11.815 -
11.816 -out_flushing:
11.817 - {
11.818 - /* Need to make sure wake up any sleeping pads when we exit */
11.819 - GST_MULTI_QUEUE_MUTEX_LOCK (mq);
11.820 - compute_high_id (mq);
11.821 - wake_up_next_non_linked (mq);
11.822 - GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
11.823 -
11.824 - gst_data_queue_set_flushing (sq->queue, TRUE);
11.825 - gst_pad_pause_task (sq->srcpad);
11.826 - GST_CAT_LOG_OBJECT (multi_queue_debug, mq,
11.827 - "SingleQueue[%d] task paused, reason:%s",
11.828 - sq->id, gst_flow_get_name (sq->srcresult));
11.829 - return;
11.830 - }
11.831 -}
11.832 -
11.833 -/**
11.834 - * gst_multi_queue_chain:
11.835 - *
11.836 - * This is similar to GstQueue's chain function, except:
11.837 - * _ we don't have leak behavioures,
11.838 - * _ we push with a unique id (curid)
11.839 - */
11.840 -static GstFlowReturn
11.841 -gst_multi_queue_chain (GstPad * pad, GstBuffer * buffer)
11.842 -{
11.843 - GstSingleQueue *sq;
11.844 - GstMultiQueue *mq;
11.845 - GstMultiQueueItem *item;
11.846 - GstFlowReturn ret = GST_FLOW_OK;
11.847 - guint32 curid;
11.848 - GstClockTime timestamp, duration;
11.849 -
11.850 - sq = gst_pad_get_element_private (pad);
11.851 - mq = (GstMultiQueue *) gst_pad_get_parent (pad);
11.852 -
11.853 - /* Get a unique incrementing id */
11.854 - GST_MULTI_QUEUE_MUTEX_LOCK (mq);
11.855 - curid = mq->counter++;
11.856 - GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
11.857 -
11.858 - GST_LOG_OBJECT (mq, "SingleQueue %d : about to enqueue buffer %p with id %d",
11.859 - sq->id, buffer, curid);
11.860 -
11.861 - item = gst_multi_queue_item_new (GST_MINI_OBJECT_CAST (buffer), curid);
11.862 -
11.863 - timestamp = GST_BUFFER_TIMESTAMP (buffer);
11.864 - duration = GST_BUFFER_DURATION (buffer);
11.865 -
11.866 - if (!(gst_data_queue_push (sq->queue, (GstDataQueueItem *) item)))
11.867 - goto flushing;
11.868 -
11.869 - /* update time level, we must do this after pushing the data in the queue so
11.870 - * that we never end up filling the queue first. */
11.871 - apply_buffer (mq, sq, timestamp, duration, &sq->sink_segment);
11.872 -
11.873 -done:
11.874 - gst_object_unref (mq);
11.875 -
11.876 - return ret;
11.877 -
11.878 - /* ERRORS */
11.879 -flushing:
11.880 - {
11.881 - ret = sq->srcresult;
11.882 - GST_LOG_OBJECT (mq, "SingleQueue %d : exit because task paused, reason: %s",
11.883 - sq->id, gst_flow_get_name (ret));
11.884 - gst_multi_queue_item_destroy (item);
11.885 - goto done;
11.886 - }
11.887 -}
11.888 -
11.889 -static gboolean
11.890 -gst_multi_queue_sink_activate_push (GstPad * pad, gboolean active)
11.891 -{
11.892 - GstSingleQueue *sq;
11.893 -
11.894 - sq = (GstSingleQueue *) gst_pad_get_element_private (pad);
11.895 -
11.896 - if (active) {
11.897 - /* All pads start off not-linked for a smooth kick-off */
11.898 - sq->srcresult = GST_FLOW_NOT_LINKED;
11.899 - } else {
11.900 - sq->srcresult = GST_FLOW_WRONG_STATE;
11.901 - gst_data_queue_flush (sq->queue);
11.902 - }
11.903 - return TRUE;
11.904 -}
11.905 -
11.906 -static gboolean
11.907 -gst_multi_queue_sink_event (GstPad * pad, GstEvent * event)
11.908 -{
11.909 - GstSingleQueue *sq;
11.910 - GstMultiQueue *mq;
11.911 - guint32 curid;
11.912 - GstMultiQueueItem *item;
11.913 - gboolean res;
11.914 - GstEventType type;
11.915 - GstEvent *sref = NULL;
11.916 -
11.917 - sq = (GstSingleQueue *) gst_pad_get_element_private (pad);
11.918 - mq = (GstMultiQueue *) gst_pad_get_parent (pad);
11.919 -
11.920 - type = GST_EVENT_TYPE (event);
11.921 -
11.922 - switch (type) {
11.923 - case GST_EVENT_FLUSH_START:
11.924 - GST_DEBUG_OBJECT (mq, "SingleQueue %d : received flush start event",
11.925 - sq->id);
11.926 -
11.927 - res = gst_pad_push_event (sq->srcpad, event);
11.928 -
11.929 - gst_single_queue_flush (mq, sq, TRUE);
11.930 - goto done;
11.931 -
11.932 - case GST_EVENT_FLUSH_STOP:
11.933 - GST_DEBUG_OBJECT (mq, "SingleQueue %d : received flush stop event",
11.934 - sq->id);
11.935 -
11.936 - res = gst_pad_push_event (sq->srcpad, event);
11.937 -
11.938 - gst_single_queue_flush (mq, sq, FALSE);
11.939 - goto done;
11.940 - case GST_EVENT_NEWSEGMENT:
11.941 - /* take ref because the queue will take ownership and we need the event
11.942 - * afterwards to update the segment */
11.943 - sref = gst_event_ref (event);
11.944 - break;
11.945 -
11.946 - default:
11.947 - if (!(GST_EVENT_IS_SERIALIZED (event))) {
11.948 - res = gst_pad_push_event (sq->srcpad, event);
11.949 - goto done;
11.950 - }
11.951 - break;
11.952 - }
11.953 -
11.954 - /* Get an unique incrementing id */
11.955 - GST_MULTI_QUEUE_MUTEX_LOCK (mq);
11.956 - curid = mq->counter++;
11.957 - GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
11.958 -
11.959 - item = gst_multi_queue_item_new ((GstMiniObject *) event, curid);
11.960 -
11.961 - GST_DEBUG_OBJECT (mq,
11.962 - "SingleQueue %d : Enqueuing event %p of type %s with id %d",
11.963 - sq->id, event, GST_EVENT_TYPE_NAME (event), curid);
11.964 -
11.965 - if (!(res = gst_data_queue_push (sq->queue, (GstDataQueueItem *) item)))
11.966 - goto flushing;
11.967 -
11.968 - /* mark EOS when we received one, we must do that after putting the
11.969 - * buffer in the queue because EOS marks the buffer as filled. No need to take
11.970 - * a lock, the _check_full happens from this thread only, right before pushing
11.971 - * into dataqueue. */
11.972 - switch (type) {
11.973 - case GST_EVENT_EOS:
11.974 - sq->is_eos = TRUE;
11.975 - break;
11.976 - case GST_EVENT_NEWSEGMENT:
11.977 - apply_segment (mq, sq, sref, &sq->sink_segment);
11.978 - gst_event_unref (sref);
11.979 - break;
11.980 - default:
11.981 - break;
11.982 - }
11.983 -done:
11.984 - gst_object_unref (mq);
11.985 - return res;
11.986 -
11.987 -flushing:
11.988 - {
11.989 - GST_LOG_OBJECT (mq, "SingleQueue %d : exit because task paused, reason: %s",
11.990 - sq->id, gst_flow_get_name (sq->srcresult));
11.991 - if (sref)
11.992 - gst_event_unref (sref);
11.993 - gst_multi_queue_item_destroy (item);
11.994 - goto done;
11.995 - }
11.996 -}
11.997 -
11.998 -static GstCaps *
11.999 -gst_multi_queue_getcaps (GstPad * pad)
11.1000 -{
11.1001 - GstSingleQueue *sq = gst_pad_get_element_private (pad);
11.1002 - GstPad *otherpad;
11.1003 - GstCaps *result;
11.1004 -
11.1005 - otherpad = (pad == sq->srcpad) ? sq->sinkpad : sq->srcpad;
11.1006 -
11.1007 - GST_LOG_OBJECT (otherpad, "Getting caps from the peer of this pad");
11.1008 -
11.1009 - result = gst_pad_peer_get_caps (otherpad);
11.1010 - if (result == NULL)
11.1011 - result = gst_caps_new_any ();
11.1012 -
11.1013 - return result;
11.1014 -}
11.1015 -
11.1016 -static GstFlowReturn
11.1017 -gst_multi_queue_bufferalloc (GstPad * pad, guint64 offset, guint size,
11.1018 - GstCaps * caps, GstBuffer ** buf)
11.1019 -{
11.1020 - GstSingleQueue *sq = gst_pad_get_element_private (pad);
11.1021 -
11.1022 - return gst_pad_alloc_buffer (sq->srcpad, offset, size, caps, buf);
11.1023 -}
11.1024 -
11.1025 -static gboolean
11.1026 -gst_multi_queue_src_activate_push (GstPad * pad, gboolean active)
11.1027 -{
11.1028 - GstMultiQueue *mq;
11.1029 - GstSingleQueue *sq;
11.1030 - gboolean result = FALSE;
11.1031 -
11.1032 - sq = (GstSingleQueue *) gst_pad_get_element_private (pad);
11.1033 - mq = sq->mqueue;
11.1034 -
11.1035 - GST_DEBUG_OBJECT (mq, "SingleQueue %d", sq->id);
11.1036 -
11.1037 - if (active) {
11.1038 - result = gst_single_queue_flush (mq, sq, FALSE);
11.1039 - } else {
11.1040 - result = gst_single_queue_flush (mq, sq, TRUE);
11.1041 - /* make sure streaming finishes */
11.1042 - result |= gst_pad_stop_task (pad);
11.1043 - }
11.1044 - return result;
11.1045 -}
11.1046 -
11.1047 -static gboolean
11.1048 -gst_multi_queue_acceptcaps (GstPad * pad, GstCaps * caps)
11.1049 -{
11.1050 - return TRUE;
11.1051 -}
11.1052 -
11.1053 -static gboolean
11.1054 -gst_multi_queue_src_event (GstPad * pad, GstEvent * event)
11.1055 -{
11.1056 - GstSingleQueue *sq = gst_pad_get_element_private (pad);
11.1057 -
11.1058 - return gst_pad_push_event (sq->sinkpad, event);
11.1059 -}
11.1060 -
11.1061 -static gboolean
11.1062 -gst_multi_queue_src_query (GstPad * pad, GstQuery * query)
11.1063 -{
11.1064 - GstSingleQueue *sq = gst_pad_get_element_private (pad);
11.1065 - GstPad *peerpad;
11.1066 - gboolean res;
11.1067 -
11.1068 - /* FIXME, Handle position offset depending on queue size */
11.1069 -
11.1070 - /* default handling */
11.1071 - if (!(peerpad = gst_pad_get_peer (sq->sinkpad)))
11.1072 - goto no_peer;
11.1073 -
11.1074 - res = gst_pad_query (peerpad, query);
11.1075 -
11.1076 - gst_object_unref (peerpad);
11.1077 -
11.1078 - return res;
11.1079 -
11.1080 - /* ERRORS */
11.1081 -no_peer:
11.1082 - {
11.1083 - GST_LOG_OBJECT (sq->sinkpad, "Couldn't send query because we have no peer");
11.1084 - return FALSE;
11.1085 - }
11.1086 -}
11.1087 -
11.1088 -/*
11.1089 - * Next-non-linked functions
11.1090 - */
11.1091 -
11.1092 -/* WITH LOCK TAKEN */
11.1093 -static void
11.1094 -wake_up_next_non_linked (GstMultiQueue * mq)
11.1095 -{
11.1096 - GList *tmp;
11.1097 -
11.1098 - /* maybe no-one is waiting */
11.1099 - if (mq->numwaiting < 1)
11.1100 - return;
11.1101 -
11.1102 - /* Else figure out which singlequeue(s) need waking up */
11.1103 - for (tmp = mq->queues; tmp; tmp = g_list_next (tmp)) {
11.1104 - GstSingleQueue *sq = (GstSingleQueue *) tmp->data;
11.1105 -
11.1106 - if (sq->srcresult == GST_FLOW_NOT_LINKED) {
11.1107 - if (sq->nextid != 0 && sq->nextid <= mq->highid) {
11.1108 - GST_LOG_OBJECT (mq, "Waking up singlequeue %d", sq->id);
11.1109 - g_cond_signal (sq->turn);
11.1110 - }
11.1111 - }
11.1112 - }
11.1113 -}
11.1114 -
11.1115 -/* WITH LOCK TAKEN */
11.1116 -static void
11.1117 -compute_high_id (GstMultiQueue * mq)
11.1118 -{
11.1119 - /* The high-id is either the highest id among the linked pads, or if all
11.1120 - * pads are not-linked, it's the lowest not-linked pad */
11.1121 - GList *tmp;
11.1122 - guint32 lowest = G_MAXUINT32;
11.1123 - guint32 highid = G_MAXUINT32;
11.1124 -
11.1125 - for (tmp = mq->queues; tmp; tmp = g_list_next (tmp)) {
11.1126 - GstSingleQueue *sq = (GstSingleQueue *) tmp->data;
11.1127 -
11.1128 - GST_LOG_OBJECT (mq, "inspecting sq:%d , nextid:%d, oldid:%d, srcresult:%s",
11.1129 - sq->id, sq->nextid, sq->oldid, gst_flow_get_name (sq->srcresult));
11.1130 -
11.1131 - if (sq->srcresult == GST_FLOW_NOT_LINKED) {
11.1132 - /* No need to consider queues which are not waiting */
11.1133 - if (sq->nextid == 0) {
11.1134 - GST_LOG_OBJECT (mq, "sq:%d is not waiting - ignoring", sq->id);
11.1135 - continue;
11.1136 - }
11.1137 -
11.1138 - if (sq->nextid < lowest)
11.1139 - lowest = sq->nextid;
11.1140 - } else if (sq->srcresult != GST_FLOW_UNEXPECTED) {
11.1141 - /* If we don't have a global highid, or the global highid is lower than
11.1142 - * this single queue's last outputted id, store the queue's one,
11.1143 - * unless the singlequeue is at EOS (srcresult = UNEXPECTED) */
11.1144 - if ((highid == G_MAXUINT32) || (sq->oldid > highid))
11.1145 - highid = sq->oldid;
11.1146 - }
11.1147 - }
11.1148 -
11.1149 - if (highid == G_MAXUINT32 || lowest < highid)
11.1150 - mq->highid = lowest;
11.1151 - else
11.1152 - mq->highid = highid;
11.1153 -
11.1154 - GST_LOG_OBJECT (mq, "Highid is now : %u, lowest non-linked %u", mq->highid,
11.1155 - lowest);
11.1156 -}
11.1157 -
11.1158 -#define IS_FILLED(format, value) ((sq->max_size.format) != 0 && \
11.1159 - (sq->max_size.format) <= (value))
11.1160 -
11.1161 -/*
11.1162 - * GstSingleQueue functions
11.1163 - */
11.1164 -static void
11.1165 -single_queue_overrun_cb (GstDataQueue * dq, GstSingleQueue * sq)
11.1166 -{
11.1167 - GstMultiQueue *mq = sq->mqueue;
11.1168 - GList *tmp;
11.1169 - GstDataQueueSize size;
11.1170 - gboolean filled = FALSE;
11.1171 -
11.1172 - gst_data_queue_get_level (sq->queue, &size);
11.1173 -
11.1174 - GST_LOG_OBJECT (mq, "Single Queue %d is full", sq->id);
11.1175 -
11.1176 - GST_MULTI_QUEUE_MUTEX_LOCK (mq);
11.1177 - for (tmp = mq->queues; tmp; tmp = g_list_next (tmp)) {
11.1178 - GstSingleQueue *ssq = (GstSingleQueue *) tmp->data;
11.1179 - GstDataQueueSize ssize;
11.1180 -
11.1181 - GST_LOG_OBJECT (mq, "Checking Queue %d", ssq->id);
11.1182 -
11.1183 - if (gst_data_queue_is_empty (ssq->queue)) {
11.1184 - GST_LOG_OBJECT (mq, "Queue %d is empty", ssq->id);
11.1185 - if (IS_FILLED (visible, size.visible)) {
11.1186 - sq->max_size.visible++;
11.1187 - GST_DEBUG_OBJECT (mq,
11.1188 - "Another queue is empty, bumping single queue %d max visible to %d",
11.1189 - sq->id, sq->max_size.visible);
11.1190 - }
11.1191 - GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
11.1192 - goto beach;
11.1193 - }
11.1194 - /* check if we reached the hard time/bytes limits */
11.1195 - gst_data_queue_get_level (ssq->queue, &ssize);
11.1196 -
11.1197 - GST_DEBUG_OBJECT (mq,
11.1198 - "queue %d: visible %u/%u, bytes %u/%u, time %" G_GUINT64_FORMAT "/%"
11.1199 - G_GUINT64_FORMAT, ssq->id, ssize.visible, sq->max_size.visible,
11.1200 - ssize.bytes, sq->max_size.bytes, sq->cur_time, sq->max_size.time);
11.1201 -
11.1202 - /* if this queue is filled completely we must signal overrun */
11.1203 - if (IS_FILLED (bytes, ssize.bytes) || IS_FILLED (time, sq->cur_time)) {
11.1204 - GST_LOG_OBJECT (mq, "Queue %d is filled", ssq->id);
11.1205 - filled = TRUE;
11.1206 - }
11.1207 - }
11.1208 - /* no queues were empty */
11.1209 - GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
11.1210 -
11.1211 - /* Overrun is always forwarded, since this is blocking the upstream element */
11.1212 - if (filled) {
11.1213 - GST_DEBUG_OBJECT (mq, "A queue is filled, signalling overrun");
11.1214 - g_signal_emit (G_OBJECT (mq), gst_multi_queue_signals[SIGNAL_OVERRUN], 0);
11.1215 - }
11.1216 -
11.1217 -beach:
11.1218 - return;
11.1219 -}
11.1220 -
11.1221 -static void
11.1222 -single_queue_underrun_cb (GstDataQueue * dq, GstSingleQueue * sq)
11.1223 -{
11.1224 - gboolean empty = TRUE;
11.1225 - GstMultiQueue *mq = sq->mqueue;
11.1226 - GList *tmp;
11.1227 -
11.1228 - GST_LOG_OBJECT (mq,
11.1229 - "Single Queue %d is empty, Checking other single queues", sq->id);
11.1230 -
11.1231 - GST_MULTI_QUEUE_MUTEX_LOCK (mq);
11.1232 - for (tmp = mq->queues; tmp; tmp = g_list_next (tmp)) {
11.1233 - GstSingleQueue *sq = (GstSingleQueue *) tmp->data;
11.1234 -
11.1235 - if (gst_data_queue_is_full (sq->queue)) {
11.1236 - GstDataQueueSize size;
11.1237 -
11.1238 - gst_data_queue_get_level (sq->queue, &size);
11.1239 - if (IS_FILLED (visible, size.visible)) {
11.1240 - sq->max_size.visible++;
11.1241 - GST_DEBUG_OBJECT (mq,
11.1242 - "queue %d is filled, bumping its max visible to %d", sq->id,
11.1243 - sq->max_size.visible);
11.1244 - gst_data_queue_limits_changed (sq->queue);
11.1245 - }
11.1246 - }
11.1247 - if (!gst_data_queue_is_empty (sq->queue))
11.1248 - empty = FALSE;
11.1249 - }
11.1250 - GST_MULTI_QUEUE_MUTEX_UNLOCK (mq);
11.1251 -
11.1252 - if (empty) {
11.1253 - GST_DEBUG_OBJECT (mq, "All queues are empty, signalling it");
11.1254 - g_signal_emit (G_OBJECT (mq), gst_multi_queue_signals[SIGNAL_UNDERRUN], 0);
11.1255 - }
11.1256 -}
11.1257 -
11.1258 -static gboolean
11.1259 -single_queue_check_full (GstDataQueue * dataq, guint visible, guint bytes,
11.1260 - guint64 time, GstSingleQueue * sq)
11.1261 -{
11.1262 - gboolean res;
11.1263 -
11.1264 - GST_DEBUG ("queue %d: visible %u/%u, bytes %u/%u, time %" G_GUINT64_FORMAT
11.1265 - "/%" G_GUINT64_FORMAT, sq->id, visible, sq->max_size.visible, bytes,
11.1266 - sq->max_size.bytes, sq->cur_time, sq->max_size.time);
11.1267 -
11.1268 - /* we are always filled on EOS */
11.1269 - if (sq->is_eos)
11.1270 - return TRUE;
11.1271 -
11.1272 - /* we never go past the max visible items */
11.1273 - if (IS_FILLED (visible, visible))
11.1274 - return TRUE;
11.1275 -
11.1276 - if (sq->cur_time != 0) {
11.1277 - /* if we have valid time in the queue, check */
11.1278 - res = IS_FILLED (time, sq->cur_time);
11.1279 - } else {
11.1280 - /* no valid time, check bytes */
11.1281 - res = IS_FILLED (bytes, bytes);
11.1282 - }
11.1283 - return res;
11.1284 -}
11.1285 -
11.1286 -static void
11.1287 -gst_single_queue_free (GstSingleQueue * sq)
11.1288 -{
11.1289 - /* DRAIN QUEUE */
11.1290 - gst_data_queue_flush (sq->queue);
11.1291 - g_object_unref (sq->queue);
11.1292 - g_cond_free (sq->turn);
11.1293 - g_free (sq);
11.1294 -}
11.1295 -
11.1296 -static GstSingleQueue *
11.1297 -gst_single_queue_new (GstMultiQueue * mqueue)
11.1298 -{
11.1299 - GstSingleQueue *sq;
11.1300 - gchar *tmp;
11.1301 -
11.1302 - sq = g_new0 (GstSingleQueue, 1);
11.1303 -
11.1304 - GST_MULTI_QUEUE_MUTEX_LOCK (mqueue);
11.1305 - sq->id = mqueue->nbqueues++;
11.1306 -
11.1307 - /* copy over max_size and extra_size so we don't need to take the lock
11.1308 - * any longer when checking if the queue is full. */
11.1309 - sq->max_size.visible = mqueue->max_size.visible;
11.1310 - sq->max_size.bytes = mqueue->max_size.bytes;
11.1311 - sq->max_size.time = mqueue->max_size.time;
11.1312 -
11.1313 - sq->extra_size.visible = mqueue->extra_size.visible;
11.1314 - sq->extra_size.bytes = mqueue->extra_size.bytes;
11.1315 - sq->extra_size.time = mqueue->extra_size.time;
11.1316 -
11.1317 - GST_MULTI_QUEUE_MUTEX_UNLOCK (mqueue);
11.1318 -
11.1319 - GST_DEBUG_OBJECT (mqueue, "Creating GstSingleQueue id:%d", sq->id);
11.1320 -
11.1321 - sq->mqueue = mqueue;
11.1322 - sq->srcresult = GST_FLOW_WRONG_STATE;
11.1323 - sq->queue = gst_data_queue_new ((GstDataQueueCheckFullFunction)
11.1324 - single_queue_check_full, sq);
11.1325 - sq->is_eos = FALSE;
11.1326 - gst_segment_init (&sq->sink_segment, GST_FORMAT_TIME);
11.1327 - gst_segment_init (&sq->src_segment, GST_FORMAT_TIME);
11.1328 -
11.1329 - sq->nextid = 0;
11.1330 - sq->oldid = 0;
11.1331 - sq->turn = g_cond_new ();
11.1332 -
11.1333 - /* attach to underrun/overrun signals to handle non-starvation */
11.1334 - g_signal_connect (G_OBJECT (sq->queue), "full",
11.1335 - G_CALLBACK (single_queue_overrun_cb), sq);
11.1336 - g_signal_connect (G_OBJECT (sq->queue), "empty",
11.1337 - G_CALLBACK (single_queue_underrun_cb), sq);
11.1338 -
11.1339 - tmp = g_strdup_printf ("sink%d", sq->id);
11.1340 - sq->sinkpad = gst_pad_new_from_static_template (&sinktemplate, tmp);
11.1341 - g_free (tmp);
11.1342 -
11.1343 - gst_pad_set_chain_function (sq->sinkpad,
11.1344 - GST_DEBUG_FUNCPTR (gst_multi_queue_chain));
11.1345 - gst_pad_set_activatepush_function (sq->sinkpad,
11.1346 - GST_DEBUG_FUNCPTR (gst_multi_queue_sink_activate_push));
11.1347 - gst_pad_set_event_function (sq->sinkpad,
11.1348 - GST_DEBUG_FUNCPTR (gst_multi_queue_sink_event));
11.1349 - gst_pad_set_getcaps_function (sq->sinkpad,
11.1350 - GST_DEBUG_FUNCPTR (gst_multi_queue_getcaps));
11.1351 - gst_pad_set_bufferalloc_function (sq->sinkpad,
11.1352 - GST_DEBUG_FUNCPTR (gst_multi_queue_bufferalloc));
11.1353 - gst_pad_set_internal_link_function (sq->sinkpad,
11.1354 - GST_DEBUG_FUNCPTR (gst_multi_queue_get_internal_links));
11.1355 -
11.1356 - tmp = g_strdup_printf ("src%d", sq->id);
11.1357 - sq->srcpad = gst_pad_new_from_static_template (&srctemplate, tmp);
11.1358 - g_free (tmp);
11.1359 -
11.1360 - gst_pad_set_activatepush_function (sq->srcpad,
11.1361 - GST_DEBUG_FUNCPTR (gst_multi_queue_src_activate_push));
11.1362 - gst_pad_set_acceptcaps_function (sq->srcpad,
11.1363 - GST_DEBUG_FUNCPTR (gst_multi_queue_acceptcaps));
11.1364 - gst_pad_set_getcaps_function (sq->srcpad,
11.1365 - GST_DEBUG_FUNCPTR (gst_multi_queue_getcaps));
11.1366 - gst_pad_set_event_function (sq->srcpad,
11.1367 - GST_DEBUG_FUNCPTR (gst_multi_queue_src_event));
11.1368 - gst_pad_set_query_function (sq->srcpad,
11.1369 - GST_DEBUG_FUNCPTR (gst_multi_queue_src_query));
11.1370 - gst_pad_set_internal_link_function (sq->srcpad,
11.1371 - GST_DEBUG_FUNCPTR (gst_multi_queue_get_internal_links));
11.1372 -
11.1373 - gst_pad_set_element_private (sq->sinkpad, (gpointer) sq);
11.1374 - gst_pad_set_element_private (sq->srcpad, (gpointer) sq);
11.1375 -
11.1376 - gst_pad_set_active (sq->srcpad, TRUE);
11.1377 - gst_element_add_pad (GST_ELEMENT (mqueue), sq->srcpad);
11.1378 -
11.1379 - gst_pad_set_active (sq->sinkpad, TRUE);
11.1380 - gst_element_add_pad (GST_ELEMENT (mqueue), sq->sinkpad);
11.1381 -
11.1382 - GST_DEBUG_OBJECT (mqueue, "GstSingleQueue [%d] created and pads added",
11.1383 - sq->id);
11.1384 -
11.1385 - return sq;
11.1386 -}
11.1387 -
11.1388 -static gboolean
11.1389 -plugin_init (GstPlugin * plugin)
11.1390 -{
11.1391 - return gst_element_register (plugin, "multiqueue", GST_RANK_NONE,
11.1392 - GST_TYPE_MULTI_QUEUE);
11.1393 -}
11.1394 -
11.1395 -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
11.1396 - GST_VERSION_MINOR,
11.1397 - "multiqueue",
11.1398 - "multiqueue", plugin_init, VERSION, GST_LICENSE,
11.1399 - GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
11.1400 -
12.1 --- a/gst-gmyth/multiqueue/gstmultiqueue.h Tue Sep 18 21:01:18 2007 +0100
12.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
12.3 @@ -1,86 +0,0 @@
12.4 -/* GStreamer
12.5 - * Copyright (C) 2006 Edward Hervey <edward@fluendo.com>
12.6 - *
12.7 - * gstmultiqueue.h:
12.8 - *
12.9 - * This library is free software; you can redistribute it and/or
12.10 - * modify it under the terms of the GNU Library General Public
12.11 - * License as published by the Free Software Foundation; either
12.12 - * version 2 of the License, or (at your option) any later version.
12.13 - *
12.14 - * This library is distributed in the hope that it will be useful,
12.15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
12.16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12.17 - * Library General Public License for more details.
12.18 - *
12.19 - * You should have received a copy of the GNU Library General Public
12.20 - * License along with this library; if not, write to the
12.21 - * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
12.22 - * Boston, MA 02111-1307, USA.
12.23 - */
12.24 -
12.25 -
12.26 -#ifndef __GST_MULTI_QUEUE_H__
12.27 -#define __GST_MULTI_QUEUE_H__
12.28 -
12.29 -#include <gst/gst.h>
12.30 -#include "gstdataqueue.h"
12.31 -
12.32 -G_BEGIN_DECLS
12.33 -
12.34 -#define GST_TYPE_MULTI_QUEUE \
12.35 - (gst_multi_queue_get_type())
12.36 -#define GST_MULTI_QUEUE(obj) \
12.37 - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MULTI_QUEUE,GstMultiQueue))
12.38 -#define GST_MULTI_QUEUE_CLASS(klass) \
12.39 - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MULTI_QUEUE,GstMultiQueueClass))
12.40 -#define GST_IS_MULTI_QUEUE(obj) \
12.41 - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MULTI_QUEUE))
12.42 -#define GST_IS_MULTI_QUEUE_CLASS(obj) \
12.43 - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MULTI_QUEUE))
12.44 -
12.45 -typedef struct _GstMultiQueue GstMultiQueue;
12.46 -typedef struct _GstMultiQueueClass GstMultiQueueClass;
12.47 -
12.48 -/**
12.49 - * GstMultiQueue:
12.50 - *
12.51 - * Opaque #GstMultiQueue structure.
12.52 - */
12.53 -struct _GstMultiQueue {
12.54 - GstElement element;
12.55 -
12.56 - /* number of queues */
12.57 - guint nbqueues;
12.58 -
12.59 - /* The list of individual queues */
12.60 - GList *queues;
12.61 -
12.62 - GstDataQueueSize max_size, extra_size;
12.63 -
12.64 - guint32 counter; /* incoming object counter */
12.65 - guint32 highid; /* contains highest id of last outputted object */
12.66 -
12.67 - GMutex * qlock; /* Global queue lock (vs object lock or individual */
12.68 - /* queues lock). Protects nbqueues, queues, global */
12.69 - /* GstMultiQueueSize, counter and highid */
12.70 -
12.71 - gint nextnotlinked; /* ID of the next queue not linked (-1 : none) */
12.72 -
12.73 - gint numwaiting; /* number of not-linked pads waiting */
12.74 -};
12.75 -
12.76 -struct _GstMultiQueueClass {
12.77 - GstElementClass parent_class;
12.78 -
12.79 - /* signals emitted when ALL queues are either full or empty */
12.80 - void (*underrun) (GstMultiQueue *queue);
12.81 - void (*overrun) (GstMultiQueue *queue);
12.82 -};
12.83 -
12.84 -GType gst_multi_queue_get_type (void);
12.85 -
12.86 -G_END_DECLS
12.87 -
12.88 -
12.89 -#endif /* __GST_MULTI_QUEUE_H__ */
13.1 --- a/gst-gmyth/playbinmaemo/Makefile.am Tue Sep 18 21:01:18 2007 +0100
13.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
13.3 @@ -1,27 +0,0 @@
13.4 -plugin_LTLIBRARIES = libgstplaybinmaemo.la
13.5 -
13.6 -libgstplaybinmaemo_la_SOURCES = \
13.7 - gstplaybinmaemo.c
13.8 -
13.9 -libgstplaybinmaemo_la_CFLAGS = \
13.10 - $(GST_CFLAGS) \
13.11 - $(GST_BASE_CFLAGS) \
13.12 - $(GST_PLUGINS_BASE_CFLAGS) \
13.13 - $(X11_CFLAGS)
13.14 -
13.15 -libgstplaybinmaemo_la_LIBADD = \
13.16 - $(GST_LIBS_LIBS) \
13.17 - $(X11_LIBS)
13.18 - -lgstinterfaces-0.10
13.19 -
13.20 -libgstplaybinmaemo_la_LDFLAGS = \
13.21 - $(GST_LIBS) \
13.22 - $(GST_PLUGIN_LDFLAGS) \
13.23 - $(GST_BASE_LIBS) \
13.24 - $(GST_PLUGINS_BASE_LIBS) \
13.25 - -lgstinterfaces-0.10 \
13.26 - $(X11_LIBS)
13.27 -
13.28 -noinst_HEADERS = \
13.29 - gstplaybinmaemo.h
13.30 -
14.1 --- a/gst-gmyth/playbinmaemo/gstplaybinmaemo.c Tue Sep 18 21:01:18 2007 +0100
14.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
14.3 @@ -1,1092 +0,0 @@
14.4 -/* GStreamer
14.5 - * Copyright (C) <2007> Renato Araujo Oliveira Filho <renato.filho@indt.org.br>
14.6 - *
14.7 - * This library is free software; you can redistribute it and/or
14.8 - * modify it under the terms of the GNU Library General Public
14.9 - * License as published by the Free Software Foundation; either
14.10 - * version 2 of the License, or (at your option) any later version.
14.11 - *
14.12 - * This library is distributed in the hope that it will be useful,
14.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
14.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14.15 - * Library General Public License for more details.
14.16 - *
14.17 - * You should have received a copy of the GNU Library General Public
14.18 - * License along with this library; if not, write to the
14.19 - * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14.20 - * Boston, MA 02111-1307, USA.
14.21 - */
14.22 -
14.23 -#ifdef HAVE_CONFIG_H
14.24 -#include "config.h"
14.25 -#endif
14.26 -
14.27 -#include <glib/gi18n.h>
14.28 -#include <string.h>
14.29 -#include <gst/gst.h>
14.30 -#include <gst/gsterror.h>
14.31 -#include <gst/gstplugin.h>
14.32 -#include <gst/interfaces/xoverlay.h>
14.33 -#include <X11/Xlib.h>
14.34 -//#include <gst/pbutils/pbutils.h>
14.35 -#include "gstplaybinmaemo.h"
14.36 -
14.37 -
14.38 -GST_DEBUG_CATEGORY_STATIC (gst_play_bin_maemo_debug);
14.39 -#define GST_CAT_DEFAULT gst_play_bin_maemo_debug
14.40 -
14.41 -#define DEFAULT_VOLUME 1.0
14.42 -#define DEFAULT_XID -1
14.43 -
14.44 -/* props */
14.45 -enum
14.46 -{
14.47 - ARG_0,
14.48 - ARG_URI,
14.49 - ARG_QUEUE_SIZE,
14.50 - ARG_QUEUE_MIN_THRESHOLD,
14.51 - ARG_SOURCE,
14.52 - ARG_VOLUME,
14.53 - ARG_PARSE_METADATA,
14.54 - ARG_XID
14.55 -};
14.56 -
14.57 -static const GstElementDetails gst_play_bin_maemo_details =
14.58 - GST_ELEMENT_DETAILS("playbinmaemo",
14.59 - "Generic/Bin/Player",
14.60 - "Autoplug and play media from an uri used on maemo plataform",
14.61 - "Renato Araujo Oliveira Filho <renato.filho@indt.org.br>");
14.62 -
14.63 -static void gst_play_bin_maemo_dispose (GObject * object);
14.64 -static void gst_play_bin_maemo_finalize (GObject * object);
14.65 -static void gst_play_bin_maemo_set_property (GObject * object, guint prop_id,
14.66 - const GValue * value, GParamSpec * spec);
14.67 -static void gst_play_bin_maemo_get_property (GObject * object, guint prop_id,
14.68 - GValue * value, GParamSpec * spec);
14.69 -static GstStateChangeReturn
14.70 - gst_play_bin_maemo_change_state (GstElement *element,
14.71 - GstStateChange transition);
14.72 -static gboolean factory_filter_sinks (GstPluginFeature *feature,
14.73 - GstPlayBinMaemo *pbm);
14.74 -static gint compare_ranks (GstPluginFeature * f1,
14.75 - GstPluginFeature * f2);
14.76 -static GList *find_compatibles (GstPlayBinMaemo *pbm,
14.77 - const GstCaps *caps);
14.78 -static GstPad *find_sink_pad (GstElement * element);
14.79 -static void update_volume (GstPlayBinMaemo *pbm,
14.80 - gdouble volume);
14.81 -static void update_xid (GstPlayBinMaemo *pbm);
14.82 -static void new_decoded_pad_cb (GstElement *object,
14.83 - GstPad* pad,
14.84 - gboolean arg,
14.85 - gpointer user_data);
14.86 -static void removed_decoded_pad_cb (GstElement *object,
14.87 - GstPad* pad,
14.88 - gpointer user_data);
14.89 -static void unknown_type_cb (GstElement *object,
14.90 - GstPad *pad,
14.91 - GstCaps *casp,
14.92 - gpointer user_data);
14.93 -#if 0
14.94 -static gboolean autoplug_continue_cb (GstElement* object,
14.95 - GstCaps* caps,
14.96 - gpointer user_data);
14.97 -#endif
14.98 -static gboolean add_element (GstPlayBinMaemo *pbm,
14.99 - GstElement *child);
14.100 -static void clear_elements (GstPlayBinMaemo *pbm);
14.101 -static int x_error_handler (Display *display,
14.102 - XErrorEvent *event);
14.103 -
14.104 -GST_BOILERPLATE(GstPlayBinMaemo, gst_play_bin_maemo, GstPipeline, GST_TYPE_PIPELINE)
14.105 -
14.106 -
14.107 -static void
14.108 -gst_play_bin_maemo_base_init (gpointer klass)
14.109 -{
14.110 - GstElementClass *element_class = GST_ELEMENT_CLASS(klass);
14.111 -
14.112 - gst_element_class_set_details (element_class, &gst_play_bin_maemo_details);
14.113 -}
14.114 -
14.115 -static void
14.116 -gst_play_bin_maemo_class_init (GstPlayBinMaemoClass * klass)
14.117 -{
14.118 - GObjectClass *gobject_klass;
14.119 - GstElementClass *gstelement_klass;
14.120 - GstBinClass *gstbin_klass;
14.121 -
14.122 - gobject_klass = (GObjectClass *) klass;
14.123 - gstelement_klass = (GstElementClass *) klass;
14.124 - gstbin_klass = (GstBinClass *) klass;
14.125 -
14.126 - parent_class = g_type_class_peek_parent (klass);
14.127 -
14.128 - gobject_klass->set_property = gst_play_bin_maemo_set_property;
14.129 - gobject_klass->get_property = gst_play_bin_maemo_get_property;
14.130 -
14.131 - g_object_class_install_property (gobject_klass, ARG_URI,
14.132 - g_param_spec_string ("uri", "URI", "URI of the media to play",
14.133 - NULL, G_PARAM_READWRITE));
14.134 -
14.135 - g_object_class_install_property (gobject_klass, ARG_VOLUME,
14.136 - g_param_spec_double ("volume", "Audio volume", "volume",
14.137 - 0.0, 10.0, DEFAULT_VOLUME, G_PARAM_READWRITE));
14.138 -
14.139 - g_object_class_install_property (gobject_klass, ARG_XID,
14.140 - g_param_spec_long ("xid", "xid", "X windown ID",
14.141 - -1, G_MAXLONG, DEFAULT_XID, G_PARAM_READWRITE));
14.142 -
14.143 - g_object_class_install_property (gobject_klass, ARG_SOURCE,
14.144 - g_param_spec_object ("source", "Source", "Source element",
14.145 - GST_TYPE_ELEMENT, G_PARAM_READABLE));
14.146 -
14.147 - g_object_class_install_property (gobject_klass, ARG_PARSE_METADATA,
14.148 - g_param_spec_boolean ("parse-metadata", "Parse Metadata", "Parse metadata info",
14.149 - TRUE, G_PARAM_READWRITE));
14.150 -
14.151 -
14.152 - GST_DEBUG_CATEGORY_INIT (gst_play_bin_maemo_debug, "playbinmaemo", 0,
14.153 - "playbinmaemo");
14.154 -
14.155 - gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_play_bin_maemo_dispose);
14.156 - gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_play_bin_maemo_finalize);
14.157 -
14.158 - gstelement_klass->change_state =
14.159 - GST_DEBUG_FUNCPTR (gst_play_bin_maemo_change_state);
14.160 -}
14.161 -
14.162 -static void
14.163 -gst_play_bin_maemo_init (GstPlayBinMaemo * play_bin_maemo, GstPlayBinMaemoClass *class)
14.164 -{
14.165 - GList *factories;
14.166 -
14.167 - play_bin_maemo->uri = NULL;
14.168 - play_bin_maemo->source = NULL;
14.169 -
14.170 - play_bin_maemo->volume = DEFAULT_VOLUME;
14.171 - play_bin_maemo->xid = DEFAULT_XID;
14.172 - play_bin_maemo->parse_metadata = TRUE;
14.173 -
14.174 - factories = gst_default_registry_feature_filter (
14.175 - (GstPluginFeatureFilter) factory_filter_sinks,
14.176 - FALSE, play_bin_maemo);
14.177 -
14.178 - play_bin_maemo->factories = g_list_sort (factories,
14.179 - (GCompareFunc) compare_ranks);
14.180 -}
14.181 -
14.182 -static void
14.183 -gst_play_bin_maemo_dispose (GObject * object)
14.184 -{
14.185 - GstPlayBinMaemo *play_bin_maemo;
14.186 -
14.187 - play_bin_maemo = GST_PLAY_BIN_MAEMO (object);
14.188 - g_free (play_bin_maemo->uri);
14.189 - play_bin_maemo->uri = NULL;
14.190 - clear_elements (GST_PLAY_BIN_MAEMO (object));
14.191 -
14.192 - G_OBJECT_CLASS (parent_class)->dispose (object);
14.193 -}
14.194 -
14.195 -static void
14.196 -gst_play_bin_maemo_finalize (GObject * object)
14.197 -{
14.198 - G_OBJECT_CLASS (parent_class)->finalize (object);
14.199 -}
14.200 -
14.201 -static gboolean
14.202 -array_has_value (const gchar * values[], const gchar * value)
14.203 -{
14.204 - gint i;
14.205 -
14.206 - for (i = 0; values[i]; i++) {
14.207 - if (g_str_has_prefix (value, values[i]))
14.208 - return TRUE;
14.209 - }
14.210 - return FALSE;
14.211 -}
14.212 -
14.213 -/* list of URIs that we consider to be streams and that need buffering.
14.214 - * We have no mechanism yet to figure this out with a query. */
14.215 -static const gchar *stream_uris[] = { "http://", "mms://", "mmsh://",
14.216 - "mmsu://", "mmst://", NULL
14.217 -};
14.218 -
14.219 -/* blacklisted URIs, we know they will always fail. */
14.220 -static const gchar *blacklisted_uris[] = { NULL };
14.221 -
14.222 -/* mime types that we don't consider to be media types */
14.223 -/*
14.224 -static const gchar *no_media_mimes[] = {
14.225 - "application/x-executable", "application/x-bzip", "application/x-gzip",
14.226 - "application/zip", "application/x-compress", NULL
14.227 -};
14.228 -*/
14.229 -
14.230 -/* mime types we consider raw media */
14.231 -static const gchar *raw_mimes[] = {
14.232 - "audio/x-raw", "video/x-raw", NULL
14.233 -};
14.234 -
14.235 -#define IS_STREAM_URI(uri) (array_has_value (stream_uris, uri))
14.236 -#define IS_BLACKLISTED_URI(uri) (array_has_value (blacklisted_uris, uri))
14.237 -#define IS_NO_MEDIA_MIME(mime) (array_has_value (no_media_mimes, mime))
14.238 -#define IS_RAW_MIME(mime) (array_has_value (raw_mimes, mime))
14.239 -
14.240 -/*
14.241 - * Generate and configure a source element.
14.242 - */
14.243 -static GstElement *
14.244 -gen_source_element (GstPlayBinMaemo * play_bin_maemo)
14.245 -{
14.246 - GstElement *source;
14.247 -
14.248 - if (!play_bin_maemo->uri)
14.249 - goto no_uri;
14.250 -
14.251 - if (!gst_uri_is_valid (play_bin_maemo->uri))
14.252 - goto invalid_uri;
14.253 -
14.254 - if (IS_BLACKLISTED_URI (play_bin_maemo->uri))
14.255 - goto uri_blacklisted;
14.256 -
14.257 - source = gst_element_make_from_uri (GST_URI_SRC, play_bin_maemo->uri, "source");
14.258 - if (!source)
14.259 - goto no_source;
14.260 -
14.261 - play_bin_maemo->is_stream = IS_STREAM_URI (play_bin_maemo->uri);
14.262 -
14.263 - /* make HTTP sources send extra headers so we get icecast
14.264 - * metadata in case the stream is an icecast stream */
14.265 - if (!strncmp (play_bin_maemo->uri, "http://", 7) &&
14.266 - g_object_class_find_property (G_OBJECT_GET_CLASS (source),
14.267 - "iradio-mode")) {
14.268 - g_object_set (source, "iradio-mode", TRUE, NULL);
14.269 - }
14.270 - return source;
14.271 -
14.272 - /* ERRORS */
14.273 -no_uri:
14.274 - {
14.275 - GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, NOT_FOUND,
14.276 - (_("No URI specified to play from.")), (NULL));
14.277 - return NULL;
14.278 - }
14.279 -invalid_uri:
14.280 - {
14.281 - GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, NOT_FOUND,
14.282 - (_("Invalid URI \"%s\"."), play_bin_maemo->uri), (NULL));
14.283 - return NULL;
14.284 - }
14.285 -uri_blacklisted:
14.286 - {
14.287 - GST_ELEMENT_ERROR (play_bin_maemo, RESOURCE, FAILED,
14.288 - (_("RTSP streams cannot be played yet.")), (NULL));
14.289 - return NULL;
14.290 - }
14.291 -no_source:
14.292 - {
14.293 - gchar *prot = gst_uri_get_protocol (play_bin_maemo->uri);
14.294 -
14.295 - /* whoops, could not create the source element, dig a little deeper to
14.296 - * figure out what might be wrong. */
14.297 - if (prot) {
14.298 - /*
14.299 - gchar *desc;
14.300 -
14.301 - gst_element_post_message (GST_ELEMENT (play_bin_maemo),
14.302 - gst_missing_uri_source_message_new (GST_ELEMENT (play_bin_maemo),
14.303 - prot));
14.304 -
14.305 - desc = gst_pb_utils_get_source_description (prot);
14.306 - GST_ELEMENT_ERROR (play_bin_maemo, CORE, MISSING_PLUGIN,
14.307 - (_("A %s plugin is required to play this stream, but not installed."),
14.308 - desc), ("No URI handler for %s", prot));
14.309 - g_free (desc);
14.310 - */
14.311 - g_free (prot);
14.312 - } else
14.313 - goto invalid_uri;
14.314 -
14.315 - return NULL;
14.316 - }
14.317 -}
14.318 -
14.319 -static void
14.320 -_setup_decoder (GstPlayBinMaemo *pbm, GstElement *element)
14.321 -{
14.322 - GList *factories;
14.323 - GstCaps *all_caps;
14.324 - //GstCaps *decode_caps;
14.325 -
14.326 -
14.327 -// all_caps = gst_caps_new_empty ();
14.328 - g_object_get (element, "caps", &all_caps, NULL);
14.329 - all_caps = gst_caps_copy (all_caps);
14.330 -// gst_caps_append (all_caps, decode_caps);
14.331 -
14.332 - /* loop over all the factories */
14.333 - for (factories = pbm->factories; factories; factories = g_list_next (factories)) {
14.334 - GstElementFactory *factory = GST_ELEMENT_FACTORY (factories->data);
14.335 - const GList *templates;
14.336 - GList *walk;
14.337 -
14.338 - /* get the templates from the element factory */
14.339 - templates = gst_element_factory_get_static_pad_templates (factory);
14.340 - for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
14.341 - GstStaticPadTemplate *templ = walk->data;
14.342 -
14.343 - /* we only care about the sink templates */
14.344 - if (templ->direction == GST_PAD_SINK) {
14.345 - GstCaps *tmpl_caps;
14.346 -
14.347 - /* try to intersect the caps with the caps of the template */
14.348 - tmpl_caps = gst_static_caps_get (&templ->static_caps);
14.349 - gst_caps_append (all_caps, gst_caps_copy (tmpl_caps));
14.350 - gst_caps_ref (tmpl_caps);
14.351 - }
14.352 - }
14.353 - }
14.354 -
14.355 - g_object_set (element, "caps", all_caps, NULL);
14.356 -}
14.357 -
14.358 -static void
14.359 -prepare_elements (GstPlayBinMaemo *pbm)
14.360 -{
14.361 - GstElement *decoder;
14.362 - GstElement *queue;
14.363 -
14.364 - queue = gst_element_factory_make ("queue", NULL);
14.365 - add_element (pbm, queue);
14.366 -
14.367 - decoder = gst_element_factory_make ("decodebin2", "decode");
14.368 - _setup_decoder (pbm, decoder);
14.369 - add_element (pbm, decoder);
14.370 - /*
14.371 - g_signal_connect (G_OBJECT (decoder),
14.372 - "autoplug-continue",
14.373 - G_CALLBACK (autoplug_continue_cb),
14.374 - pbm);
14.375 - */
14.376 -
14.377 - g_signal_connect (G_OBJECT (decoder),
14.378 - "unknown-type",
14.379 - G_CALLBACK (unknown_type_cb),
14.380 - pbm);
14.381 -
14.382 - g_signal_connect (G_OBJECT (decoder),
14.383 - "new-decoded-pad",
14.384 - G_CALLBACK (new_decoded_pad_cb),
14.385 - pbm);
14.386 -
14.387 - g_signal_connect (G_OBJECT (decoder),
14.388 - "removed-decoded-pad",
14.389 - G_CALLBACK (removed_decoded_pad_cb),
14.390 - pbm);
14.391 -
14.392 -
14.393 - if (gst_element_link_many (pbm->source, queue, decoder, NULL) == FALSE) {
14.394 - GST_WARNING ("FAIL TO LINK SRC WITH DECODEBIN2");
14.395 - }
14.396 -}
14.397 -
14.398 -static gboolean
14.399 -setup_source (GstPlayBinMaemo *pbm)
14.400 -{
14.401 - if (!pbm->need_rebuild)
14.402 - return TRUE;
14.403 -
14.404 - clear_elements (pbm);
14.405 -
14.406 - GST_DEBUG_OBJECT (pbm, "setup source");
14.407 -
14.408 - pbm->has_metadata = FALSE;
14.409 -
14.410 - /* create and configure an element that can handle the uri */
14.411 - if (!(pbm->source = gen_source_element (pbm)))
14.412 - goto no_source;
14.413 -
14.414 - add_element (pbm, pbm->source);
14.415 -
14.416 -
14.417 -#if 0
14.418 - if (verify_src_have_sink (pbm)) {
14.419 - /* source can be linked with sinks directly */
14.420 - return TRUE;
14.421 - }
14.422 -#endif
14.423 -
14.424 - prepare_elements (pbm);
14.425 -
14.426 - return TRUE;
14.427 -
14.428 -no_source:
14.429 - return FALSE;
14.430 -}
14.431 -
14.432 -static void
14.433 -gst_play_bin_maemo_set_property (GObject *object,
14.434 - guint prop_id,
14.435 - const GValue *value,
14.436 - GParamSpec *pspec)
14.437 -{
14.438 - GstPlayBinMaemo *play_bin_maemo;
14.439 -
14.440 - g_return_if_fail (GST_IS_PLAY_BIN_MAEMO (object));
14.441 -
14.442 - play_bin_maemo = GST_PLAY_BIN_MAEMO (object);
14.443 -
14.444 - switch (prop_id) {
14.445 - case ARG_URI:
14.446 - {
14.447 - const gchar *uri = g_value_get_string (value);
14.448 -
14.449 - if (uri == NULL) {
14.450 - GST_WARNING ("cannot set NULL uri");
14.451 - return;
14.452 - }
14.453 - /* if we have no previous uri, or the new uri is different from the
14.454 - * old one, replug */
14.455 - if (play_bin_maemo->uri == NULL || strcmp (play_bin_maemo->uri, uri) != 0) {
14.456 - g_free (play_bin_maemo->uri);
14.457 - play_bin_maemo->uri = g_strdup (uri);
14.458 -
14.459 - GST_DEBUG ("setting new uri to %s", uri);
14.460 -
14.461 - play_bin_maemo->need_rebuild = TRUE;
14.462 - }
14.463 - break;
14.464 - }
14.465 - case ARG_VOLUME:
14.466 - update_volume(play_bin_maemo, g_value_get_double (value));
14.467 - break;
14.468 - case ARG_XID:
14.469 - {
14.470 - long xid;
14.471 - xid = g_value_get_long (value);
14.472 - if (play_bin_maemo->xid != xid)
14.473 - {
14.474 - play_bin_maemo->xid = xid;
14.475 - update_xid (play_bin_maemo);
14.476 - }
14.477 - break;
14.478 - }
14.479 - case ARG_PARSE_METADATA:
14.480 - play_bin_maemo->parse_metadata = g_value_get_boolean (value);
14.481 - break;
14.482 - default:
14.483 - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
14.484 - break;
14.485 - }
14.486 -}
14.487 -
14.488 -static void
14.489 -gst_play_bin_maemo_get_property (GObject * object,
14.490 - guint prop_id,
14.491 - GValue * value,
14.492 - GParamSpec * pspec)
14.493 -{
14.494 - GstPlayBinMaemo *play_bin_maemo;
14.495 -
14.496 - g_return_if_fail (GST_IS_PLAY_BIN_MAEMO (object));
14.497 -
14.498 - play_bin_maemo = GST_PLAY_BIN_MAEMO (object);
14.499 -
14.500 - switch (prop_id) {
14.501 - case ARG_URI:
14.502 - g_value_set_string (value, play_bin_maemo->uri);
14.503 - break;
14.504 - case ARG_SOURCE:
14.505 - g_value_set_object (value, play_bin_maemo->source);
14.506 - break;
14.507 - case ARG_VOLUME:
14.508 - g_value_set_double (value, play_bin_maemo->volume);
14.509 - break;
14.510 - case ARG_XID:
14.511 - g_value_set_long (value, play_bin_maemo->xid);
14.512 - break;
14.513 - case ARG_PARSE_METADATA:
14.514 - g_value_set_boolean (value, play_bin_maemo->parse_metadata);
14.515 - break;
14.516 - default:
14.517 - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
14.518 - break;
14.519 - }
14.520 -}
14.521 -
14.522 -static GstStateChangeReturn
14.523 -gst_play_bin_maemo_change_state (GstElement * element,
14.524 - GstStateChange transition)
14.525 -{
14.526 - GstStateChangeReturn ret;
14.527 - GstPlayBinMaemo *play_bin_maemo;
14.528 -
14.529 - play_bin_maemo = GST_PLAY_BIN_MAEMO (element);
14.530 -
14.531 - switch (transition) {
14.532 - case GST_STATE_CHANGE_READY_TO_PAUSED:
14.533 - if (!setup_source (play_bin_maemo))
14.534 - goto source_failed;
14.535 - break;
14.536 - default:
14.537 - break;
14.538 - }
14.539 -
14.540 - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
14.541 -
14.542 - switch (transition) {
14.543 - case GST_STATE_CHANGE_READY_TO_PAUSED:
14.544 - if (ret == GST_STATE_CHANGE_FAILURE) {
14.545 - play_bin_maemo->need_rebuild = TRUE;
14.546 - return GST_STATE_CHANGE_FAILURE;
14.547 - }
14.548 - break;
14.549 - /* clean-up in both cases, READY=>NULL clean-up is if there was an error */
14.550 - case GST_STATE_CHANGE_PAUSED_TO_READY:
14.551 - case GST_STATE_CHANGE_READY_TO_NULL:
14.552 - play_bin_maemo->need_rebuild = TRUE;
14.553 - clear_elements (play_bin_maemo);
14.554 - break;
14.555 - default:
14.556 - break;
14.557 - }
14.558 - return ret;
14.559 -
14.560 - /* ERRORS */
14.561 -source_failed:
14.562 - {
14.563 - play_bin_maemo->need_rebuild = TRUE;
14.564 -
14.565 - return GST_STATE_CHANGE_FAILURE;
14.566 - }
14.567 -}
14.568 -
14.569 -static gboolean
14.570 -factory_filter_sinks (GstPluginFeature *feature,
14.571 - GstPlayBinMaemo *pbm)
14.572 -{
14.573 - guint rank;
14.574 - const gchar *klass;
14.575 -
14.576 - if (!GST_IS_ELEMENT_FACTORY (feature))
14.577 - return FALSE;
14.578 -
14.579 - klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature));
14.580 -
14.581 - if ((strstr (klass, "Sink/Video") == NULL) && (strstr (klass, "Sink/Audio") == NULL))
14.582 - return FALSE;
14.583 -
14.584 - GST_DEBUG_OBJECT (pbm, "Filtered: %s",
14.585 - gst_element_factory_get_longname ((GST_ELEMENT_FACTORY (feature))));
14.586 - rank = gst_plugin_feature_get_rank (feature);
14.587 - if (rank < GST_RANK_MARGINAL)
14.588 - return FALSE;
14.589 -
14.590 - return TRUE;
14.591 -}
14.592 -
14.593 -static gint
14.594 -compare_ranks (GstPluginFeature * f1,
14.595 - GstPluginFeature * f2)
14.596 -{
14.597 - gint diff;
14.598 - const gchar *rname1, *rname2;
14.599 -
14.600 - diff = gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1);
14.601 - if (diff != 0)
14.602 - return diff;
14.603 -
14.604 - rname1 = gst_plugin_feature_get_name (f1);
14.605 - rname2 = gst_plugin_feature_get_name (f2);
14.606 -
14.607 - diff = strcmp (rname2, rname1);
14.608 -
14.609 - return diff;
14.610 -}
14.611 -
14.612 -
14.613 -static GList *
14.614 -find_compatibles (GstPlayBinMaemo *pbm,
14.615 - const GstCaps *caps)
14.616 -{
14.617 - GList *factories;
14.618 - GList *to_try = NULL;
14.619 -
14.620 - /* loop over all the factories */
14.621 - for (factories = pbm->factories; factories; factories = g_list_next (factories)) {
14.622 - GstElementFactory *factory = GST_ELEMENT_FACTORY (factories->data);
14.623 - const GList *templates;
14.624 - GList *walk;
14.625 -
14.626 - /* get the templates from the element factory */
14.627 - templates = gst_element_factory_get_static_pad_templates (factory);
14.628 - for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
14.629 - GstStaticPadTemplate *templ = walk->data;
14.630 -
14.631 - /* we only care about the sink templates */
14.632 - if (templ->direction == GST_PAD_SINK) {
14.633 - GstCaps *intersect;
14.634 - GstCaps *tmpl_caps;
14.635 -
14.636 - /* try to intersect the caps with the caps of the template */
14.637 - tmpl_caps = gst_static_caps_get (&templ->static_caps);
14.638 -
14.639 - intersect = gst_caps_intersect (caps, tmpl_caps);
14.640 -
14.641 - gst_caps_unref (tmpl_caps);
14.642 -
14.643 - /* check if the intersection is empty */
14.644 - if (!gst_caps_is_empty (intersect)) {
14.645 - /* non empty intersection, we can use this element */
14.646 - to_try = g_list_prepend (to_try, factory);
14.647 - gst_caps_unref (intersect);
14.648 - break;
14.649 - }
14.650 - gst_caps_unref (intersect);
14.651 - }
14.652 - }
14.653 - }
14.654 - to_try = g_list_reverse (to_try);
14.655 -
14.656 - return to_try;
14.657 -}
14.658 -
14.659 -#if 0
14.660 -static gboolean
14.661 -autoplug_continue_cb (GstElement* object,
14.662 - GstCaps* caps,
14.663 - gpointer user_data)
14.664 -{
14.665 - GList *comp = NULL;
14.666 - gboolean ret = TRUE;
14.667 - GstPlayBinMaemo *pbm;
14.668 -
14.669 - pbm = GST_PLAY_BIN_MAEMO (user_data);
14.670 -
14.671 - //TODO: fix this to work with all metadata elements
14.672 - if (pbm->parse_metadata) {
14.673 - gchar *caps_str = gst_caps_to_string (caps);
14.674 - if ((strstr (caps_str, "id3") != NULL) &&
14.675 - (pbm->has_metadata == FALSE)) {
14.676 -
14.677 - g_free (caps_str);
14.678 - pbm->has_metadata = TRUE;
14.679 - return ret;
14.680 - }
14.681 - g_free (caps_str);
14.682 - }
14.683 -
14.684 - comp = find_compatibles (GST_PLAY_BIN_MAEMO (user_data), caps);
14.685 - if (comp != NULL) {
14.686 - g_list_free (comp);
14.687 - ret = FALSE;
14.688 - }
14.689 -
14.690 - return ret;
14.691 -}
14.692 -#endif
14.693 -
14.694 -static void
14.695 -unknown_type_cb (GstElement *object,
14.696 - GstPad *pad,
14.697 - GstCaps *caps,
14.698 - gpointer user_data)
14.699 -{
14.700 - GST_DEBUG ("unknown_type_cb: %s", gst_caps_to_string (caps));
14.701 -}
14.702 -
14.703 -static GstPad*
14.704 -find_sink_pad (GstElement * element)
14.705 -{
14.706 - GstIterator *it;
14.707 - GstPad *pad = NULL;
14.708 - gpointer point;
14.709 -
14.710 - it = gst_element_iterate_sink_pads (element);
14.711 -
14.712 - if ((gst_iterator_next (it, &point)) == GST_ITERATOR_OK)
14.713 - pad = (GstPad *) point;
14.714 -
14.715 - gst_iterator_free (it);
14.716 -
14.717 - return pad;
14.718 -}
14.719 -
14.720 -static GstElement*
14.721 -create_element (GstPlayBinMaemo *pbm,
14.722 - GstElementFactory *factory)
14.723 -{
14.724 - GstElement *queue;
14.725 - GstElement *bin = NULL;
14.726 - GstElement *element;
14.727 - GstPad *pad;
14.728 -
14.729 - element = gst_element_factory_create (factory, NULL);
14.730 - if (element == NULL)
14.731 - goto error;
14.732 -
14.733 - bin = gst_bin_new (NULL);
14.734 - if (bin == NULL)
14.735 - goto error;
14.736 -
14.737 - queue = gst_element_factory_make ("queue", NULL);
14.738 - gst_bin_add (GST_BIN (bin), queue);
14.739 -
14.740 - if (strstr (gst_element_factory_get_klass (factory), "Sink/Video") != NULL) {
14.741 - GstElement *colorspace;
14.742 -
14.743 - colorspace = gst_element_factory_make ("ffmpegcolorspace", NULL);
14.744 - if (colorspace == NULL)
14.745 - goto error;
14.746 -
14.747 - gst_bin_add (GST_BIN (bin), colorspace);
14.748 - if (gst_element_link (queue, colorspace) == FALSE) {
14.749 - GST_WARNING_OBJECT (pbm, "Failed to link queue and colorspace");
14.750 - gst_element_set_state (colorspace, GST_STATE_NULL);
14.751 - gst_object_unref (colorspace);
14.752 - goto error;
14.753 - }
14.754 -
14.755 - gst_bin_add (GST_BIN (bin), element);
14.756 - if (gst_element_link (colorspace, element) == FALSE) {
14.757 - GST_WARNING_OBJECT (pbm, "Failed to link colorspace and sink video: %s",
14.758 - GST_ELEMENT_NAME (element));
14.759 - gst_element_set_state (colorspace, GST_STATE_NULL);
14.760 - gst_object_unref (colorspace);
14.761 - goto error;
14.762 - }
14.763 -
14.764 - pbm->video_sink = element;
14.765 - update_xid (pbm);
14.766 -
14.767 - } else if (strstr (gst_element_factory_get_klass (factory), "Sink/Audio") != NULL) {
14.768 - GParamSpec *vol_spec;
14.769 - GstElement *prev = NULL;
14.770 -
14.771 - prev = queue;
14.772 - vol_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (element), "volume");
14.773 -
14.774 - if (vol_spec == NULL) {
14.775 - GstElement *conv;
14.776 - GstElement *volume;
14.777 -
14.778 - conv = gst_element_factory_make ("audioconvert", "aconv");
14.779 - if (conv == NULL)
14.780 - goto error;
14.781 -
14.782 - gst_bin_add (GST_BIN_CAST (bin), conv);
14.783 -
14.784 - gst_element_link (queue, conv);
14.785 -
14.786 - volume = gst_element_factory_make ("volume", "volume");
14.787 - if (volume == NULL)
14.788 - goto error;
14.789 -
14.790 - gst_bin_add (GST_BIN (bin), volume);
14.791 - if (gst_element_link (conv, volume) == FALSE) {
14.792 - GST_WARNING_OBJECT (pbm, "Failed to link queue and volume");
14.793 - gst_element_set_state (volume, GST_STATE_NULL);
14.794 - gst_object_unref (volume);
14.795 - goto error;
14.796 - }
14.797 -
14.798 - prev = volume;
14.799 - }
14.800 -
14.801 - gst_bin_add (GST_BIN (bin), element);
14.802 - if (gst_element_link (prev, element) == FALSE) {
14.803 - GST_WARNING_OBJECT (pbm, "Failed to link volume and sink audio: %s", GST_ELEMENT_NAME (element));
14.804 - if (prev != queue) {
14.805 - gst_element_set_state (prev, GST_STATE_NULL);
14.806 - gst_object_unref (prev);
14.807 - }
14.808 - goto error;
14.809 - }
14.810 - pbm->volume_element = (prev != queue) ? prev : element;
14.811 - update_volume (pbm, pbm->volume);
14.812 - }
14.813 -
14.814 - pad = gst_element_get_pad (queue, "sink");
14.815 - gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad));
14.816 - gst_object_unref (pad);
14.817 -
14.818 -
14.819 - return bin;
14.820 -
14.821 -error:
14.822 - GST_WARNING_OBJECT (pbm, "Error creating pipeline");
14.823 -
14.824 - gst_element_set_state (bin, GST_STATE_NULL);
14.825 - gst_object_unref (bin);
14.826 -
14.827 - return NULL;
14.828 -}
14.829 -
14.830 -static void
14.831 -new_decoded_pad_cb (GstElement *object,
14.832 - GstPad* pad,
14.833 - gboolean arg,
14.834 - gpointer user_data)
14.835 -{
14.836 - GList *comp = NULL;
14.837 - GList *walk;
14.838 - GstCaps *caps;
14.839 - gboolean linked;
14.840 - GstPlayBinMaemo *pbm;
14.841 -
14.842 - pbm = GST_PLAY_BIN_MAEMO (user_data);
14.843 - caps = gst_pad_get_caps (pad);
14.844 -
14.845 - GST_DEBUG_OBJECT (pbm, "new_decoded_pad_cb: %s", gst_caps_to_string (caps));
14.846 -
14.847 - comp = find_compatibles (GST_PLAY_BIN_MAEMO (user_data), caps);
14.848 -
14.849 - if (comp == NULL) {
14.850 - GST_WARNING ("flow error: dont find comaptible");
14.851 - return;
14.852 - }
14.853 -
14.854 - GST_PAD_STREAM_LOCK (pad);
14.855 -
14.856 - linked = FALSE;
14.857 - for (walk=comp; walk != NULL; walk = walk->next) {
14.858 - GstElementFactory *factory = (GstElementFactory *) walk->data;
14.859 - GstElement *element;
14.860 - GstPad *sinkpad = NULL;
14.861 -
14.862 -
14.863 - if ((element = create_element (pbm, factory)) == NULL) {
14.864 - GST_WARNING_OBJECT (pbm, "Could not create an element from %s",
14.865 - gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
14.866 - continue;
14.867 - }
14.868 -
14.869 - if (!(sinkpad = find_sink_pad (element))) {
14.870 - GST_WARNING_OBJECT (pbm, "Element %s doesn't have a sink pad", GST_ELEMENT_NAME (element));
14.871 - gst_object_unref (element);
14.872 - continue;
14.873 - }
14.874 -
14.875 - if (!(add_element (GST_PLAY_BIN_MAEMO (user_data), element))) {
14.876 - GST_WARNING_OBJECT (pbm, "Couldn't add element %s to bin", GST_ELEMENT_NAME (element));
14.877 - gst_object_unref (sinkpad);
14.878 - gst_object_unref (element);
14.879 - continue;
14.880 - }
14.881 -
14.882 - if ((gst_element_set_state (element, GST_STATE_READY))
14.883 - == GST_STATE_CHANGE_FAILURE) {
14.884 - GST_WARNING_OBJECT (pbm, "Couldn't set %s to READY", GST_ELEMENT_NAME (element));
14.885 - gst_object_unref (sinkpad);
14.886 - gst_bin_remove (GST_BIN (user_data), element);
14.887 - continue;
14.888 - }
14.889 -
14.890 - if (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK) {
14.891 - GST_WARNING_OBJECT (pbm, "Link failed on pad %s:%s", GST_DEBUG_PAD_NAME (sinkpad));
14.892 - gst_element_set_state (element, GST_STATE_NULL);
14.893 - gst_object_unref (sinkpad);
14.894 - gst_bin_remove (GST_BIN (user_data), element);
14.895 - continue;
14.896 - }
14.897 -
14.898 - gst_object_unref (sinkpad);
14.899 -
14.900 - if ((gst_element_set_state (element, GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) {
14.901 - gst_element_set_state (element, GST_STATE_NULL);
14.902 - gst_bin_remove (GST_BIN (user_data), element);
14.903 - continue;
14.904 - }
14.905 -
14.906 - linked = TRUE;
14.907 - break;
14.908 - }
14.909 -
14.910 - g_list_free (comp);
14.911 - if (linked == FALSE) {
14.912 - GST_WARNING ("GstFlow ERROR");
14.913 - }
14.914 - GST_PAD_STREAM_UNLOCK (pad);
14.915 -}
14.916 -
14.917 -static void
14.918 -removed_decoded_pad_cb (GstElement *object,
14.919 - GstPad* pad,
14.920 - gpointer user_data)
14.921 -{
14.922 - GstElement *sink;
14.923 -
14.924 - GST_DEBUG("removed_decoded_pad_cb");
14.925 -
14.926 - sink = gst_pad_get_parent_element (pad);
14.927 -
14.928 - if (sink)
14.929 - gst_bin_remove (GST_BIN (user_data), sink);
14.930 -}
14.931 -
14.932 -static GValue*
14.933 -convert_volume_base (GstPlayBinMaemo *pbm, gfloat volume)
14.934 -{
14.935 - GValue value = { 0, };
14.936 - GValue *converted_vol = g_new0(GValue, 1);
14.937 -
14.938 - GParamSpec* vol_spec = g_object_class_find_property (
14.939 - G_OBJECT_GET_CLASS (pbm->volume_element), "volume");
14.940 -
14.941 - g_value_init (&value, vol_spec->value_type);
14.942 - g_value_init (converted_vol, vol_spec->value_type);
14.943 -
14.944 - g_object_get_property (G_OBJECT (pbm->volume_element), "volume", &value);
14.945 -
14.946 - /* convert volume from double to int range if needed */
14.947 - switch (G_VALUE_TYPE (&value)) {
14.948 - case G_TYPE_UINT:
14.949 - {
14.950 - GParamSpecUInt *puint = G_PARAM_SPEC_UINT (vol_spec);
14.951 - guint scale = puint->maximum - puint->minimum;
14.952 - guint vol_guint = (guint) ((scale * volume) + puint->minimum);
14.953 -
14.954 - GST_WARNING ("Range: %u - %u, Converted: %u",
14.955 - puint->minimum, puint->maximum, vol_guint);
14.956 - g_value_set_uint (converted_vol, vol_guint);
14.957 - break;
14.958 - }
14.959 - case G_TYPE_INT:
14.960 - {
14.961 - GParamSpecInt *pint = G_PARAM_SPEC_INT (vol_spec);
14.962 - gint scale = pint->maximum - pint->minimum;
14.963 - gint vol_gint = (gint) ((scale * volume) + pint->minimum);
14.964 -
14.965 - GST_WARNING ("Range: %d - %d, Converted: %d",
14.966 - pint->minimum, pint->maximum, vol_gint);
14.967 - g_value_set_int (converted_vol, vol_gint);
14.968 - break;
14.969 - }
14.970 - case G_TYPE_DOUBLE:
14.971 - case G_TYPE_FLOAT:
14.972 - {
14.973 - GST_WARNING ("Default converted to float: %f", volume);
14.974 - g_value_set_double (converted_vol, volume);
14.975 - break;
14.976 - }
14.977 - default:
14.978 - GST_WARNING ("Dont know how to convert volume");
14.979 - }
14.980 -
14.981 - return converted_vol;
14.982 -}
14.983 -
14.984 -static void
14.985 -update_volume (GstPlayBinMaemo *pbm, gdouble volume)
14.986 -{
14.987 - pbm->volume = volume;
14.988 - if (pbm->volume_element) {
14.989 - GValue *converted_vol = convert_volume_base (pbm, volume);
14.990 - g_object_set_property (G_OBJECT (pbm->volume_element), "volume",
14.991 - converted_vol);
14.992 - g_value_unset (converted_vol);
14.993 - }
14.994 -}
14.995 -
14.996 -static void
14.997 -update_xid (GstPlayBinMaemo *pbm)
14.998 -{
14.999 - if ((pbm->video_sink != NULL) && (pbm->xid != -1) &&
14.1000 - (GST_IS_X_OVERLAY (pbm->video_sink))) {
14.1001 - Display *display;
14.1002 - /*
14.1003 - g_object_set (G_OBJECT (pbm->video_sink),
14.1004 - "force-aspect-ratio", TRUE, NULL);
14.1005 - */
14.1006 -
14.1007 - display = XOpenDisplay(NULL);
14.1008 -
14.1009 - XMapRaised(display, pbm->xid);
14.1010 - XSync (display, FALSE);
14.1011 -
14.1012 - XSetErrorHandler(x_error_handler);
14.1013 -
14.1014 - gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (pbm->video_sink),
14.1015 - pbm->xid);
14.1016 - }
14.1017 -}
14.1018 -
14.1019 -static int
14.1020 -x_error_handler(Display *display,
14.1021 - XErrorEvent *event)
14.1022 -{
14.1023 - GST_DEBUG ("In x error handler:");
14.1024 -
14.1025 - switch (event->error_code) {
14.1026 - case BadWindow:
14.1027 - GST_DEBUG ("got bad window");
14.1028 - break;
14.1029 - case BadDrawable:
14.1030 - GST_DEBUG ("got bad drawable");
14.1031 - break;
14.1032 - case BadGC:
14.1033 - GST_DEBUG ("got bad gc");
14.1034 - break;
14.1035 - default:
14.1036 - GST_DEBUG ("unhandled x error = %d", event->error_code);
14.1037 - }
14.1038 -
14.1039 - return 0;
14.1040 -}
14.1041 -
14.1042 -static gboolean
14.1043 -add_element (GstPlayBinMaemo *pbm,
14.1044 - GstElement *child)
14.1045 -{
14.1046 - if (gst_bin_add (GST_BIN (pbm), child)) {
14.1047 - pbm->elements = g_list_append (pbm->elements, child);
14.1048 - return TRUE;
14.1049 - }
14.1050 - return FALSE;
14.1051 -}
14.1052 -
14.1053 -static void
14.1054 -clear_elements (GstPlayBinMaemo *pbm)
14.1055 -{
14.1056 - GList *walk;
14.1057 -
14.1058 - walk = pbm->elements;
14.1059 -
14.1060 - for (; walk != NULL; walk = walk->next) {
14.1061 - GstElement *e = GST_ELEMENT (walk->data);
14.1062 -
14.1063 - gst_element_set_state (e, GST_STATE_NULL);
14.1064 - gst_bin_remove (GST_BIN (pbm), e);
14.1065 - }
14.1066 -
14.1067 - g_list_free (pbm->elements);
14.1068 - pbm->elements = NULL;
14.1069 - pbm->source = NULL;
14.1070 - pbm->volume_element = NULL;
14.1071 - pbm->video_sink = NULL;
14.1072 -}
14.1073 -
14.1074 -static gboolean
14.1075 -plugin_init(GstPlugin * plugin)
14.1076 -{
14.1077 -#ifdef ENABLE_NLS
14.1078 - setlocale(LC_ALL, "");
14.1079 - bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
14.1080 -#endif /* ENABLE_NLS */
14.1081 -
14.1082 - if (!gst_element_register(plugin, "playbinmaemo", GST_RANK_SECONDARY,
14.1083 - GST_TYPE_PLAY_BIN_MAEMO)) {
14.1084 - return FALSE;
14.1085 - }
14.1086 -
14.1087 - return TRUE;
14.1088 -}
14.1089 -
14.1090 -GST_PLUGIN_DEFINE(GST_VERSION_MAJOR,
14.1091 - GST_VERSION_MINOR,
14.1092 - "playbinmaemo",
14.1093 - "A playbin element that uses decodebin2 for automatic playback of audio and video",
14.1094 - plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME,
14.1095 - GST_PACKAGE_ORIGIN)
15.1 --- a/gst-gmyth/playbinmaemo/gstplaybinmaemo.h Tue Sep 18 21:01:18 2007 +0100
15.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
15.3 @@ -1,73 +0,0 @@
15.4 -/* GStreamer
15.5 - *
15.6 - * This library is free software; you can redistribute it and/or
15.7 - * modify it under the terms of the GNU Library General Public
15.8 - * License as published by the Free Software Foundation; either
15.9 - * version 2 of the License, or (at your option) any later version.
15.10 - *
15.11 - * This library is distributed in the hope that it will be useful,
15.12 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
15.13 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15.14 - * Library General Public License for more details.
15.15 - *
15.16 - * You should have received a copy of the GNU Library General Public
15.17 - * License along with this library; if not, write to the
15.18 - * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15.19 - * Boston, MA 02111-1307, USA.
15.20 - */
15.21 -
15.22 -#ifndef __GST_PLAYBINMAEMO_H__
15.23 -#define __GST_PLAYBINMAEMO_H__
15.24 -
15.25 -#include <gst/gst.h>
15.26 -
15.27 -G_BEGIN_DECLS
15.28 -
15.29 -#define GST_TYPE_PLAY_BIN_MAEMO \
15.30 - (gst_play_bin_maemo_get_type())
15.31 -#define GST_PLAY_BIN_MAEMO(obj) \
15.32 - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PLAY_BIN_MAEMO,GstPlayBinMaemo))
15.33 -#define GST_PLAY_BIN_MAEMO_CLASS(klass) \
15.34 - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PLAY_BIN_MAEMO,GstPlayBinMaemoClass))
15.35 -#define GST_IS_PLAY_BIN_MAEMO(obj) \
15.36 - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PLAY_BIN_MAEMO))
15.37 -#define GST_IS_PLAY_BIN_MAEMO_CLASS(klass) \
15.38 - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PLAY_BIN_MAEMO))
15.39 -#define GST_PLAY_BIN_MAEMO_GET_CLASS(obj) \
15.40 - (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_PLAY_BIN_MAEMO,GstPlayBinMaemoClass))
15.41 -
15.42 -typedef struct _GstPlayBinMaemo GstPlayBinMaemo;
15.43 -typedef struct _GstPlayBinMaemoClass GstPlayBinMaemoClass;
15.44 -
15.45 -struct _GstPlayBinMaemo {
15.46 - GstPipeline pipeline;
15.47 -
15.48 - /* properties */
15.49 - guint64 queue_size;
15.50 - guint64 queue_min_threshold;
15.51 - gboolean is_stream;
15.52 - gboolean parse_metadata;
15.53 - glong xid;
15.54 - gdouble volume;
15.55 -
15.56 - /* currently loaded media */
15.57 - gboolean need_rebuild;
15.58 - gboolean has_metadata;
15.59 - gchar *uri;
15.60 - GstElement *volume_element;
15.61 - GstElement *source;
15.62 - GstElement *video_sink;
15.63 - GList *elements;
15.64 - GList *factories;
15.65 -};
15.66 -
15.67 -struct _GstPlayBinMaemoClass {
15.68 - GstPipelineClass parent_class;
15.69 -};
15.70 -
15.71 -GType gst_play_bin_maemo_get_type (void);
15.72 -
15.73 -G_END_DECLS
15.74 -
15.75 -#endif /* __GST_PLAYBINMAEMO_H__ */
15.76 -