gst_plugins_base/gst/playback/gsturidecodebin.c
changeset 0 0e761a78d257
child 8 4a7fac7dd34a
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     1 /* GStreamer
       
     2  * Copyright (C) <2007> Wim Taymans <wim.taymans@gmail.com>
       
     3  *
       
     4  * This library is free software; you can redistribute it and/or
       
     5  * modify it under the terms of the GNU Library General Public
       
     6  * License as published by the Free Software Foundation; either
       
     7  * version 2 of the License, or (at your option) any later version.
       
     8  *
       
     9  * This library is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    12  * Library General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU Library General Public
       
    15  * License along with this library; if not, write to the
       
    16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    17  * Boston, MA 02111-1307, USA.
       
    18  */
       
    19 
       
    20 /**
       
    21  * SECTION:element-uridecodebin
       
    22  * @short_description: decoder for an uri
       
    23  *
       
    24  * Decodes data from a URI into raw media.
       
    25  */
       
    26 
       
    27 #ifdef HAVE_CONFIG_H
       
    28 #  include "config.h"
       
    29 #endif
       
    30 
       
    31 #include <string.h>
       
    32 
       
    33 #include <gst/gst.h>
       
    34 #include <gst/gst-i18n-plugin.h>
       
    35 
       
    36 #include "gstplay-marshal.h"
       
    37 #include "gstplay-enum.h"
       
    38 
       
    39 #ifdef __SYMBIAN32__
       
    40 #include <glib_global.h>
       
    41 #endif
       
    42 #define GST_TYPE_URI_DECODE_BIN \
       
    43   (gst_uri_decode_bin_get_type())
       
    44 #define GST_URI_DECODE_BIN(obj) \
       
    45   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_URI_DECODE_BIN,GstURIDecodeBin))
       
    46 #define GST_URI_DECODE_BIN_CLASS(klass) \
       
    47   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_URI_DECODE_BIN,GstURIDecodeBinClass))
       
    48 #define GST_IS_URI_DECODE_BIN(obj) \
       
    49   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_URI_DECODE_BIN))
       
    50 #define GST_IS_URI_DECODE_BIN_CLASS(klass) \
       
    51   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_URI_DECODE_BIN))
       
    52 
       
    53 typedef struct _GstURIDecodeBin GstURIDecodeBin;
       
    54 typedef struct _GstURIDecodeBinClass GstURIDecodeBinClass;
       
    55 
       
    56 struct _GstURIDecodeBin
       
    57 {
       
    58   GstBin parent_instance;
       
    59 
       
    60   gchar *uri;
       
    61   guint connection_speed;
       
    62   GstCaps *caps;
       
    63   gchar *encoding;
       
    64 
       
    65   gboolean is_stream;
       
    66   GstElement *source;
       
    67   GstElement *queue;
       
    68   GSList *decoders;
       
    69   GSList *srcpads;
       
    70   gint numpads;
       
    71 
       
    72   /* for dynamic sources */
       
    73   guint src_np_sig_id;          /* new-pad signal id */
       
    74   guint src_nmp_sig_id;         /* no-more-pads signal id */
       
    75   gint pending;
       
    76 };
       
    77 
       
    78 struct _GstURIDecodeBinClass
       
    79 {
       
    80   GstBinClass parent_class;
       
    81 
       
    82   /* signal fired when we found a pad that we cannot decode */
       
    83   void (*unknown_type) (GstElement * element, GstPad * pad, GstCaps * caps);
       
    84 
       
    85   /* signal fired to know if we continue trying to decode the given caps */
       
    86     gboolean (*autoplug_continue) (GstElement * element, GstPad * pad,
       
    87       GstCaps * caps);
       
    88   /* signal fired to get a list of factories to try to autoplug */
       
    89   GValueArray *(*autoplug_factories) (GstElement * element, GstPad * pad,
       
    90       GstCaps * caps);
       
    91   /* signal fired to select from the proposed list of factories */
       
    92     GstAutoplugSelectResult (*autoplug_select) (GstElement * element,
       
    93       GstPad * pad, GstCaps * caps, GValueArray * factories);
       
    94 
       
    95   /* emited when all data is decoded */
       
    96   void (*drained) (GstElement * element);
       
    97 };
       
    98 
       
    99 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src%d",
       
   100     GST_PAD_SRC,
       
   101     GST_PAD_SOMETIMES,
       
   102     GST_STATIC_CAPS_ANY);
       
   103 
       
   104 GST_DEBUG_CATEGORY_STATIC (gst_uri_decode_bin_debug);
       
   105 #define GST_CAT_DEFAULT gst_uri_decode_bin_debug
       
   106 
       
   107 static const GstElementDetails gst_uri_decode_bin_details =
       
   108 GST_ELEMENT_DETAILS ("URI Decoder",
       
   109     "Generic/Bin/Decoder",
       
   110     "Autoplug and decode an URI to raw media",
       
   111     "Wim Taymans <wim.taymans@gmail.com>");
       
   112 
       
   113 /* signals */
       
   114 enum
       
   115 {
       
   116   SIGNAL_UNKNOWN_TYPE,
       
   117   SIGNAL_AUTOPLUG_CONTINUE,
       
   118   SIGNAL_AUTOPLUG_FACTORIES,
       
   119   SIGNAL_AUTOPLUG_SELECT,
       
   120   SIGNAL_DRAINED,
       
   121   LAST_SIGNAL
       
   122 };
       
   123 
       
   124 /* properties */
       
   125 #define DEFAULT_PROP_URI	    NULL
       
   126 #define DEFAULT_CONNECTION_SPEED    0
       
   127 #define DEFAULT_CAPS                NULL
       
   128 #define DEFAULT_SUBTITLE_ENCODING   NULL
       
   129 
       
   130 enum
       
   131 {
       
   132   PROP_0,
       
   133   PROP_URI,
       
   134   PROP_CONNECTION_SPEED,
       
   135   PROP_CAPS,
       
   136   PROP_SUBTITLE_ENCODING,
       
   137   PROP_LAST
       
   138 };
       
   139 
       
   140 static guint gst_uri_decode_bin_signals[LAST_SIGNAL] = { 0 };
       
   141 
       
   142 GST_BOILERPLATE (GstURIDecodeBin, gst_uri_decode_bin, GstBin, GST_TYPE_BIN);
       
   143 
       
   144 static void gst_uri_decode_bin_set_property (GObject * object, guint prop_id,
       
   145     const GValue * value, GParamSpec * pspec);
       
   146 static void gst_uri_decode_bin_get_property (GObject * object, guint prop_id,
       
   147     GValue * value, GParamSpec * pspec);
       
   148 static void gst_uri_decode_bin_finalize (GObject * obj);
       
   149 
       
   150 static void handle_message (GstBin * bin, GstMessage * msg);
       
   151 
       
   152 static gboolean gst_uri_decode_bin_query (GstElement * element,
       
   153     GstQuery * query);
       
   154 static GstStateChangeReturn gst_uri_decode_bin_change_state (GstElement *
       
   155     element, GstStateChange transition);
       
   156 
       
   157 static void
       
   158 gst_uri_decode_bin_base_init (gpointer g_class)
       
   159 {
       
   160   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
       
   161 
       
   162   gst_element_class_add_pad_template (gstelement_class,
       
   163       gst_static_pad_template_get (&srctemplate));
       
   164   gst_element_class_set_details (gstelement_class, &gst_uri_decode_bin_details);
       
   165 }
       
   166 
       
   167 static gboolean
       
   168 _gst_boolean_accumulator (GSignalInvocationHint * ihint,
       
   169     GValue * return_accu, const GValue * handler_return, gpointer dummy)
       
   170 {
       
   171   gboolean myboolean;
       
   172 
       
   173   myboolean = g_value_get_boolean (handler_return);
       
   174   if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
       
   175     g_value_set_boolean (return_accu, myboolean);
       
   176 
       
   177   /* stop emission if FALSE */
       
   178   return myboolean;
       
   179 }
       
   180 
       
   181 static gboolean
       
   182 _gst_array_accumulator (GSignalInvocationHint * ihint,
       
   183     GValue * return_accu, const GValue * handler_return, gpointer dummy)
       
   184 {
       
   185   gpointer array;
       
   186 
       
   187   array = g_value_get_boxed (handler_return);
       
   188   if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
       
   189     g_value_set_boxed (return_accu, array);
       
   190 
       
   191   return FALSE;
       
   192 }
       
   193 
       
   194 static gboolean
       
   195 _gst_select_accumulator (GSignalInvocationHint * ihint,
       
   196     GValue * return_accu, const GValue * handler_return, gpointer dummy)
       
   197 {
       
   198   GstAutoplugSelectResult res;
       
   199 
       
   200   res = g_value_get_enum (handler_return);
       
   201   if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP))
       
   202     g_value_set_enum (return_accu, res);
       
   203 
       
   204   return FALSE;
       
   205 }
       
   206 
       
   207 static gboolean
       
   208 gst_uri_decode_bin_autoplug_continue (GstElement * element, GstPad * pad,
       
   209     GstCaps * caps)
       
   210 {
       
   211   /* by default we always continue */
       
   212   return TRUE;
       
   213 }
       
   214 
       
   215 static void
       
   216 gst_uri_decode_bin_class_init (GstURIDecodeBinClass * klass)
       
   217 {
       
   218   GObjectClass *gobject_class;
       
   219   GstElementClass *gstelement_class;
       
   220   GstBinClass *gstbin_class;
       
   221 
       
   222   gobject_class = G_OBJECT_CLASS (klass);
       
   223   gstelement_class = GST_ELEMENT_CLASS (klass);
       
   224   gstbin_class = GST_BIN_CLASS (klass);
       
   225 
       
   226   gobject_class->set_property = gst_uri_decode_bin_set_property;
       
   227   gobject_class->get_property = gst_uri_decode_bin_get_property;
       
   228   gobject_class->finalize = gst_uri_decode_bin_finalize;
       
   229 
       
   230   g_object_class_install_property (gobject_class, PROP_URI,
       
   231       g_param_spec_string ("uri", "URI", "URI to decode",
       
   232           DEFAULT_PROP_URI, G_PARAM_READWRITE));
       
   233 
       
   234   g_object_class_install_property (gobject_class, PROP_CONNECTION_SPEED,
       
   235       g_param_spec_uint ("connection-speed", "Connection Speed",
       
   236           "Network connection speed in kbps (0 = unknown)",
       
   237           0, G_MAXUINT, DEFAULT_CONNECTION_SPEED, G_PARAM_READWRITE));
       
   238 
       
   239   g_object_class_install_property (gobject_class, PROP_CAPS,
       
   240       g_param_spec_boxed ("caps", "Caps",
       
   241           "The caps on which to stop decoding. (NULL = default)",
       
   242           GST_TYPE_CAPS, G_PARAM_READWRITE));
       
   243 
       
   244   g_object_class_install_property (gobject_class, PROP_SUBTITLE_ENCODING,
       
   245       g_param_spec_string ("subtitle-encoding", "subtitle encoding",
       
   246           "Encoding to assume if input subtitles are not in UTF-8 encoding. "
       
   247           "If not set, the GST_SUBTITLE_ENCODING environment variable will "
       
   248           "be checked for an encoding to use. If that is not set either, "
       
   249           "ISO-8859-15 will be assumed.", NULL, G_PARAM_READWRITE));
       
   250 
       
   251   /**
       
   252    * GstURIDecodeBin::unknown-type:
       
   253    * @pad: the new pad containing caps that cannot be resolved to a 'final' stream type.
       
   254    * @caps: the #GstCaps of the pad that cannot be resolved.
       
   255    *
       
   256    * This signal is emitted when a pad for which there is no further possible
       
   257    * decoding is added to the uridecodebin.
       
   258    */
       
   259   gst_uri_decode_bin_signals[SIGNAL_UNKNOWN_TYPE] =
       
   260       g_signal_new ("unknown-type", G_TYPE_FROM_CLASS (klass),
       
   261       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass, unknown_type),
       
   262       NULL, NULL, gst_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2,
       
   263       GST_TYPE_PAD, GST_TYPE_CAPS);
       
   264 
       
   265   /**
       
   266    * GstURIDecodeBin::autoplug-continue:
       
   267    * @pad: The #GstPad.
       
   268    * @caps: The #GstCaps found.
       
   269    *
       
   270    * This signal is emitted whenever uridecodebin finds a new stream. It is
       
   271    * emitted before looking for any elements that can handle that stream.
       
   272    *
       
   273    * Returns: #TRUE if you wish uridecodebin to look for elements that can
       
   274    * handle the given @caps. If #FALSE, those caps will be considered as
       
   275    * final and the pad will be exposed as such (see 'new-decoded-pad'
       
   276    * signal).
       
   277    */
       
   278   gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE] =
       
   279       g_signal_new ("autoplug-continue", G_TYPE_FROM_CLASS (klass),
       
   280       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass,
       
   281           autoplug_continue), _gst_boolean_accumulator, NULL,
       
   282       gst_play_marshal_BOOLEAN__OBJECT_OBJECT, G_TYPE_BOOLEAN, 2, GST_TYPE_PAD,
       
   283       GST_TYPE_CAPS);
       
   284 
       
   285   /**
       
   286    * GstURIDecodeBin::autoplug-factories:
       
   287    * @pad: The #GstPad.
       
   288    * @caps: The #GstCaps found.
       
   289    *
       
   290    * This function is emited when an array of possible factories for @caps on
       
   291    * @pad is needed. Decodebin2 will by default return 
       
   292    *
       
   293    * Returns: a #GValueArray* with a list of factories to try. The factories are
       
   294    * by default tried in the returned order or based on the index returned by
       
   295    * "autoplug-select".
       
   296    */
       
   297   gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES] =
       
   298       g_signal_new ("autoplug-factories", G_TYPE_FROM_CLASS (klass),
       
   299       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass,
       
   300           autoplug_factories), _gst_array_accumulator, NULL,
       
   301       gst_play_marshal_BOXED__OBJECT_OBJECT, G_TYPE_VALUE_ARRAY, 2,
       
   302       GST_TYPE_PAD, GST_TYPE_CAPS);
       
   303 
       
   304   /**
       
   305    * GstURIDecodeBin::autoplug-select:
       
   306    * @pad: The #GstPad.
       
   307    * @caps: The #GstCaps.
       
   308    * @factories: A #GValueArray of possible #GstElementFactory to use, sorted by
       
   309    * rank (higher ranks come first).
       
   310    *
       
   311    * This signal is emitted once uridecodebin has found all the possible
       
   312    * #GstElementFactory that can be used to handle the given @caps.
       
   313    *
       
   314    * Returns: A #gint indicating what factory index from the @factories array
       
   315    * that you wish uridecodebin to use for trying to decode the given @caps.
       
   316    * -1 to stop selection of a factory. The default handler always
       
   317    * returns the first possible factory.
       
   318    */
       
   319   gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT] =
       
   320       g_signal_new ("autoplug-select", G_TYPE_FROM_CLASS (klass),
       
   321       G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass,
       
   322           autoplug_select), _gst_select_accumulator, NULL,
       
   323       gst_play_marshal_ENUM__OBJECT_OBJECT_OBJECT,
       
   324       GST_TYPE_AUTOPLUG_SELECT_RESULT, 3, GST_TYPE_PAD, GST_TYPE_CAPS,
       
   325       GST_TYPE_ELEMENT_FACTORY);
       
   326 
       
   327   /**
       
   328    * GstURIDecodeBin::drained:
       
   329    *
       
   330    * This signal is emitted when the data for the current uri is played.
       
   331    */
       
   332   gst_uri_decode_bin_signals[SIGNAL_DRAINED] =
       
   333       g_signal_new ("drained", G_TYPE_FROM_CLASS (klass),
       
   334       G_SIGNAL_RUN_LAST,
       
   335       G_STRUCT_OFFSET (GstURIDecodeBinClass, drained), NULL, NULL,
       
   336       gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE);
       
   337 
       
   338   gstelement_class->query = GST_DEBUG_FUNCPTR (gst_uri_decode_bin_query);
       
   339   gstelement_class->change_state =
       
   340       GST_DEBUG_FUNCPTR (gst_uri_decode_bin_change_state);
       
   341 
       
   342   gstbin_class->handle_message = GST_DEBUG_FUNCPTR (handle_message);
       
   343 
       
   344   klass->autoplug_continue =
       
   345       GST_DEBUG_FUNCPTR (gst_uri_decode_bin_autoplug_continue);
       
   346 }
       
   347 
       
   348 static void
       
   349 gst_uri_decode_bin_init (GstURIDecodeBin * dec, GstURIDecodeBinClass * klass)
       
   350 {
       
   351   dec->uri = g_strdup (DEFAULT_PROP_URI);
       
   352   dec->connection_speed = DEFAULT_CONNECTION_SPEED;
       
   353   dec->caps = DEFAULT_CAPS;
       
   354   dec->encoding = g_strdup (DEFAULT_SUBTITLE_ENCODING);
       
   355 }
       
   356 
       
   357 static void
       
   358 gst_uri_decode_bin_finalize (GObject * obj)
       
   359 {
       
   360   GstURIDecodeBin *dec = GST_URI_DECODE_BIN (obj);
       
   361 
       
   362   g_free (dec->uri);
       
   363   g_free (dec->encoding);
       
   364 
       
   365   G_OBJECT_CLASS (parent_class)->finalize (obj);
       
   366 }
       
   367 
       
   368 static void
       
   369 gst_uri_decode_bin_set_property (GObject * object, guint prop_id,
       
   370     const GValue * value, GParamSpec * pspec)
       
   371 {
       
   372   GstURIDecodeBin *dec = GST_URI_DECODE_BIN (object);
       
   373 
       
   374   switch (prop_id) {
       
   375     case PROP_URI:
       
   376       GST_OBJECT_LOCK (dec);
       
   377       g_free (dec->uri);
       
   378       dec->uri = g_value_dup_string (value);
       
   379       GST_OBJECT_UNLOCK (dec);
       
   380       break;
       
   381     case PROP_CONNECTION_SPEED:
       
   382       GST_OBJECT_LOCK (dec);
       
   383       dec->connection_speed = g_value_get_uint (value) * 1000;
       
   384       GST_OBJECT_UNLOCK (dec);
       
   385       break;
       
   386     case PROP_CAPS:
       
   387       GST_OBJECT_LOCK (dec);
       
   388       if (dec->caps)
       
   389         gst_caps_unref (dec->caps);
       
   390       dec->caps = g_value_dup_boxed (value);
       
   391       GST_OBJECT_UNLOCK (dec);
       
   392       break;
       
   393     case PROP_SUBTITLE_ENCODING:
       
   394       GST_OBJECT_LOCK (dec);
       
   395       g_free (dec->encoding);
       
   396       dec->encoding = g_value_dup_string (value);
       
   397       GST_OBJECT_UNLOCK (dec);
       
   398       break;
       
   399     default:
       
   400       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
   401       break;
       
   402   }
       
   403 }
       
   404 
       
   405 static void
       
   406 gst_uri_decode_bin_get_property (GObject * object, guint prop_id,
       
   407     GValue * value, GParamSpec * pspec)
       
   408 {
       
   409   GstURIDecodeBin *dec = GST_URI_DECODE_BIN (object);
       
   410 
       
   411   switch (prop_id) {
       
   412     case PROP_URI:
       
   413       GST_OBJECT_LOCK (dec);
       
   414       g_value_set_string (value, dec->uri);
       
   415       GST_OBJECT_UNLOCK (dec);
       
   416       break;
       
   417     case PROP_CONNECTION_SPEED:
       
   418       GST_OBJECT_LOCK (dec);
       
   419       g_value_set_uint (value, dec->connection_speed / 1000);
       
   420       GST_OBJECT_UNLOCK (dec);
       
   421       break;
       
   422     case PROP_CAPS:
       
   423       GST_OBJECT_LOCK (dec);
       
   424       g_value_set_boxed (value, dec->caps);
       
   425       GST_OBJECT_UNLOCK (dec);
       
   426       break;
       
   427     case PROP_SUBTITLE_ENCODING:
       
   428       GST_OBJECT_LOCK (dec);
       
   429       g_value_set_string (value, dec->encoding);
       
   430       GST_OBJECT_UNLOCK (dec);
       
   431       break;
       
   432     default:
       
   433       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       
   434       break;
       
   435   }
       
   436 }
       
   437 
       
   438 #define DEFAULT_QUEUE_SIZE          (3 * GST_SECOND)
       
   439 #define DEFAULT_QUEUE_MIN_THRESHOLD ((DEFAULT_QUEUE_SIZE * 30) / 100)
       
   440 #define DEFAULT_QUEUE_THRESHOLD     ((DEFAULT_QUEUE_SIZE * 95) / 100)
       
   441 
       
   442 static void
       
   443 unknown_type_cb (GstElement * element, GstPad * pad, GstCaps * caps,
       
   444     GstURIDecodeBin * decoder)
       
   445 {
       
   446   gchar *capsstr;
       
   447 
       
   448   capsstr = gst_caps_to_string (caps);
       
   449   GST_ELEMENT_WARNING (decoder, STREAM, WRONG_TYPE,
       
   450       (_("No decoder available for type \'%s\'."), capsstr), (NULL));
       
   451   g_free (capsstr);
       
   452 }
       
   453 
       
   454 /* add a streaminfo that indicates that the stream is handled by the
       
   455  * given element. This usually means that a stream without actual data is
       
   456  * produced but one that is sunken by an element. Examples of this are:
       
   457  * cdaudio, a hardware decoder/sink, dvd meta bins etc...
       
   458  */
       
   459 static void
       
   460 add_element_stream (GstElement * element, GstURIDecodeBin * decoder)
       
   461 {
       
   462   g_warning ("add element stream");
       
   463 }
       
   464 
       
   465 /* when the decoder element signals that no more pads will be generated, we
       
   466  * can commit the current group.
       
   467  */
       
   468 static void
       
   469 no_more_pads_full (GstElement * element, gboolean subs,
       
   470     GstURIDecodeBin * decoder)
       
   471 {
       
   472   gboolean final;
       
   473 
       
   474   /* setup phase */
       
   475   GST_DEBUG_OBJECT (element, "no more pads, %d pending", decoder->pending);
       
   476 
       
   477   GST_OBJECT_LOCK (decoder);
       
   478   final = (decoder->pending == 0);
       
   479 
       
   480   /* nothing pending, we can exit */
       
   481   if (final)
       
   482     goto done;
       
   483 
       
   484   /* the object has no pending no_more_pads */
       
   485   if (!g_object_get_data (G_OBJECT (element), "pending"))
       
   486     goto done;
       
   487   g_object_set_data (G_OBJECT (element), "pending", NULL);
       
   488 
       
   489   decoder->pending--;
       
   490   final = (decoder->pending == 0);
       
   491 
       
   492 done:
       
   493   GST_OBJECT_UNLOCK (decoder);
       
   494 
       
   495   if (final)
       
   496     gst_element_no_more_pads (GST_ELEMENT_CAST (decoder));
       
   497 
       
   498   return;
       
   499 }
       
   500 
       
   501 static void
       
   502 no_more_pads (GstElement * element, GstURIDecodeBin * decoder)
       
   503 {
       
   504   no_more_pads_full (element, FALSE, decoder);
       
   505 }
       
   506 
       
   507 static void
       
   508 source_no_more_pads (GstElement * element, GstURIDecodeBin * bin)
       
   509 {
       
   510   GST_DEBUG_OBJECT (bin, "No more pads in source element %s.",
       
   511       GST_ELEMENT_NAME (element));
       
   512 
       
   513   g_signal_handler_disconnect (G_OBJECT (element), bin->src_np_sig_id);
       
   514   bin->src_np_sig_id = 0;
       
   515   g_signal_handler_disconnect (G_OBJECT (element), bin->src_nmp_sig_id);
       
   516   bin->src_nmp_sig_id = 0;
       
   517 
       
   518   no_more_pads_full (element, FALSE, bin);
       
   519 }
       
   520 
       
   521 /* Called by the signal handlers when a decodebin has 
       
   522  * found a new raw pad.  
       
   523  */
       
   524 static void
       
   525 new_decoded_pad_cb (GstElement * element, GstPad * pad, gboolean last,
       
   526     GstURIDecodeBin * decoder)
       
   527 {
       
   528   GstPad *newpad;
       
   529   gchar *padname;
       
   530 
       
   531   GST_DEBUG_OBJECT (element, "new decoded pad, name: <%s>. Last: %d",
       
   532       GST_PAD_NAME (pad), last);
       
   533 
       
   534   GST_OBJECT_LOCK (decoder);
       
   535   padname = g_strdup_printf ("src%d", decoder->numpads);
       
   536   decoder->numpads++;
       
   537   GST_OBJECT_UNLOCK (decoder);
       
   538 
       
   539   newpad = gst_ghost_pad_new (padname, pad);
       
   540   g_free (padname);
       
   541 
       
   542   /* store ref to the ghostpad so we can remove it */
       
   543   g_object_set_data (G_OBJECT (pad), "uridecodebin.ghostpad", newpad);
       
   544 
       
   545   gst_pad_set_active (newpad, TRUE);
       
   546   gst_element_add_pad (GST_ELEMENT_CAST (decoder), newpad);
       
   547 }
       
   548 
       
   549 static void
       
   550 pad_removed_cb (GstElement * element, GstPad * pad, GstURIDecodeBin * decoder)
       
   551 {
       
   552   GstPad *ghost;
       
   553 
       
   554   GST_DEBUG_OBJECT (element, "pad removed name: <%s:%s>",
       
   555       GST_DEBUG_PAD_NAME (pad));
       
   556 
       
   557   if (!(ghost = g_object_get_data (G_OBJECT (pad), "uridecodebin.ghostpad")))
       
   558     goto no_ghost;
       
   559 
       
   560   /* unghost the pad */
       
   561   gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ghost), NULL);
       
   562 
       
   563   /* deactivate and remove */
       
   564   gst_pad_set_active (pad, FALSE);
       
   565   gst_element_remove_pad (GST_ELEMENT_CAST (decoder), ghost);
       
   566 
       
   567   return;
       
   568 
       
   569   /* ERRORS */
       
   570 no_ghost:
       
   571   {
       
   572     GST_WARNING_OBJECT (element, "no ghost pad found");
       
   573     return;
       
   574   }
       
   575 }
       
   576 
       
   577 /* helper function to lookup stuff in lists */
       
   578 static gboolean
       
   579 array_has_value (const gchar * values[], const gchar * value)
       
   580 {
       
   581   gint i;
       
   582 
       
   583   for (i = 0; values[i]; i++) {
       
   584     if (g_str_has_prefix (value, values[i]))
       
   585       return TRUE;
       
   586   }
       
   587   return FALSE;
       
   588 }
       
   589 
       
   590 /* list of URIs that we consider to be streams and that need buffering.
       
   591  * We have no mechanism yet to figure this out with a query. */
       
   592 static const gchar *stream_uris[] = { "http://", "mms://", "mmsh://",
       
   593   "mmsu://", "mmst://", NULL
       
   594 };
       
   595 
       
   596 /* blacklisted URIs, we know they will always fail. */
       
   597 static const gchar *blacklisted_uris[] = { NULL };
       
   598 
       
   599 /* mime types that we don't consider to be media types */
       
   600 #if 0
       
   601 static const gchar *no_media_mimes[] = {
       
   602   "application/x-executable", "application/x-bzip", "application/x-gzip",
       
   603   "application/zip", "application/x-compress", NULL
       
   604 };
       
   605 #endif
       
   606 
       
   607 /* mime types we consider raw media */
       
   608 static const gchar *raw_mimes[] = {
       
   609   "audio/x-raw", "video/x-raw", NULL
       
   610 };
       
   611 
       
   612 #define IS_STREAM_URI(uri)          (array_has_value (stream_uris, uri))
       
   613 #define IS_BLACKLISTED_URI(uri)     (array_has_value (blacklisted_uris, uri))
       
   614 #define IS_NO_MEDIA_MIME(mime)      (array_has_value (no_media_mimes, mime))
       
   615 #define IS_RAW_MIME(mime)           (array_has_value (raw_mimes, mime))
       
   616 
       
   617 /*
       
   618  * Generate and configure a source element.
       
   619  */
       
   620 static GstElement *
       
   621 gen_source_element (GstURIDecodeBin * decoder)
       
   622 {
       
   623   GstElement *source;
       
   624 
       
   625   if (!decoder->uri)
       
   626     goto no_uri;
       
   627 
       
   628   if (!gst_uri_is_valid (decoder->uri))
       
   629     goto invalid_uri;
       
   630 
       
   631   if (IS_BLACKLISTED_URI (decoder->uri))
       
   632     goto uri_blacklisted;
       
   633 
       
   634   source = gst_element_make_from_uri (GST_URI_SRC, decoder->uri, "source");
       
   635   if (!source)
       
   636     goto no_source;
       
   637 
       
   638   decoder->is_stream = IS_STREAM_URI (decoder->uri);
       
   639 
       
   640   /* make HTTP sources send extra headers so we get icecast
       
   641    * metadata in case the stream is an icecast stream */
       
   642   if (!strncmp (decoder->uri, "http://", 7) &&
       
   643       g_object_class_find_property (G_OBJECT_GET_CLASS (source),
       
   644           "iradio-mode")) {
       
   645     g_object_set (source, "iradio-mode", TRUE, NULL);
       
   646   }
       
   647 
       
   648   if (g_object_class_find_property (G_OBJECT_GET_CLASS (source),
       
   649           "connection-speed")) {
       
   650     GST_DEBUG_OBJECT (decoder,
       
   651         "setting connection-speed=%d to source element",
       
   652         decoder->connection_speed / 1000);
       
   653     g_object_set (source, "connection-speed",
       
   654         decoder->connection_speed / 1000, NULL);
       
   655   }
       
   656 
       
   657   return source;
       
   658 
       
   659   /* ERRORS */
       
   660 no_uri:
       
   661   {
       
   662     GST_ELEMENT_ERROR (decoder, RESOURCE, NOT_FOUND,
       
   663         (_("No URI specified to play from.")), (NULL));
       
   664     return NULL;
       
   665   }
       
   666 invalid_uri:
       
   667   {
       
   668     GST_ELEMENT_ERROR (decoder, RESOURCE, NOT_FOUND,
       
   669         (_("Invalid URI \"%s\"."), decoder->uri), (NULL));
       
   670     return NULL;
       
   671   }
       
   672 uri_blacklisted:
       
   673   {
       
   674     GST_ELEMENT_ERROR (decoder, RESOURCE, FAILED,
       
   675         (_("This stream type cannot be played yet.")), (NULL));
       
   676     return NULL;
       
   677   }
       
   678 no_source:
       
   679   {
       
   680     gchar *prot = gst_uri_get_protocol (decoder->uri);
       
   681 
       
   682     /* whoops, could not create the source element, dig a little deeper to
       
   683      * figure out what might be wrong. */
       
   684     if (prot) {
       
   685       GST_ELEMENT_ERROR (decoder, RESOURCE, FAILED,
       
   686           (_("No URI handler implemented for \"%s\"."), prot), (NULL));
       
   687       g_free (prot);
       
   688     } else
       
   689       goto invalid_uri;
       
   690 
       
   691     return NULL;
       
   692   }
       
   693 }
       
   694 
       
   695 /**
       
   696  * has_all_raw_caps:
       
   697  * @pad: a #GstPad
       
   698  * @all_raw: pointer to hold the result
       
   699  *
       
   700  * check if the caps of the pad are all raw. The caps are all raw if
       
   701  * all of its structures contain audio/x-raw or video/x-raw.
       
   702  *
       
   703  * Returns: %FALSE @pad has no caps. Else TRUE and @all_raw set t the result.
       
   704  */
       
   705 static gboolean
       
   706 has_all_raw_caps (GstPad * pad, gboolean * all_raw)
       
   707 {
       
   708   GstCaps *caps;
       
   709   gint capssize;
       
   710   guint i, num_raw = 0;
       
   711   gboolean res = FALSE;
       
   712 
       
   713   caps = gst_pad_get_caps (pad);
       
   714   if (caps == NULL)
       
   715     return FALSE;
       
   716 
       
   717   capssize = gst_caps_get_size (caps);
       
   718   /* no caps, skip and move to the next pad */
       
   719   if (capssize == 0 || gst_caps_is_empty (caps) || gst_caps_is_any (caps))
       
   720     goto done;
       
   721 
       
   722   /* count the number of raw formats in the caps */
       
   723   for (i = 0; i < capssize; ++i) {
       
   724     GstStructure *s;
       
   725     const gchar *mime_type;
       
   726 
       
   727     s = gst_caps_get_structure (caps, i);
       
   728     mime_type = gst_structure_get_name (s);
       
   729 
       
   730     if (IS_RAW_MIME (mime_type))
       
   731       ++num_raw;
       
   732   }
       
   733 
       
   734   *all_raw = (num_raw == capssize);
       
   735   res = TRUE;
       
   736 
       
   737 done:
       
   738   gst_caps_unref (caps);
       
   739   return res;
       
   740 }
       
   741 
       
   742 /**
       
   743  * analyse_source:
       
   744  * @decoder: a #GstURIDecodeBin
       
   745  * @is_raw: are all pads raw data
       
   746  * @have_out: does the source have output
       
   747  * @is_dynamic: is this a dynamic source
       
   748  *
       
   749  * Check the source of @decoder and collect information about it.
       
   750  *
       
   751  * @is_raw will be set to TRUE if the source only produces raw pads. When this
       
   752  * function returns, all of the raw pad of the source will be added
       
   753  * to @decoder.
       
   754  *
       
   755  * @have_out: will be set to TRUE if the source has output pads.
       
   756  *
       
   757  * @is_dynamic: TRUE if the element will create (more) pads dynamically later
       
   758  * on.
       
   759  *
       
   760  * Returns: FALSE if a fatal error occured while scanning.
       
   761  */
       
   762 static gboolean
       
   763 analyse_source (GstURIDecodeBin * decoder, gboolean * is_raw,
       
   764     gboolean * have_out, gboolean * is_dynamic)
       
   765 {
       
   766   GstIterator *pads_iter;
       
   767   gboolean done = FALSE;
       
   768   gboolean res = TRUE;
       
   769 
       
   770   *have_out = FALSE;
       
   771   *is_raw = FALSE;
       
   772   *is_dynamic = FALSE;
       
   773 
       
   774   pads_iter = gst_element_iterate_src_pads (decoder->source);
       
   775   while (!done) {
       
   776     GstPad *pad;
       
   777 
       
   778     switch (gst_iterator_next (pads_iter, (gpointer) & pad)) {
       
   779       case GST_ITERATOR_ERROR:
       
   780         res = FALSE;
       
   781         /* FALLTROUGH */
       
   782       case GST_ITERATOR_DONE:
       
   783         done = TRUE;
       
   784         break;
       
   785       case GST_ITERATOR_RESYNC:
       
   786         /* reset results and resync */
       
   787         *have_out = FALSE;
       
   788         *is_raw = FALSE;
       
   789         *is_dynamic = FALSE;
       
   790         gst_iterator_resync (pads_iter);
       
   791         break;
       
   792       case GST_ITERATOR_OK:
       
   793         /* we now officially have an ouput pad */
       
   794         *have_out = TRUE;
       
   795 
       
   796         /* if FALSE, this pad has no caps and we continue with the next pad. */
       
   797         if (!has_all_raw_caps (pad, is_raw))
       
   798           break;
       
   799 
       
   800         /* caps on source pad are all raw, we can add the pad */
       
   801         if (*is_raw)
       
   802           new_decoded_pad_cb (decoder->source, pad, FALSE, decoder);
       
   803         break;
       
   804     }
       
   805   }
       
   806   gst_iterator_free (pads_iter);
       
   807 
       
   808   if (!*have_out) {
       
   809     GstElementClass *elemclass;
       
   810     GList *walk;
       
   811 
       
   812     /* element has no output pads, check for padtemplates that list SOMETIMES
       
   813      * pads. */
       
   814     elemclass = GST_ELEMENT_GET_CLASS (decoder->source);
       
   815 
       
   816     walk = gst_element_class_get_pad_template_list (elemclass);
       
   817     while (walk != NULL) {
       
   818       GstPadTemplate *templ;
       
   819 
       
   820       templ = (GstPadTemplate *) walk->data;
       
   821       if (GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC) {
       
   822         if (GST_PAD_TEMPLATE_PRESENCE (templ) == GST_PAD_SOMETIMES)
       
   823           *is_dynamic = TRUE;
       
   824         break;
       
   825       }
       
   826       walk = g_list_next (walk);
       
   827     }
       
   828   }
       
   829 
       
   830   return res;
       
   831 }
       
   832 
       
   833 static void
       
   834 remove_decoders (GstURIDecodeBin * bin)
       
   835 {
       
   836   GSList *walk;
       
   837 
       
   838   for (walk = bin->decoders; walk; walk = g_slist_next (walk)) {
       
   839     GstElement *decoder = GST_ELEMENT_CAST (walk->data);
       
   840 
       
   841     GST_DEBUG_OBJECT (bin, "removing old decoder element");
       
   842     gst_element_set_state (decoder, GST_STATE_NULL);
       
   843     gst_bin_remove (GST_BIN_CAST (bin), decoder);
       
   844   }
       
   845   g_slist_free (bin->decoders);
       
   846   bin->decoders = NULL;
       
   847 }
       
   848 
       
   849 static void
       
   850 remove_pads (GstURIDecodeBin * bin)
       
   851 {
       
   852   GSList *walk;
       
   853 
       
   854   for (walk = bin->srcpads; walk; walk = g_slist_next (walk)) {
       
   855     GstPad *pad = GST_PAD_CAST (walk->data);
       
   856 
       
   857     GST_DEBUG_OBJECT (bin, "removing old pad");
       
   858     gst_pad_set_active (pad, FALSE);
       
   859     gst_element_remove_pad (GST_ELEMENT_CAST (bin), pad);
       
   860   }
       
   861   g_slist_free (bin->srcpads);
       
   862   bin->srcpads = NULL;
       
   863 }
       
   864 
       
   865 static void
       
   866 proxy_unknown_type_signal (GstElement * element, GstPad * pad, GstCaps * caps,
       
   867     GstURIDecodeBin * dec)
       
   868 {
       
   869   GST_DEBUG_OBJECT (dec, "unknown-type signaled");
       
   870 
       
   871   g_signal_emit (G_OBJECT (dec),
       
   872       gst_uri_decode_bin_signals[SIGNAL_UNKNOWN_TYPE], 0, pad, caps);
       
   873 }
       
   874 
       
   875 static gboolean
       
   876 proxy_autoplug_continue_signal (GstElement * element, GstPad * pad,
       
   877     GstCaps * caps, GstURIDecodeBin * dec)
       
   878 {
       
   879   gboolean result;
       
   880 
       
   881   g_signal_emit (G_OBJECT (dec),
       
   882       gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE], 0, pad, caps,
       
   883       &result);
       
   884 
       
   885   GST_DEBUG_OBJECT (dec, "autoplug-continue returned %d", result);
       
   886 
       
   887   return result;
       
   888 }
       
   889 
       
   890 static GValueArray *
       
   891 proxy_autoplug_factories_signal (GstElement * element, GstPad * pad,
       
   892     GstCaps * caps, GstURIDecodeBin * dec)
       
   893 {
       
   894   GValueArray *result = NULL;
       
   895 
       
   896   g_signal_emit (G_OBJECT (dec),
       
   897       gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES], 0, pad, caps,
       
   898       &result);
       
   899 
       
   900   GST_DEBUG_OBJECT (dec, "autoplug-factories returned %p", result);
       
   901 
       
   902   return result;
       
   903 }
       
   904 
       
   905 static GstAutoplugSelectResult
       
   906 proxy_autoplug_select_signal (GstElement * element, GstPad * pad,
       
   907     GstCaps * caps, GstElementFactory * factory, GstURIDecodeBin * dec)
       
   908 {
       
   909   GstAutoplugSelectResult result;
       
   910 
       
   911   g_signal_emit (G_OBJECT (dec),
       
   912       gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT], 0, pad, caps, factory,
       
   913       &result);
       
   914 
       
   915   GST_DEBUG_OBJECT (dec, "autoplug-select returned %d", result);
       
   916 
       
   917   return result;
       
   918 }
       
   919 
       
   920 static void
       
   921 proxy_drained_signal (GstElement * element, GstURIDecodeBin * dec)
       
   922 {
       
   923   GST_DEBUG_OBJECT (dec, "drained signaled");
       
   924 
       
   925   g_signal_emit (G_OBJECT (dec),
       
   926       gst_uri_decode_bin_signals[SIGNAL_DRAINED], 0, NULL);
       
   927 }
       
   928 
       
   929 static GstElement *
       
   930 make_decoder (GstURIDecodeBin * decoder, gboolean use_queue)
       
   931 {
       
   932   GstElement *result, *decodebin;
       
   933 
       
   934   /* now create the decoder element */
       
   935   decodebin = gst_element_factory_make ("decodebin2", NULL);
       
   936   if (!decodebin)
       
   937     goto no_decodebin;
       
   938 
       
   939   /* connect signals to proxy */
       
   940   g_signal_connect (G_OBJECT (decodebin), "unknown-type",
       
   941       G_CALLBACK (proxy_unknown_type_signal), decoder);
       
   942   g_signal_connect (G_OBJECT (decodebin), "autoplug-continue",
       
   943       G_CALLBACK (proxy_autoplug_continue_signal), decoder);
       
   944   g_signal_connect (G_OBJECT (decodebin), "autoplug-factories",
       
   945       G_CALLBACK (proxy_autoplug_factories_signal), decoder);
       
   946   g_signal_connect (G_OBJECT (decodebin), "autoplug-select",
       
   947       G_CALLBACK (proxy_autoplug_select_signal), decoder);
       
   948   g_signal_connect (G_OBJECT (decodebin), "drained",
       
   949       G_CALLBACK (proxy_drained_signal), decoder);
       
   950 
       
   951   if (use_queue) {
       
   952     GstElement *queue;
       
   953     GstPad *gpad, *pad;
       
   954 
       
   955     queue = gst_element_factory_make ("queue2", NULL);
       
   956     if (!queue)
       
   957       goto no_queue2;
       
   958 
       
   959     /* configure the queue as a buffering element */
       
   960     g_object_set (G_OBJECT (queue), "use-buffering", TRUE, NULL);
       
   961 
       
   962     result = gst_bin_new ("source-bin");
       
   963 
       
   964     gst_bin_add (GST_BIN_CAST (result), queue);
       
   965     gst_bin_add (GST_BIN_CAST (result), decodebin);
       
   966 
       
   967     gst_element_link (queue, decodebin);
       
   968 
       
   969     pad = gst_element_get_pad (queue, "sink");
       
   970     gpad = gst_ghost_pad_new (GST_PAD_NAME (pad), pad);
       
   971     gst_object_unref (pad);
       
   972 
       
   973     gst_pad_set_active (gpad, TRUE);
       
   974     gst_element_add_pad (GST_ELEMENT_CAST (result), gpad);
       
   975   } else {
       
   976     result = decodebin;
       
   977   }
       
   978 
       
   979   /* set up callbacks to create the links between decoded data
       
   980    * and video/audio/subtitle rendering/output. */
       
   981   g_signal_connect (G_OBJECT (decodebin),
       
   982       "new-decoded-pad", G_CALLBACK (new_decoded_pad_cb), decoder);
       
   983   g_signal_connect (G_OBJECT (decodebin),
       
   984       "pad-removed", G_CALLBACK (pad_removed_cb), decoder);
       
   985   g_signal_connect (G_OBJECT (decodebin), "no-more-pads",
       
   986       G_CALLBACK (no_more_pads), decoder);
       
   987   g_signal_connect (G_OBJECT (decodebin),
       
   988       "unknown-type", G_CALLBACK (unknown_type_cb), decoder);
       
   989   g_object_set_data (G_OBJECT (decodebin), "pending", "1");
       
   990   decoder->pending++;
       
   991 
       
   992   gst_bin_add (GST_BIN_CAST (decoder), result);
       
   993 
       
   994   decoder->decoders = g_slist_prepend (decoder->decoders, result);
       
   995 
       
   996   return result;
       
   997 
       
   998   /* ERRORS */
       
   999 no_decodebin:
       
  1000   {
       
  1001     GST_ELEMENT_ERROR (decoder, CORE, MISSING_PLUGIN,
       
  1002         (_("Could not create \"decodebin2\" element.")), (NULL));
       
  1003     return NULL;
       
  1004   }
       
  1005 no_queue2:
       
  1006   {
       
  1007     GST_ELEMENT_ERROR (decoder, CORE, MISSING_PLUGIN,
       
  1008         (_("Could not create \"queue2\" element.")), (NULL));
       
  1009     return NULL;
       
  1010   }
       
  1011 }
       
  1012 
       
  1013 static void
       
  1014 remove_source (GstURIDecodeBin * bin)
       
  1015 {
       
  1016   GstElement *source = bin->source;
       
  1017 
       
  1018   if (source) {
       
  1019     GST_DEBUG_OBJECT (bin, "removing old src element");
       
  1020     gst_element_set_state (source, GST_STATE_NULL);
       
  1021     gst_bin_remove (GST_BIN_CAST (bin), source);
       
  1022 
       
  1023     if (bin->src_np_sig_id) {
       
  1024       g_signal_handler_disconnect (G_OBJECT (source), bin->src_np_sig_id);
       
  1025       bin->src_np_sig_id = 0;
       
  1026     }
       
  1027     if (bin->src_nmp_sig_id) {
       
  1028       g_signal_handler_disconnect (G_OBJECT (source), bin->src_nmp_sig_id);
       
  1029       bin->src_nmp_sig_id = 0;
       
  1030     }
       
  1031     bin->source = NULL;
       
  1032   }
       
  1033 }
       
  1034 
       
  1035 /* is called when a dynamic source element created a new pad. */
       
  1036 static void
       
  1037 source_new_pad (GstElement * element, GstPad * pad, GstURIDecodeBin * bin)
       
  1038 {
       
  1039   GstElement *decoder;
       
  1040   gboolean is_raw;
       
  1041 
       
  1042   GST_DEBUG_OBJECT (bin, "Found new pad %s.%s in source element %s",
       
  1043       GST_DEBUG_PAD_NAME (pad), GST_ELEMENT_NAME (element));
       
  1044 
       
  1045   /* if this is a pad with all raw caps, we can expose it */
       
  1046   if (has_all_raw_caps (pad, &is_raw) && is_raw) {
       
  1047     /* it's all raw, create output pads. */
       
  1048     new_decoded_pad_cb (element, pad, FALSE, bin);
       
  1049     return;
       
  1050   }
       
  1051 
       
  1052   /* not raw, create decoder */
       
  1053   decoder = make_decoder (bin, FALSE);
       
  1054   if (!decoder)
       
  1055     goto no_decodebin;
       
  1056 
       
  1057   /* and link to decoder */
       
  1058   if (!gst_element_link (bin->source, decoder))
       
  1059     goto could_not_link;
       
  1060 
       
  1061   GST_DEBUG_OBJECT (bin, "linked decoder to new pad");
       
  1062 
       
  1063   gst_element_set_state (decoder, GST_STATE_PLAYING);
       
  1064 
       
  1065   return;
       
  1066 
       
  1067   /* ERRORS */
       
  1068 no_decodebin:
       
  1069   {
       
  1070     /* error was posted */
       
  1071     return;
       
  1072   }
       
  1073 could_not_link:
       
  1074   {
       
  1075     GST_ELEMENT_ERROR (bin, CORE, NEGOTIATION,
       
  1076         (NULL), ("Can't link source to decoder element"));
       
  1077     return;
       
  1078   }
       
  1079 }
       
  1080 
       
  1081 /* construct and run the source and decoder elements until we found
       
  1082  * all the streams or until a preroll queue has been filled.
       
  1083 */
       
  1084 static gboolean
       
  1085 setup_source (GstURIDecodeBin * decoder)
       
  1086 {
       
  1087   gboolean is_raw, have_out, is_dynamic;
       
  1088 
       
  1089   GST_DEBUG_OBJECT (decoder, "setup source");
       
  1090 
       
  1091   /* delete old src */
       
  1092   remove_source (decoder);
       
  1093 
       
  1094   /* create and configure an element that can handle the uri */
       
  1095   if (!(decoder->source = gen_source_element (decoder)))
       
  1096     goto no_source;
       
  1097 
       
  1098   /* state will be merged later - if file is not found, error will be
       
  1099    * handled by the application right after. */
       
  1100   gst_bin_add (GST_BIN_CAST (decoder), decoder->source);
       
  1101 
       
  1102   /* remove the old decoders now, if any */
       
  1103   remove_decoders (decoder);
       
  1104 
       
  1105   /* see if the source element emits raw audio/video all by itself,
       
  1106    * if so, we can create streams for the pads and be done with it.
       
  1107    * Also check that is has source pads, if not, we assume it will
       
  1108    * do everything itself.  */
       
  1109   if (!analyse_source (decoder, &is_raw, &have_out, &is_dynamic))
       
  1110     goto invalid_source;
       
  1111 
       
  1112   if (is_raw) {
       
  1113     GST_DEBUG_OBJECT (decoder, "Source provides all raw data");
       
  1114     /* source provides raw data, we added the pads and we can now signal a
       
  1115      * no_more pads because we are done. */
       
  1116     /* FIXME, actually do this... */
       
  1117     return TRUE;
       
  1118   }
       
  1119   if (!have_out && !is_dynamic) {
       
  1120     GST_DEBUG_OBJECT (decoder, "Source has no output pads");
       
  1121     /* create a stream to indicate that this uri is handled by a self
       
  1122      * contained element. We are now done. */
       
  1123     add_element_stream (decoder->source, decoder);
       
  1124     return TRUE;
       
  1125   }
       
  1126   if (is_dynamic) {
       
  1127     GST_DEBUG_OBJECT (decoder, "Source has dynamic output pads");
       
  1128     /* connect a handler for the new-pad signal */
       
  1129     decoder->src_np_sig_id =
       
  1130         g_signal_connect (G_OBJECT (decoder->source), "pad-added",
       
  1131         G_CALLBACK (source_new_pad), decoder);
       
  1132     decoder->src_nmp_sig_id =
       
  1133         g_signal_connect (G_OBJECT (decoder->source), "no-more-pads",
       
  1134         G_CALLBACK (source_no_more_pads), decoder);
       
  1135     g_object_set_data (G_OBJECT (decoder->source), "pending", "1");
       
  1136     decoder->pending++;
       
  1137   } else {
       
  1138     GstElement *dec_elem;
       
  1139 
       
  1140     GST_DEBUG_OBJECT (decoder, "Pluggin decodebin to source");
       
  1141 
       
  1142     /* no dynamic source, we can link now */
       
  1143     dec_elem = make_decoder (decoder, decoder->is_stream);
       
  1144     if (!dec_elem)
       
  1145       goto no_decoder;
       
  1146 
       
  1147     if (!gst_element_link (decoder->source, dec_elem))
       
  1148       goto could_not_link;
       
  1149   }
       
  1150   return TRUE;
       
  1151 
       
  1152   /* ERRORS */
       
  1153 no_source:
       
  1154   {
       
  1155     /* error message was already posted */
       
  1156     return FALSE;
       
  1157   }
       
  1158 invalid_source:
       
  1159   {
       
  1160     GST_ELEMENT_ERROR (decoder, CORE, FAILED,
       
  1161         (_("Source element is invalid.")), (NULL));
       
  1162     return FALSE;
       
  1163   }
       
  1164 no_decoder:
       
  1165   {
       
  1166     /* message was posted */
       
  1167     return FALSE;
       
  1168   }
       
  1169 could_not_link:
       
  1170   {
       
  1171     GST_ELEMENT_ERROR (decoder, CORE, NEGOTIATION,
       
  1172         (NULL), ("Can't link source to decoder element"));
       
  1173     return FALSE;
       
  1174   }
       
  1175 }
       
  1176 
       
  1177 static void
       
  1178 value_list_append_structure_list (GValue * list_val, GstStructure ** first,
       
  1179     GList * structure_list)
       
  1180 {
       
  1181   GList *l;
       
  1182 
       
  1183   for (l = structure_list; l != NULL; l = l->next) {
       
  1184     GValue val = { 0, };
       
  1185 
       
  1186     if (*first == NULL)
       
  1187       *first = gst_structure_copy ((GstStructure *) l->data);
       
  1188 
       
  1189     g_value_init (&val, GST_TYPE_STRUCTURE);
       
  1190     g_value_take_boxed (&val, gst_structure_copy ((GstStructure *) l->data));
       
  1191     gst_value_list_append_value (list_val, &val);
       
  1192     g_value_unset (&val);
       
  1193   }
       
  1194 }
       
  1195 
       
  1196 /* if it's a redirect message with multiple redirect locations we might
       
  1197  * want to pick a different 'best' location depending on the required
       
  1198  * bitrates and the connection speed */
       
  1199 static GstMessage *
       
  1200 handle_redirect_message (GstURIDecodeBin * dec, GstMessage * msg)
       
  1201 {
       
  1202   const GValue *locations_list, *location_val;
       
  1203   GstMessage *new_msg;
       
  1204   GstStructure *new_structure = NULL;
       
  1205   GList *l_good = NULL, *l_neutral = NULL, *l_bad = NULL;
       
  1206   GValue new_list = { 0, };
       
  1207   guint size, i;
       
  1208 
       
  1209   GST_DEBUG_OBJECT (dec, "redirect message: %" GST_PTR_FORMAT, msg);
       
  1210   GST_DEBUG_OBJECT (dec, "connection speed: %u", dec->connection_speed);
       
  1211 
       
  1212   if (dec->connection_speed == 0 || msg->structure == NULL)
       
  1213     return msg;
       
  1214 
       
  1215   locations_list = gst_structure_get_value (msg->structure, "locations");
       
  1216   if (locations_list == NULL)
       
  1217     return msg;
       
  1218 
       
  1219   size = gst_value_list_get_size (locations_list);
       
  1220   if (size < 2)
       
  1221     return msg;
       
  1222 
       
  1223   /* maintain existing order as much as possible, just sort references
       
  1224    * with too high a bitrate to the end (the assumption being that if
       
  1225    * bitrates are given they are given for all interesting streams and
       
  1226    * that the you-need-at-least-version-xyz redirect has the same bitrate
       
  1227    * as the lowest referenced redirect alternative) */
       
  1228   for (i = 0; i < size; ++i) {
       
  1229     const GstStructure *s;
       
  1230     gint bitrate = 0;
       
  1231 
       
  1232     location_val = gst_value_list_get_value (locations_list, i);
       
  1233     s = (const GstStructure *) g_value_get_boxed (location_val);
       
  1234     if (!gst_structure_get_int (s, "minimum-bitrate", &bitrate) || bitrate <= 0) {
       
  1235       GST_DEBUG_OBJECT (dec, "no bitrate: %" GST_PTR_FORMAT, s);
       
  1236       l_neutral = g_list_append (l_neutral, (gpointer) s);
       
  1237     } else if (bitrate > dec->connection_speed) {
       
  1238       GST_DEBUG_OBJECT (dec, "bitrate too high: %" GST_PTR_FORMAT, s);
       
  1239       l_bad = g_list_append (l_bad, (gpointer) s);
       
  1240     } else if (bitrate <= dec->connection_speed) {
       
  1241       GST_DEBUG_OBJECT (dec, "bitrate OK: %" GST_PTR_FORMAT, s);
       
  1242       l_good = g_list_append (l_good, (gpointer) s);
       
  1243     }
       
  1244   }
       
  1245 
       
  1246   g_value_init (&new_list, GST_TYPE_LIST);
       
  1247   value_list_append_structure_list (&new_list, &new_structure, l_good);
       
  1248   value_list_append_structure_list (&new_list, &new_structure, l_neutral);
       
  1249   value_list_append_structure_list (&new_list, &new_structure, l_bad);
       
  1250   gst_structure_set_value (new_structure, "locations", &new_list);
       
  1251   g_value_unset (&new_list);
       
  1252 
       
  1253   g_list_free (l_good);
       
  1254   g_list_free (l_neutral);
       
  1255   g_list_free (l_bad);
       
  1256 
       
  1257   new_msg = gst_message_new_element (msg->src, new_structure);
       
  1258   gst_message_unref (msg);
       
  1259 
       
  1260   GST_DEBUG_OBJECT (dec, "new redirect message: %" GST_PTR_FORMAT, new_msg);
       
  1261   return new_msg;
       
  1262 }
       
  1263 
       
  1264 static void
       
  1265 handle_message (GstBin * bin, GstMessage * msg)
       
  1266 {
       
  1267   if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ELEMENT && msg->structure != NULL
       
  1268       && gst_structure_has_name (msg->structure, "redirect")) {
       
  1269     /* sort redirect messages based on the connection speed. This simplifies
       
  1270      * the user of this element as it can in most cases just pick the first item
       
  1271      * of the sorted list as a good redirection candidate. It can of course
       
  1272      * choose something else from the list if it has a better way. */
       
  1273     msg = handle_redirect_message (GST_URI_DECODE_BIN (bin), msg);
       
  1274   }
       
  1275   GST_BIN_CLASS (parent_class)->handle_message (bin, msg);
       
  1276 }
       
  1277 
       
  1278 /* generic struct passed to all query fold methods
       
  1279  * FIXME, move to core.
       
  1280  */
       
  1281 typedef struct
       
  1282 {
       
  1283   GstQuery *query;
       
  1284   gint64 min;
       
  1285   gint64 max;
       
  1286   gboolean seekable;
       
  1287   gboolean live;
       
  1288 } QueryFold;
       
  1289 
       
  1290 typedef void (*QueryInitFunction) (GstURIDecodeBin * dec, QueryFold * fold);
       
  1291 typedef void (*QueryDoneFunction) (GstURIDecodeBin * dec, QueryFold * fold);
       
  1292 
       
  1293 /* for duration/position we collect all durations/positions and take
       
  1294  * the MAX of all valid results */
       
  1295 static void
       
  1296 decoder_query_init (GstURIDecodeBin * dec, QueryFold * fold)
       
  1297 {
       
  1298   fold->min = 0;
       
  1299   fold->max = -1;
       
  1300   fold->seekable = TRUE;
       
  1301   fold->live = 0;
       
  1302 }
       
  1303 
       
  1304 static gboolean
       
  1305 decoder_query_duration_fold (GstPad * item, GValue * ret, QueryFold * fold)
       
  1306 {
       
  1307   if (gst_pad_query (item, fold->query)) {
       
  1308     gint64 duration;
       
  1309 
       
  1310     g_value_set_boolean (ret, TRUE);
       
  1311 
       
  1312     gst_query_parse_duration (fold->query, NULL, &duration);
       
  1313 
       
  1314     GST_DEBUG_OBJECT (item, "got duration %" G_GINT64_FORMAT, duration);
       
  1315 
       
  1316     if (duration > fold->max)
       
  1317       fold->max = duration;
       
  1318   }
       
  1319   gst_object_unref (item);
       
  1320   return TRUE;
       
  1321 }
       
  1322 static void
       
  1323 decoder_query_duration_done (GstURIDecodeBin * dec, QueryFold * fold)
       
  1324 {
       
  1325   GstFormat format;
       
  1326 
       
  1327   gst_query_parse_duration (fold->query, &format, NULL);
       
  1328   /* store max in query result */
       
  1329   gst_query_set_duration (fold->query, format, fold->max);
       
  1330 
       
  1331   GST_DEBUG ("max duration %" G_GINT64_FORMAT, fold->max);
       
  1332 }
       
  1333 
       
  1334 static gboolean
       
  1335 decoder_query_position_fold (GstPad * item, GValue * ret, QueryFold * fold)
       
  1336 {
       
  1337   if (gst_pad_query (item, fold->query)) {
       
  1338     gint64 position;
       
  1339 
       
  1340     g_value_set_boolean (ret, TRUE);
       
  1341 
       
  1342     gst_query_parse_position (fold->query, NULL, &position);
       
  1343 
       
  1344     GST_DEBUG_OBJECT (item, "got position %" G_GINT64_FORMAT, position);
       
  1345 
       
  1346     if (position > fold->max)
       
  1347       fold->max = position;
       
  1348   }
       
  1349 
       
  1350   gst_object_unref (item);
       
  1351   return TRUE;
       
  1352 }
       
  1353 static void
       
  1354 decoder_query_position_done (GstURIDecodeBin * dec, QueryFold * fold)
       
  1355 {
       
  1356   GstFormat format;
       
  1357 
       
  1358   gst_query_parse_position (fold->query, &format, NULL);
       
  1359   /* store max in query result */
       
  1360   gst_query_set_position (fold->query, format, fold->max);
       
  1361 
       
  1362   GST_DEBUG_OBJECT (dec, "max position %" G_GINT64_FORMAT, fold->max);
       
  1363 }
       
  1364 
       
  1365 static gboolean
       
  1366 decoder_query_latency_fold (GstPad * item, GValue * ret, QueryFold * fold)
       
  1367 {
       
  1368   if (gst_pad_query (item, fold->query)) {
       
  1369     GstClockTime min, max;
       
  1370     gboolean live;
       
  1371 
       
  1372     g_value_set_boolean (ret, TRUE);
       
  1373 
       
  1374     gst_query_parse_latency (fold->query, &live, &min, &max);
       
  1375 
       
  1376     GST_DEBUG_OBJECT (item,
       
  1377         "got latency min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT
       
  1378         ", live %d", GST_TIME_ARGS (min), GST_TIME_ARGS (max), live);
       
  1379 
       
  1380     /* for the combined latency we collect the MAX of all min latencies and
       
  1381      * the MIN of all max latencies */
       
  1382     if (min > fold->min)
       
  1383       fold->min = min;
       
  1384     if (fold->max == -1)
       
  1385       fold->max = max;
       
  1386     else if (max < fold->max)
       
  1387       fold->max = max;
       
  1388     if (fold->live == FALSE)
       
  1389       fold->live = live;
       
  1390   }
       
  1391 
       
  1392   gst_object_unref (item);
       
  1393   return TRUE;
       
  1394 }
       
  1395 static void
       
  1396 decoder_query_latency_done (GstURIDecodeBin * dec, QueryFold * fold)
       
  1397 {
       
  1398   /* store max in query result */
       
  1399   gst_query_set_latency (fold->query, fold->live, fold->min, fold->max);
       
  1400 
       
  1401   GST_DEBUG_OBJECT (dec,
       
  1402       "latency min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT
       
  1403       ", live %d", GST_TIME_ARGS (fold->min), GST_TIME_ARGS (fold->max),
       
  1404       fold->live);
       
  1405 }
       
  1406 
       
  1407 /* we are seekable if all srcpads are seekable */
       
  1408 static gboolean
       
  1409 decoder_query_seeking_fold (GstPad * item, GValue * ret, QueryFold * fold)
       
  1410 {
       
  1411   if (gst_pad_query (item, fold->query)) {
       
  1412     gboolean seekable;
       
  1413 
       
  1414     g_value_set_boolean (ret, TRUE);
       
  1415     gst_query_parse_seeking (fold->query, NULL, &seekable, NULL, NULL);
       
  1416 
       
  1417     GST_DEBUG_OBJECT (item, "got seekable %d", seekable);
       
  1418 
       
  1419     if (fold->seekable == TRUE)
       
  1420       fold->seekable = seekable;
       
  1421   }
       
  1422   gst_object_unref (item);
       
  1423 
       
  1424   return TRUE;
       
  1425 }
       
  1426 static void
       
  1427 decoder_query_seeking_done (GstURIDecodeBin * dec, QueryFold * fold)
       
  1428 {
       
  1429   GstFormat format;
       
  1430 
       
  1431   gst_query_parse_seeking (fold->query, &format, NULL, NULL, NULL);
       
  1432   gst_query_set_seeking (fold->query, format, fold->seekable, 0, -1);
       
  1433 
       
  1434   GST_DEBUG_OBJECT (dec, "seekable %d", fold->seekable);
       
  1435 }
       
  1436 
       
  1437 /* generic fold, return first valid result */
       
  1438 static gboolean
       
  1439 decoder_query_generic_fold (GstPad * item, GValue * ret, QueryFold * fold)
       
  1440 {
       
  1441   gboolean res;
       
  1442 
       
  1443   if ((res = gst_pad_query (item, fold->query))) {
       
  1444     g_value_set_boolean (ret, TRUE);
       
  1445     GST_DEBUG_OBJECT (item, "answered query %p", fold->query);
       
  1446   }
       
  1447 
       
  1448   gst_object_unref (item);
       
  1449 
       
  1450   /* and stop as soon as we have a valid result */
       
  1451   return !res;
       
  1452 }
       
  1453 
       
  1454 
       
  1455 /* we're a bin, the default query handler iterates sink elements, which we don't
       
  1456  * have normally. We should just query all source pads.
       
  1457  */
       
  1458 static gboolean
       
  1459 gst_uri_decode_bin_query (GstElement * element, GstQuery * query)
       
  1460 {
       
  1461   GstURIDecodeBin *decoder;
       
  1462   gboolean res = FALSE;
       
  1463   GstIterator *iter;
       
  1464   GstIteratorFoldFunction fold_func;
       
  1465   QueryInitFunction fold_init = NULL;
       
  1466   QueryDoneFunction fold_done = NULL;
       
  1467   QueryFold fold_data;
       
  1468   GValue ret = { 0 };
       
  1469 
       
  1470   decoder = GST_URI_DECODE_BIN (element);
       
  1471 
       
  1472   switch (GST_QUERY_TYPE (query)) {
       
  1473     case GST_QUERY_DURATION:
       
  1474       /* iterate and collect durations */
       
  1475       fold_func = (GstIteratorFoldFunction) decoder_query_duration_fold;
       
  1476       fold_init = decoder_query_init;
       
  1477       fold_done = decoder_query_duration_done;
       
  1478       break;
       
  1479     case GST_QUERY_POSITION:
       
  1480       /* iterate and collect durations */
       
  1481       fold_func = (GstIteratorFoldFunction) decoder_query_position_fold;
       
  1482       fold_init = decoder_query_init;
       
  1483       fold_done = decoder_query_position_done;
       
  1484       break;
       
  1485     case GST_QUERY_LATENCY:
       
  1486       /* iterate and collect durations */
       
  1487       fold_func = (GstIteratorFoldFunction) decoder_query_latency_fold;
       
  1488       fold_init = decoder_query_init;
       
  1489       fold_done = decoder_query_latency_done;
       
  1490       break;
       
  1491     case GST_QUERY_SEEKING:
       
  1492       /* iterate and collect durations */
       
  1493       fold_func = (GstIteratorFoldFunction) decoder_query_seeking_fold;
       
  1494       fold_init = decoder_query_init;
       
  1495       fold_done = decoder_query_seeking_done;
       
  1496       break;
       
  1497     default:
       
  1498       fold_func = (GstIteratorFoldFunction) decoder_query_generic_fold;
       
  1499       break;
       
  1500   }
       
  1501 
       
  1502   fold_data.query = query;
       
  1503 
       
  1504   g_value_init (&ret, G_TYPE_BOOLEAN);
       
  1505   g_value_set_boolean (&ret, FALSE);
       
  1506 
       
  1507   iter = gst_element_iterate_src_pads (element);
       
  1508   GST_DEBUG_OBJECT (element, "Sending query %p (type %d) to src pads",
       
  1509       query, GST_QUERY_TYPE (query));
       
  1510 
       
  1511   if (fold_init)
       
  1512     fold_init (decoder, &fold_data);
       
  1513 
       
  1514   while (TRUE) {
       
  1515     GstIteratorResult ires;
       
  1516 
       
  1517     ires = gst_iterator_fold (iter, fold_func, &ret, &fold_data);
       
  1518 
       
  1519     switch (ires) {
       
  1520       case GST_ITERATOR_RESYNC:
       
  1521         gst_iterator_resync (iter);
       
  1522         if (fold_init)
       
  1523           fold_init (decoder, &fold_data);
       
  1524         g_value_set_boolean (&ret, FALSE);
       
  1525         break;
       
  1526       case GST_ITERATOR_OK:
       
  1527       case GST_ITERATOR_DONE:
       
  1528         res = g_value_get_boolean (&ret);
       
  1529         if (fold_done != NULL && res)
       
  1530           fold_done (decoder, &fold_data);
       
  1531         goto done;
       
  1532       default:
       
  1533         res = FALSE;
       
  1534         goto done;
       
  1535     }
       
  1536   }
       
  1537 done:
       
  1538   gst_iterator_free (iter);
       
  1539 
       
  1540   return res;
       
  1541 }
       
  1542 
       
  1543 static GstStateChangeReturn
       
  1544 gst_uri_decode_bin_change_state (GstElement * element,
       
  1545     GstStateChange transition)
       
  1546 {
       
  1547   GstStateChangeReturn ret;
       
  1548   GstURIDecodeBin *decoder;
       
  1549 
       
  1550   decoder = GST_URI_DECODE_BIN (element);
       
  1551 
       
  1552   switch (transition) {
       
  1553     case GST_STATE_CHANGE_READY_TO_PAUSED:
       
  1554       if (!setup_source (decoder))
       
  1555         goto source_failed;
       
  1556       break;
       
  1557     default:
       
  1558       break;
       
  1559   }
       
  1560 
       
  1561   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
       
  1562 
       
  1563   switch (transition) {
       
  1564     case GST_STATE_CHANGE_READY_TO_PAUSED:
       
  1565       GST_DEBUG ("ready to paused");
       
  1566       if (ret == GST_STATE_CHANGE_FAILURE)
       
  1567         goto setup_failed;
       
  1568       break;
       
  1569     case GST_STATE_CHANGE_PAUSED_TO_READY:
       
  1570       GST_DEBUG ("paused to ready");
       
  1571       remove_decoders (decoder);
       
  1572       remove_pads (decoder);
       
  1573       remove_source (decoder);
       
  1574       break;
       
  1575     default:
       
  1576       break;
       
  1577   }
       
  1578   return ret;
       
  1579 
       
  1580   /* ERRORS */
       
  1581 source_failed:
       
  1582   {
       
  1583     return GST_STATE_CHANGE_FAILURE;
       
  1584   }
       
  1585 setup_failed:
       
  1586   {
       
  1587     /* clean up leftover groups */
       
  1588     return GST_STATE_CHANGE_FAILURE;
       
  1589   }
       
  1590 }
       
  1591 
       
  1592 gboolean gst_decode_bin_plugin_init (GstPlugin * plugin);
       
  1593 
       
  1594 static gboolean
       
  1595 gst_uri_decode_bin_plugin_init (GstPlugin * plugin)
       
  1596 {
       
  1597   GST_DEBUG_CATEGORY_INIT (gst_uri_decode_bin_debug, "uridecodebin", 0,
       
  1598       "URI decoder element");
       
  1599 
       
  1600 #ifdef ENABLE_NLS
       
  1601   GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
       
  1602       LOCALEDIR);
       
  1603   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
       
  1604 #endif /* ENABLE_NLS */
       
  1605 
       
  1606   return gst_element_register (plugin, "uridecodebin", GST_RANK_NONE,
       
  1607       GST_TYPE_URI_DECODE_BIN);
       
  1608 }
       
  1609 
       
  1610 static gboolean
       
  1611 plugin_init (GstPlugin * plugin)
       
  1612 {
       
  1613   if (!gst_decode_bin_plugin_init (plugin))
       
  1614     return FALSE;
       
  1615   if (!gst_uri_decode_bin_plugin_init (plugin))
       
  1616     return FALSE;
       
  1617 
       
  1618   return TRUE;
       
  1619 }
       
  1620 
       
  1621 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
       
  1622     GST_VERSION_MINOR,
       
  1623     "uridecodebin",
       
  1624     "URI Decoder bin", plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME,
       
  1625     GST_PACKAGE_ORIGIN);
       
  1626     
       
  1627 #ifdef __SYMBIAN32__
       
  1628 EXPORT_C 
       
  1629 #endif
       
  1630 GstPluginDesc* _GST_PLUGIN_DESC()
       
  1631 {
       
  1632     return &gst_plugin_desc;
       
  1633 }