[svn r860] moved playbinmaemo to maemo-myth project 'https://garage.maemo.org/svn/mtv/trunk/gst' trunk
authorrenatofilho
Mon Sep 24 16:06:54 2007 +0100 (2007-09-24)
branchtrunk
changeset 854871e367c9d90
parent 853 c738c2ac1968
child 855 16857017fc11
[svn r860] moved playbinmaemo to maemo-myth project 'https://garage.maemo.org/svn/mtv/trunk/gst'
gst-gmyth/Makefile.am
gst-gmyth/configure.ac
gst-gmyth/debian/control
gst-gmyth/decodebin2/Makefile.am
gst-gmyth/decodebin2/gstdecodebin2.c
gst-gmyth/decodebin2/gstplay-marshal.c
gst-gmyth/decodebin2/gstplay-marshal.h
gst-gmyth/multiqueue/Makefile.am
gst-gmyth/multiqueue/gstdataqueue.c
gst-gmyth/multiqueue/gstdataqueue.h
gst-gmyth/multiqueue/gstmultiqueue.c
gst-gmyth/multiqueue/gstmultiqueue.h
gst-gmyth/playbinmaemo/Makefile.am
gst-gmyth/playbinmaemo/gstplaybinmaemo.c
gst-gmyth/playbinmaemo/gstplaybinmaemo.h
     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 -