diff -r 567bb019e3e3 -r 7e817e7e631c gst_plugins_base/gst/playback/gsturidecodebin.c --- a/gst_plugins_base/gst/playback/gsturidecodebin.c Tue Aug 31 15:30:33 2010 +0300 +++ b/gst_plugins_base/gst/playback/gsturidecodebin.c Wed Sep 01 12:16:41 2010 +0100 @@ -19,6 +19,7 @@ /** * SECTION:element-uridecodebin + * @short_description: decoder for an uri * * Decodes data from a URI into raw media. */ @@ -32,10 +33,12 @@ #include #include -#include "gstfactorylists.h" #include "gstplay-marshal.h" #include "gstplay-enum.h" +#ifdef __SYMBIAN32__ +#include +#endif #define GST_TYPE_URI_DECODE_BIN \ (gst_uri_decode_bin_get_type()) #define GST_URI_DECODE_BIN(obj) \ @@ -46,43 +49,23 @@ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_URI_DECODE_BIN)) #define GST_IS_URI_DECODE_BIN_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_URI_DECODE_BIN)) -#define GST_URI_DECODE_BIN_CAST(obj) ((GstURIDecodeBin *) (obj)) typedef struct _GstURIDecodeBin GstURIDecodeBin; typedef struct _GstURIDecodeBinClass GstURIDecodeBinClass; -#define GST_URI_DECODE_BIN_GET_LOCK(dec) (((GstURIDecodeBin*)(dec))->lock) -#define GST_URI_DECODE_BIN_LOCK(dec) (g_mutex_lock(GST_URI_DECODE_BIN_GET_LOCK(dec))) -#define GST_URI_DECODE_BIN_UNLOCK(dec) (g_mutex_unlock(GST_URI_DECODE_BIN_GET_LOCK(dec))) - -/** - * GstURIDecodeBin - * - * uridecodebin element struct - */ struct _GstURIDecodeBin { GstBin parent_instance; - GMutex *lock; /* lock for constructing */ - - GValueArray *factories; /* factories we can use for selecting elements */ - gchar *uri; guint connection_speed; GstCaps *caps; gchar *encoding; gboolean is_stream; - gboolean need_queue; - guint64 buffer_duration; /* When streaming, buffer duration (ns) */ - guint buffer_size; /* When streaming, buffer size (bytes) */ - gboolean download; - GstElement *source; - GstElement *typefind; - guint have_type_id; /* have-type signal id from typefind */ - GSList *decodebins; + GstElement *queue; + GSList *decoders; GSList *srcpads; gint numpads; @@ -90,8 +73,6 @@ guint src_np_sig_id; /* new-pad signal id */ guint src_nmp_sig_id; /* no-more-pads signal id */ gint pending; - - gboolean async_pending; /* async-start has been emited */ }; struct _GstURIDecodeBinClass @@ -142,25 +123,17 @@ /* properties */ #define DEFAULT_PROP_URI NULL -#define DEFAULT_PROP_SOURCE NULL #define DEFAULT_CONNECTION_SPEED 0 #define DEFAULT_CAPS NULL #define DEFAULT_SUBTITLE_ENCODING NULL -#define DEFAULT_BUFFER_DURATION -1 -#define DEFAULT_BUFFER_SIZE -1 -#define DEFAULT_DOWNLOAD FALSE enum { PROP_0, PROP_URI, - PROP_SOURCE, PROP_CONNECTION_SPEED, PROP_CAPS, PROP_SUBTITLE_ENCODING, - PROP_BUFFER_SIZE, - PROP_BUFFER_DURATION, - PROP_DOWNLOAD, PROP_LAST }; @@ -239,25 +212,6 @@ return TRUE; } -static GValueArray * -gst_uri_decode_bin_autoplug_factories (GstElement * element, GstPad * pad, - GstCaps * caps) -{ - GValueArray *result; - - GST_DEBUG_OBJECT (element, "finding factories"); - - /* return all compatible factories for caps */ - result = - gst_factory_list_filter (GST_URI_DECODE_BIN_CAST (element)->factories, - caps); - - GST_DEBUG_OBJECT (element, "autoplug-factories returns %p", result); - - return result; -} - - static void gst_uri_decode_bin_class_init (GstURIDecodeBinClass * klass) { @@ -275,52 +229,28 @@ g_object_class_install_property (gobject_class, PROP_URI, g_param_spec_string ("uri", "URI", "URI to decode", - DEFAULT_PROP_URI, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_SOURCE, - g_param_spec_object ("source", "Source", "Source object used", - GST_TYPE_ELEMENT, G_PARAM_READABLE)); + DEFAULT_PROP_URI, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_CONNECTION_SPEED, g_param_spec_uint ("connection-speed", "Connection Speed", "Network connection speed in kbps (0 = unknown)", - 0, G_MAXUINT / 1000, DEFAULT_CONNECTION_SPEED, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + 0, G_MAXUINT, DEFAULT_CONNECTION_SPEED, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_CAPS, g_param_spec_boxed ("caps", "Caps", "The caps on which to stop decoding. (NULL = default)", - GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + GST_TYPE_CAPS, G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_SUBTITLE_ENCODING, g_param_spec_string ("subtitle-encoding", "subtitle encoding", "Encoding to assume if input subtitles are not in UTF-8 encoding. " "If not set, the GST_SUBTITLE_ENCODING environment variable will " "be checked for an encoding to use. If that is not set either, " - "ISO-8859-15 will be assumed.", NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE, - g_param_spec_int ("buffer-size", "Buffer size (bytes)", - "Buffer size when buffering network streams", - -1, G_MAXINT, DEFAULT_BUFFER_SIZE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_BUFFER_DURATION, - g_param_spec_int64 ("buffer-duration", "Buffer duration (ns)", - "Buffer duration when buffering network streams", - -1, G_MAXINT64, DEFAULT_BUFFER_DURATION, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_DOWNLOAD, - g_param_spec_boolean ("download", "Download", - "Attempt download buffering when buffering network streams", - DEFAULT_DOWNLOAD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + "ISO-8859-15 will be assumed.", NULL, G_PARAM_READWRITE)); /** * GstURIDecodeBin::unknown-type: - * @bin: The uridecodebin - * @pad: the new pad containing caps that cannot be resolved to a 'final' - * stream type. + * @pad: the new pad containing caps that cannot be resolved to a 'final' stream type. * @caps: the #GstCaps of the pad that cannot be resolved. * * This signal is emitted when a pad for which there is no further possible @@ -329,12 +259,11 @@ gst_uri_decode_bin_signals[SIGNAL_UNKNOWN_TYPE] = g_signal_new ("unknown-type", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass, unknown_type), - NULL, NULL, gst_marshal_VOID__OBJECT_BOXED, G_TYPE_NONE, 2, + NULL, NULL, gst_marshal_VOID__OBJECT_OBJECT, G_TYPE_NONE, 2, GST_TYPE_PAD, GST_TYPE_CAPS); /** * GstURIDecodeBin::autoplug-continue: - * @bin: The uridecodebin * @pad: The #GstPad. * @caps: The #GstCaps found. * @@ -350,23 +279,16 @@ g_signal_new ("autoplug-continue", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass, autoplug_continue), _gst_boolean_accumulator, NULL, - gst_play_marshal_BOOLEAN__OBJECT_BOXED, G_TYPE_BOOLEAN, 2, GST_TYPE_PAD, + gst_play_marshal_BOOLEAN__OBJECT_OBJECT, G_TYPE_BOOLEAN, 2, GST_TYPE_PAD, GST_TYPE_CAPS); /** * GstURIDecodeBin::autoplug-factories: - * @bin: The decodebin * @pad: The #GstPad. * @caps: The #GstCaps found. * * This function is emited when an array of possible factories for @caps on - * @pad is needed. Uridecodebin will by default return an array with all - * compatible factories, sorted by rank. - * - * If this function returns NULL, @pad will be exposed as a final caps. - * - * If this function returns an empty array, the pad will be considered as - * having an unhandled type media type. + * @pad is needed. Decodebin2 will by default return * * Returns: a #GValueArray* with a list of factories to try. The factories are * by default tried in the returned order or based on the index returned by @@ -376,40 +298,29 @@ g_signal_new ("autoplug-factories", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass, autoplug_factories), _gst_array_accumulator, NULL, - gst_play_marshal_BOXED__OBJECT_BOXED, G_TYPE_VALUE_ARRAY, 2, + gst_play_marshal_BOXED__OBJECT_OBJECT, G_TYPE_VALUE_ARRAY, 2, GST_TYPE_PAD, GST_TYPE_CAPS); /** * GstURIDecodeBin::autoplug-select: * @pad: The #GstPad. * @caps: The #GstCaps. - * @factory: A #GstElementFactory to use + * @factories: A #GValueArray of possible #GstElementFactory to use, sorted by + * rank (higher ranks come first). * * This signal is emitted once uridecodebin has found all the possible - * #GstElementFactory that can be used to handle the given @caps. For each of - * those factories, this signal is emited. - * - * The signal handler should return a #GST_TYPE_AUTOPLUG_SELECT_RESULT enum - * value indicating what decodebin2 should do next. - * - * A value of #GST_AUTOPLUG_SELECT_TRY will try to autoplug an element from - * @factory. + * #GstElementFactory that can be used to handle the given @caps. * - * A value of #GST_AUTOPLUG_SELECT_EXPOSE will expose @pad without plugging - * any element to it. - * - * A value of #GST_AUTOPLUG_SELECT_SKIP will skip @factory and move to the - * next factory. - * - * Returns: a #GST_TYPE_AUTOPLUG_SELECT_RESULT that indicates the required - * operation. The default handler will always return - * #GST_AUTOPLUG_SELECT_TRY. + * Returns: A #gint indicating what factory index from the @factories array + * that you wish uridecodebin to use for trying to decode the given @caps. + * -1 to stop selection of a factory. The default handler always + * returns the first possible factory. */ gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT] = g_signal_new ("autoplug-select", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass, autoplug_select), _gst_select_accumulator, NULL, - gst_play_marshal_ENUM__OBJECT_BOXED_OBJECT, + gst_play_marshal_ENUM__OBJECT_OBJECT_OBJECT, GST_TYPE_AUTOPLUG_SELECT_RESULT, 3, GST_TYPE_PAD, GST_TYPE_CAPS, GST_TYPE_ELEMENT_FACTORY); @@ -432,26 +343,15 @@ klass->autoplug_continue = GST_DEBUG_FUNCPTR (gst_uri_decode_bin_autoplug_continue); - klass->autoplug_factories = - GST_DEBUG_FUNCPTR (gst_uri_decode_bin_autoplug_factories); } static void gst_uri_decode_bin_init (GstURIDecodeBin * dec, GstURIDecodeBinClass * klass) { - /* first filter out the interesting element factories */ - dec->factories = gst_factory_list_get_elements (GST_FACTORY_LIST_DECODER); - - dec->lock = g_mutex_new (); - dec->uri = g_strdup (DEFAULT_PROP_URI); dec->connection_speed = DEFAULT_CONNECTION_SPEED; dec->caps = DEFAULT_CAPS; dec->encoding = g_strdup (DEFAULT_SUBTITLE_ENCODING); - - dec->buffer_duration = DEFAULT_BUFFER_DURATION; - dec->buffer_size = DEFAULT_BUFFER_SIZE; - dec->download = DEFAULT_DOWNLOAD; } static void @@ -459,40 +359,13 @@ { GstURIDecodeBin *dec = GST_URI_DECODE_BIN (obj); - g_mutex_free (dec->lock); g_free (dec->uri); g_free (dec->encoding); - if (dec->factories) - g_value_array_free (dec->factories); - if (dec->caps) - gst_caps_unref (dec->caps); G_OBJECT_CLASS (parent_class)->finalize (obj); } static void -gst_uri_decode_bin_set_encoding (GstURIDecodeBin * dec, const gchar * encoding) -{ - GSList *walk; - - GST_URI_DECODE_BIN_LOCK (dec); - - /* set property first */ - GST_OBJECT_LOCK (dec); - g_free (dec->encoding); - dec->encoding = g_strdup (encoding); - GST_OBJECT_UNLOCK (dec); - - /* set the property on all decodebins now */ - for (walk = dec->decodebins; walk; walk = g_slist_next (walk)) { - GObject *decodebin = G_OBJECT (walk->data); - - g_object_set (decodebin, "subtitle-encoding", encoding, NULL); - } - GST_URI_DECODE_BIN_UNLOCK (dec); -} - -static void gst_uri_decode_bin_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { @@ -518,16 +391,10 @@ GST_OBJECT_UNLOCK (dec); break; case PROP_SUBTITLE_ENCODING: - gst_uri_decode_bin_set_encoding (dec, g_value_get_string (value)); - break; - case PROP_BUFFER_SIZE: - dec->buffer_size = g_value_get_int (value); - break; - case PROP_BUFFER_DURATION: - dec->buffer_duration = g_value_get_int64 (value); - break; - case PROP_DOWNLOAD: - dec->download = g_value_get_boolean (value); + GST_OBJECT_LOCK (dec); + g_free (dec->encoding); + dec->encoding = g_value_dup_string (value); + GST_OBJECT_UNLOCK (dec); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -547,11 +414,6 @@ g_value_set_string (value, dec->uri); GST_OBJECT_UNLOCK (dec); break; - case PROP_SOURCE: - GST_OBJECT_LOCK (dec); - g_value_set_object (value, dec->source); - GST_OBJECT_UNLOCK (dec); - break; case PROP_CONNECTION_SPEED: GST_OBJECT_LOCK (dec); g_value_set_uint (value, dec->connection_speed / 1000); @@ -567,50 +429,12 @@ g_value_set_string (value, dec->encoding); GST_OBJECT_UNLOCK (dec); break; - case PROP_BUFFER_SIZE: - GST_OBJECT_LOCK (dec); - g_value_set_int (value, dec->buffer_size); - GST_OBJECT_UNLOCK (dec); - break; - case PROP_BUFFER_DURATION: - GST_OBJECT_LOCK (dec); - g_value_set_int64 (value, dec->buffer_duration); - GST_OBJECT_UNLOCK (dec); - break; - case PROP_DOWNLOAD: - g_value_set_boolean (value, dec->download); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } -static void -do_async_start (GstURIDecodeBin * dbin) -{ - GstMessage *message; - - dbin->async_pending = TRUE; - - message = gst_message_new_async_start (GST_OBJECT_CAST (dbin), FALSE); - parent_class->handle_message (GST_BIN_CAST (dbin), message); -} - -static void -do_async_done (GstURIDecodeBin * dbin) -{ - GstMessage *message; - - if (dbin->async_pending) { - GST_DEBUG_OBJECT (dbin, "posting ASYNC_DONE"); - message = gst_message_new_async_done (GST_OBJECT_CAST (dbin)); - parent_class->handle_message (GST_BIN_CAST (dbin), message); - - dbin->async_pending = FALSE; - } -} - #define DEFAULT_QUEUE_SIZE (3 * GST_SECOND) #define DEFAULT_QUEUE_MIN_THRESHOLD ((DEFAULT_QUEUE_SIZE * 30) / 100) #define DEFAULT_QUEUE_THRESHOLD ((DEFAULT_QUEUE_SIZE * 95) / 100) @@ -650,7 +474,7 @@ /* setup phase */ GST_DEBUG_OBJECT (element, "no more pads, %d pending", decoder->pending); - GST_URI_DECODE_BIN_LOCK (decoder); + GST_OBJECT_LOCK (decoder); final = (decoder->pending == 0); /* nothing pending, we can exit */ @@ -666,7 +490,7 @@ final = (decoder->pending == 0); done: - GST_URI_DECODE_BIN_UNLOCK (decoder); + GST_OBJECT_UNLOCK (decoder); if (final) gst_element_no_more_pads (GST_ELEMENT_CAST (decoder)); @@ -707,10 +531,10 @@ GST_DEBUG_OBJECT (element, "new decoded pad, name: <%s>. Last: %d", GST_PAD_NAME (pad), last); - GST_URI_DECODE_BIN_LOCK (decoder); + GST_OBJECT_LOCK (decoder); padname = g_strdup_printf ("src%d", decoder->numpads); decoder->numpads++; - GST_URI_DECODE_BIN_UNLOCK (decoder); + GST_OBJECT_UNLOCK (decoder); newpad = gst_ghost_pad_new (padname, pad); g_free (padname); @@ -730,10 +554,6 @@ GST_DEBUG_OBJECT (element, "pad removed name: <%s:%s>", GST_DEBUG_PAD_NAME (pad)); - /* we only care about srcpads */ - if (!GST_PAD_IS_SRC (pad)) - return; - if (!(ghost = g_object_get_data (G_OBJECT (pad), "uridecodebin.ghostpad"))) goto no_ghost; @@ -767,27 +587,12 @@ return FALSE; } -static gboolean -array_has_uri_value (const gchar * values[], const gchar * value) -{ - gint i; - - for (i = 0; values[i]; i++) { - if (!g_ascii_strncasecmp (value, values[i], strlen (values[i]))) - return TRUE; - } - return FALSE; -} - /* list of URIs that we consider to be streams and that need buffering. * We have no mechanism yet to figure this out with a query. */ static const gchar *stream_uris[] = { "http://", "mms://", "mmsh://", - "mmsu://", "mmst://", "fd://", NULL + "mmsu://", "mmst://", NULL }; -/* list of URIs that need a queue because they are pretty bursty */ -static const gchar *queue_uris[] = { "cdda://", NULL }; - /* blacklisted URIs, we know they will always fail. */ static const gchar *blacklisted_uris[] = { NULL }; @@ -799,23 +604,15 @@ }; #endif -/* media types we consider raw media */ -static const gchar *raw_media[] = { - "audio/x-raw", "video/x-raw", "text/plain", "text/x-pango-markup", - "video/x-dvd-subpicture", "subpicture/x-", NULL +/* mime types we consider raw media */ +static const gchar *raw_mimes[] = { + "audio/x-raw", "video/x-raw", NULL }; -/* media types we can download */ -static const gchar *download_media[] = { - "video/quicktime", "video/x-flv", NULL -}; - -#define IS_STREAM_URI(uri) (array_has_uri_value (stream_uris, uri)) -#define IS_QUEUE_URI(uri) (array_has_uri_value (queue_uris, uri)) -#define IS_BLACKLISTED_URI(uri) (array_has_uri_value (blacklisted_uris, uri)) +#define IS_STREAM_URI(uri) (array_has_value (stream_uris, uri)) +#define IS_BLACKLISTED_URI(uri) (array_has_value (blacklisted_uris, uri)) #define IS_NO_MEDIA_MIME(mime) (array_has_value (no_media_mimes, mime)) -#define IS_RAW_MEDIA(media) (array_has_value (raw_media, media)) -#define IS_DOWNLOAD_MEDIA(media) (array_has_value (download_media, media)) +#define IS_RAW_MIME(mime) (array_has_value (raw_mimes, mime)) /* * Generate and configure a source element. @@ -828,8 +625,6 @@ if (!decoder->uri) goto no_uri; - GST_LOG_OBJECT (decoder, "finding source for %s", decoder->uri); - if (!gst_uri_is_valid (decoder->uri)) goto invalid_uri; @@ -840,20 +635,13 @@ if (!source) goto no_source; - GST_LOG_OBJECT (decoder, "found source type %s", G_OBJECT_TYPE_NAME (source)); - decoder->is_stream = IS_STREAM_URI (decoder->uri); - GST_LOG_OBJECT (decoder, "source is stream: %d", decoder->is_stream); - - decoder->need_queue = IS_QUEUE_URI (decoder->uri); - GST_LOG_OBJECT (decoder, "source needs queue: %d", decoder->need_queue); /* make HTTP sources send extra headers so we get icecast * metadata in case the stream is an icecast stream */ if (!strncmp (decoder->uri, "http://", 7) && g_object_class_find_property (G_OBJECT_GET_CLASS (source), "iradio-mode")) { - GST_LOG_OBJECT (decoder, "configuring iradio-mode"); g_object_set (source, "iradio-mode", TRUE, NULL); } @@ -865,13 +653,7 @@ g_object_set (source, "connection-speed", decoder->connection_speed / 1000, NULL); } - if (g_object_class_find_property (G_OBJECT_GET_CLASS (source), - "subtitle-encoding")) { - GST_DEBUG_OBJECT (decoder, - "setting subtitle-encoding=%s to source element", decoder->encoding); - g_object_set (G_OBJECT (source), "subtitle-encoding", decoder->encoding, - NULL); - } + return source; /* ERRORS */ @@ -932,8 +714,6 @@ if (caps == NULL) return FALSE; - GST_DEBUG_OBJECT (pad, "have caps %" GST_PTR_FORMAT, caps); - capssize = gst_caps_get_size (caps); /* no caps, skip and move to the next pad */ if (capssize == 0 || gst_caps_is_empty (caps) || gst_caps_is_any (caps)) @@ -942,14 +722,12 @@ /* count the number of raw formats in the caps */ for (i = 0; i < capssize; ++i) { GstStructure *s; - const gchar *media_type; + const gchar *mime_type; s = gst_caps_get_structure (caps, i); - media_type = gst_structure_get_name (s); + mime_type = gst_structure_get_name (s); - GST_DEBUG_OBJECT (pad, "check media-type %s", media_type); - - if (IS_RAW_MEDIA (media_type)) + if (IS_RAW_MIME (mime_type)) ++num_raw; } @@ -967,7 +745,6 @@ * @is_raw: are all pads raw data * @have_out: does the source have output * @is_dynamic: is this a dynamic source - * @use_queue: put a queue before raw output pads * * Check the source of @decoder and collect information about it. * @@ -984,7 +761,7 @@ */ static gboolean analyse_source (GstURIDecodeBin * decoder, gboolean * is_raw, - gboolean * have_out, gboolean * is_dynamic, gboolean use_queue) + gboolean * have_out, gboolean * is_dynamic) { GstIterator *pads_iter; gboolean done = FALSE; @@ -1017,35 +794,12 @@ *have_out = TRUE; /* if FALSE, this pad has no caps and we continue with the next pad. */ - if (!has_all_raw_caps (pad, is_raw)) { - gst_object_unref (pad); + if (!has_all_raw_caps (pad, is_raw)) break; - } /* caps on source pad are all raw, we can add the pad */ - if (*is_raw) { - GstElement *outelem; - - if (use_queue) { - GstPad *sinkpad; - - /* insert a queue element right before the raw pad */ - outelem = gst_element_factory_make ("queue2", "queue"); - gst_bin_add (GST_BIN_CAST (decoder), outelem); - - sinkpad = gst_element_get_static_pad (outelem, "sink"); - gst_pad_link (pad, sinkpad); - gst_object_unref (sinkpad); - gst_object_unref (pad); - - /* get the new raw srcpad */ - pad = gst_element_get_static_pad (outelem, "src"); - } else { - outelem = decoder->source; - } - new_decoded_pad_cb (outelem, pad, FALSE, decoder); - } - gst_object_unref (pad); + if (*is_raw) + new_decoded_pad_cb (decoder->source, pad, FALSE, decoder); break; } } @@ -1081,15 +835,15 @@ { GSList *walk; - for (walk = bin->decodebins; walk; walk = g_slist_next (walk)) { + for (walk = bin->decoders; walk; walk = g_slist_next (walk)) { GstElement *decoder = GST_ELEMENT_CAST (walk->data); GST_DEBUG_OBJECT (bin, "removing old decoder element"); gst_element_set_state (decoder, GST_STATE_NULL); gst_bin_remove (GST_BIN_CAST (bin), decoder); } - g_slist_free (bin->decodebins); - bin->decodebins = NULL; + g_slist_free (bin->decoders); + bin->decoders = NULL; } static void @@ -1137,7 +891,7 @@ proxy_autoplug_factories_signal (GstElement * element, GstPad * pad, GstCaps * caps, GstURIDecodeBin * dec) { - GValueArray *result; + GValueArray *result = NULL; g_signal_emit (G_OBJECT (dec), gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES], 0, pad, caps, @@ -1172,23 +926,16 @@ gst_uri_decode_bin_signals[SIGNAL_DRAINED], 0, NULL); } -/* make a decodebin and connect to all the signals */ static GstElement * -make_decoder (GstURIDecodeBin * decoder) +make_decoder (GstURIDecodeBin * decoder, gboolean use_queue) { - GstElement *decodebin; - - GST_LOG_OBJECT (decoder, "making new decodebin2"); + GstElement *result, *decodebin; /* now create the decoder element */ decodebin = gst_element_factory_make ("decodebin2", NULL); if (!decodebin) goto no_decodebin; - /* configure caps if we have any */ - if (decoder->caps) - g_object_set (decodebin, "caps", decoder->caps, NULL); - /* connect signals to proxy */ g_signal_connect (G_OBJECT (decodebin), "unknown-type", G_CALLBACK (proxy_unknown_type_signal), decoder); @@ -1201,6 +948,34 @@ g_signal_connect (G_OBJECT (decodebin), "drained", G_CALLBACK (proxy_drained_signal), decoder); + if (use_queue) { + GstElement *queue; + GstPad *gpad, *pad; + + queue = gst_element_factory_make ("queue2", NULL); + if (!queue) + goto no_queue2; + + /* configure the queue as a buffering element */ + g_object_set (G_OBJECT (queue), "use-buffering", TRUE, NULL); + + result = gst_bin_new ("source-bin"); + + gst_bin_add (GST_BIN_CAST (result), queue); + gst_bin_add (GST_BIN_CAST (result), decodebin); + + gst_element_link (queue, decodebin); + + pad = gst_element_get_pad (queue, "sink"); + gpad = gst_ghost_pad_new (GST_PAD_NAME (pad), pad); + gst_object_unref (pad); + + gst_pad_set_active (gpad, TRUE); + gst_element_add_pad (GST_ELEMENT_CAST (result), gpad); + } else { + result = decodebin; + } + /* set up callbacks to create the links between decoded data * and video/audio/subtitle rendering/output. */ g_signal_connect (G_OBJECT (decodebin), @@ -1212,16 +987,13 @@ g_signal_connect (G_OBJECT (decodebin), "unknown-type", G_CALLBACK (unknown_type_cb), decoder); g_object_set_data (G_OBJECT (decodebin), "pending", "1"); - g_object_set (G_OBJECT (decodebin), "subtitle-encoding", decoder->encoding, - NULL); decoder->pending++; - GST_LOG_OBJECT (decoder, "have %d pending dynamic objects", decoder->pending); + + gst_bin_add (GST_BIN_CAST (decoder), result); - gst_bin_add (GST_BIN_CAST (decoder), decodebin); + decoder->decoders = g_slist_prepend (decoder->decoders, result); - decoder->decodebins = g_slist_prepend (decoder->decodebins, decodebin); - - return decodebin; + return result; /* ERRORS */ no_decodebin: @@ -1230,151 +1002,11 @@ (_("Could not create \"decodebin2\" element.")), (NULL)); return NULL; } -} - -static void -type_found (GstElement * typefind, guint probability, - GstCaps * caps, GstURIDecodeBin * decoder) -{ - GstElement *dec_elem, *queue; - GstStructure *s; - const gchar *media_type; - - GST_DEBUG_OBJECT (decoder, "typefind found caps %" GST_PTR_FORMAT, caps); - - dec_elem = make_decoder (decoder); - if (!dec_elem) - goto no_decodebin; - - queue = gst_element_factory_make ("queue2", NULL); - if (!queue) - goto no_queue2; - - g_object_set (G_OBJECT (queue), "use-buffering", TRUE, NULL); - - s = gst_caps_get_structure (caps, 0); - media_type = gst_structure_get_name (s); - - GST_DEBUG_OBJECT (decoder, "check media-type %s, %d", media_type, - decoder->download); - - if (IS_DOWNLOAD_MEDIA (media_type) && decoder->download) { - gchar *temp_template, *filename; - const gchar *tmp_dir, *prgname; - - tmp_dir = g_get_tmp_dir (); - prgname = g_get_prgname (); - if (prgname == NULL) - prgname = "GStreamer"; - - filename = g_strdup_printf ("%s-XXXXXX", prgname); - - /* build our filename */ - temp_template = g_build_filename (tmp_dir, filename, NULL); - - GST_DEBUG_OBJECT (decoder, "enable download buffering in %s (%s, %s, %s)", - temp_template, tmp_dir, prgname, filename); - - /* configure progressive download for selected media types */ - g_object_set (G_OBJECT (queue), "temp-template", temp_template, NULL); - - g_free (filename); - g_free (temp_template); - } - - /* Disable max-size-buffers */ - g_object_set (G_OBJECT (queue), "max-size-buffers", 0, NULL); - - /* If buffer size or duration are set, set them on the queue2 element */ - if (decoder->buffer_size != -1) - g_object_set (G_OBJECT (queue), "max-size-bytes", - decoder->buffer_size, NULL); - if (decoder->buffer_duration != -1) - g_object_set (G_OBJECT (queue), "max-size-time", - decoder->buffer_duration, NULL); - - gst_bin_add (GST_BIN_CAST (decoder), queue); - - if (!gst_element_link_pads (typefind, "src", queue, "sink")) - goto could_not_link; - - /* to force caps on the decodebin element and avoid reparsing stuff by - * typefind. It also avoids a deadlock in the way typefind activates pads in - * the state change */ - g_object_set (G_OBJECT (dec_elem), "sink-caps", caps, NULL); - - if (!gst_element_link_pads (queue, "src", dec_elem, "sink")) - goto could_not_link; - - gst_element_set_state (dec_elem, GST_STATE_PLAYING); - gst_element_set_state (queue, GST_STATE_PLAYING); - - do_async_done (decoder); - - return; - - /* ERRORS */ -no_decodebin: - { - /* error was posted */ - return; - } -could_not_link: - { - GST_ELEMENT_ERROR (decoder, CORE, NEGOTIATION, - (NULL), ("Can't link typefind to decodebin2 element")); - return; - } no_queue2: { GST_ELEMENT_ERROR (decoder, CORE, MISSING_PLUGIN, (_("Could not create \"queue2\" element.")), (NULL)); - return; - } -} - -/* setup a streaming source. This will first plug a typefind element to the - * source. After we find the type, we decide to plug a queue2 and continue to - * plug a decodebin2 starting from the found caps */ -static gboolean -setup_streaming (GstURIDecodeBin * decoder) -{ - GstElement *typefind; - - /* now create the decoder element */ - typefind = gst_element_factory_make ("typefind", NULL); - if (!typefind) - goto no_typefind; - - gst_bin_add (GST_BIN_CAST (decoder), typefind); - - if (!gst_element_link (decoder->source, typefind)) - goto could_not_link; - - decoder->typefind = typefind; - - /* connect a signal to find out when the typefind element found - * a type */ - decoder->have_type_id = - g_signal_connect (G_OBJECT (decoder->typefind), "have-type", - G_CALLBACK (type_found), decoder); - - do_async_start (decoder); - - return TRUE; - - /* ERRORS */ -no_typefind: - { - GST_ELEMENT_ERROR (decoder, CORE, MISSING_PLUGIN, - (_("Could not create \"typefind\" element.")), (NULL)); - return FALSE; - } -could_not_link: - { - GST_ELEMENT_ERROR (decoder, CORE, NEGOTIATION, - (NULL), ("Can't link source to typefind element")); - return FALSE; + return NULL; } } @@ -1407,20 +1039,18 @@ GstElement *decoder; gboolean is_raw; - GST_URI_DECODE_BIN_LOCK (bin); GST_DEBUG_OBJECT (bin, "Found new pad %s.%s in source element %s", GST_DEBUG_PAD_NAME (pad), GST_ELEMENT_NAME (element)); /* if this is a pad with all raw caps, we can expose it */ if (has_all_raw_caps (pad, &is_raw) && is_raw) { /* it's all raw, create output pads. */ - GST_URI_DECODE_BIN_UNLOCK (bin); new_decoded_pad_cb (element, pad, FALSE, bin); return; } /* not raw, create decoder */ - decoder = make_decoder (bin); + decoder = make_decoder (bin, FALSE); if (!decoder) goto no_decodebin; @@ -1431,7 +1061,6 @@ GST_DEBUG_OBJECT (bin, "linked decoder to new pad"); gst_element_set_state (decoder, GST_STATE_PLAYING); - GST_URI_DECODE_BIN_UNLOCK (bin); return; @@ -1439,14 +1068,12 @@ no_decodebin: { /* error was posted */ - GST_URI_DECODE_BIN_UNLOCK (bin); return; } could_not_link: { GST_ELEMENT_ERROR (bin, CORE, NEGOTIATION, (NULL), ("Can't link source to decoder element")); - GST_URI_DECODE_BIN_UNLOCK (bin); return; } } @@ -1464,8 +1091,6 @@ /* delete old src */ remove_source (decoder); - decoder->pending = 0; - /* create and configure an element that can handle the uri */ if (!(decoder->source = gen_source_element (decoder))) goto no_source; @@ -1474,9 +1099,6 @@ * handled by the application right after. */ gst_bin_add (GST_BIN_CAST (decoder), decoder->source); - /* notify of the new source used */ - g_object_notify (G_OBJECT (decoder), "source"); - /* remove the old decoders now, if any */ remove_decoders (decoder); @@ -1484,15 +1106,14 @@ * if so, we can create streams for the pads and be done with it. * Also check that is has source pads, if not, we assume it will * do everything itself. */ - if (!analyse_source (decoder, &is_raw, &have_out, &is_dynamic, - decoder->need_queue)) + if (!analyse_source (decoder, &is_raw, &have_out, &is_dynamic)) goto invalid_source; if (is_raw) { GST_DEBUG_OBJECT (decoder, "Source provides all raw data"); /* source provides raw data, we added the pads and we can now signal a * no_more pads because we are done. */ - gst_element_no_more_pads (GST_ELEMENT_CAST (decoder)); + /* FIXME, actually do this... */ return TRUE; } if (!have_out && !is_dynamic) { @@ -1514,24 +1135,17 @@ g_object_set_data (G_OBJECT (decoder->source), "pending", "1"); decoder->pending++; } else { - if (decoder->is_stream) { - GST_DEBUG_OBJECT (decoder, "Setting up streaming"); - /* do the stream things here */ - if (!setup_streaming (decoder)) - goto streaming_failed; - } else { - GstElement *dec_elem; + GstElement *dec_elem; + + GST_DEBUG_OBJECT (decoder, "Pluggin decodebin to source"); - /* no streaming source, we can link now */ - GST_DEBUG_OBJECT (decoder, "Plugging decodebin to source"); + /* no dynamic source, we can link now */ + dec_elem = make_decoder (decoder, decoder->is_stream); + if (!dec_elem) + goto no_decoder; - dec_elem = make_decoder (decoder); - if (!dec_elem) - goto no_decoder; - - if (!gst_element_link (decoder->source, dec_elem)) - goto could_not_link; - } + if (!gst_element_link (decoder->source, dec_elem)) + goto could_not_link; } return TRUE; @@ -1552,11 +1166,6 @@ /* message was posted */ return FALSE; } -streaming_failed: - { - /* message was posted */ - return FALSE; - } could_not_link: { GST_ELEMENT_ERROR (decoder, CORE, NEGOTIATION, @@ -1710,7 +1319,6 @@ gst_object_unref (item); return TRUE; } - static void decoder_query_duration_done (GstURIDecodeBin * dec, QueryFold * fold) { @@ -1742,7 +1350,6 @@ gst_object_unref (item); return TRUE; } - static void decoder_query_position_done (GstURIDecodeBin * dec, QueryFold * fold) { @@ -1785,7 +1392,6 @@ gst_object_unref (item); return TRUE; } - static void decoder_query_latency_done (GstURIDecodeBin * dec, QueryFold * fold) { @@ -1817,7 +1423,6 @@ return TRUE; } - static void decoder_query_seeking_done (GstURIDecodeBin * dec, QueryFold * fold) { @@ -1966,13 +1571,6 @@ remove_decoders (decoder); remove_pads (decoder); remove_source (decoder); - do_async_done (decoder); - break; - case GST_STATE_CHANGE_READY_TO_NULL: - GST_DEBUG ("ready to null"); - remove_decoders (decoder); - remove_pads (decoder); - remove_source (decoder); break; default: break; @@ -2003,7 +1601,6 @@ GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, LOCALEDIR); bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); #endif /* ENABLE_NLS */ return gst_element_register (plugin, "uridecodebin", GST_RANK_NONE,