2 * Copyright (C) 2003 Benjamin Otte <in7y118@public.uni-hamburg.de>
4 * gsttypefindelement.c: element that detects type of stream
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
22 * SECTION:element-typefind
24 * Determines the media-type of a stream. It applies typefind functions in the
25 * order of their rank. One the type has been deteted it sets its src pad caps
26 * to the found media type.
28 * Whenever a type is found the #GstTypeFindElement::have-type signal is
29 * emitted, either from the streaming thread or the application thread
30 * (the latter may happen when typefinding is done pull-based from the
31 * state change function).
33 * Plugins can register custom typefinders by using #GstTypeFindFactory.
36 /* FIXME: need a better solution for non-seekable streams */
39 * 1) get a list of all typefind functions sorted best to worst
40 * 2) if all elements have been called with all requested data goto 8
41 * 3) call all functions once with all available data
42 * 4) if a function returns a value >= PROP_MAXIMUM goto 8
43 * 5) all functions with a result > PROP_MINIMUM or functions that did not get
44 * all requested data (where peek returned NULL) stay in list
45 * 6) seek to requested offset of best function that still has open data
48 * 8) take best available result and use its caps
50 * The element has two scheduling modes:
52 * 1) chain based, it will collect buffers and run the typefind function on
53 * the buffer until something is found.
54 * 2) getrange based, it will proxy the getrange function to the sinkpad. It
55 * is assumed that the peer element is happy with whatever format we
58 * By default it tries to do pull based typefinding (this avoids joining
59 * received buffers and holding them back in store.)
61 * When the element has no connected srcpad, and the sinkpad can operate in
62 * getrange based mode, the element starts its own task to figure out the
65 * Most of the actual implementation is in libs/gst/base/gsttypefindhelper.c.
72 #include "gst/gst_private.h"
74 #include "gsttypefindelement.h"
75 #include "gst/gst-i18n-lib.h"
76 #include "gst/base/gsttypefindhelper.h"
78 #include <gst/gsttypefind.h>
79 #include <gst/gstutils.h>
80 #include <gst/gsterror.h>
82 GST_DEBUG_CATEGORY_STATIC (gst_type_find_element_debug);
83 #define GST_CAT_DEFAULT gst_type_find_element_debug
85 /* generic templates */
86 static GstStaticPadTemplate type_find_element_sink_template =
87 GST_STATIC_PAD_TEMPLATE ("sink",
92 static GstStaticPadTemplate type_find_element_src_template =
93 GST_STATIC_PAD_TEMPLATE ("src",
98 /* Require at least 2kB of data before we attempt typefinding in chain-mode.
99 * 128kB is massive overkill for the maximum, but doesn't do any harm */
100 #define TYPE_FIND_MIN_SIZE (2*1024)
101 #define TYPE_FIND_MAX_SIZE (128*1024)
103 /* TypeFind signals and args */
120 MODE_NORMAL, /* act as identity */
121 MODE_TYPEFIND, /* do typefinding */
122 MODE_ERROR /* had fatal error */
127 GST_DEBUG_CATEGORY_INIT (gst_type_find_element_debug, "typefind", \
128 GST_DEBUG_BG_YELLOW | GST_DEBUG_FG_GREEN, "type finding element");
129 #define gst_type_find_element_parent_class parent_class
130 G_DEFINE_TYPE_WITH_CODE (GstTypeFindElement, gst_type_find_element,
131 GST_TYPE_ELEMENT, _do_init);
133 static void gst_type_find_element_dispose (GObject * object);
134 static void gst_type_find_element_set_property (GObject * object,
135 guint prop_id, const GValue * value, GParamSpec * pspec);
136 static void gst_type_find_element_get_property (GObject * object,
137 guint prop_id, GValue * value, GParamSpec * pspec);
140 static const GstEventMask *gst_type_find_element_src_event_mask (GstPad * pad);
143 static gboolean gst_type_find_element_src_event (GstPad * pad,
144 GstObject * parent, GstEvent * event);
145 static gboolean gst_type_find_handle_src_query (GstPad * pad,
146 GstObject * parent, GstQuery * query);
148 static gboolean gst_type_find_element_sink_event (GstPad * pad,
149 GstObject * parent, GstEvent * event);
150 static gboolean gst_type_find_element_setcaps (GstTypeFindElement * typefind,
152 static GstFlowReturn gst_type_find_element_chain (GstPad * sinkpad,
153 GstObject * parent, GstBuffer * buffer);
154 static GstFlowReturn gst_type_find_element_getrange (GstPad * srcpad,
155 GstObject * parent, guint64 offset, guint length, GstBuffer ** buffer);
157 static GstStateChangeReturn
158 gst_type_find_element_change_state (GstElement * element,
159 GstStateChange transition);
160 static gboolean gst_type_find_element_activate (GstPad * pad,
162 static gboolean gst_type_find_element_activate_src_pull (GstPad * pad,
163 GstObject * parent, gboolean active);
165 gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind,
166 gboolean check_avail);
167 static void gst_type_find_element_send_cached_events (GstTypeFindElement *
170 static guint gst_type_find_element_signals[LAST_SIGNAL] = { 0 };
173 gst_type_find_element_have_type (GstTypeFindElement * typefind,
174 guint probability, const GstCaps * caps)
178 g_assert (caps != NULL);
180 GST_INFO_OBJECT (typefind, "found caps %" GST_PTR_FORMAT ", probability=%u",
183 GST_OBJECT_LOCK (typefind);
185 gst_caps_unref (typefind->caps);
186 typefind->caps = gst_caps_copy (caps);
187 copy = gst_caps_ref (typefind->caps);
188 GST_OBJECT_UNLOCK (typefind);
190 gst_pad_push_event (typefind->src, gst_event_new_caps (copy));
191 gst_caps_unref (copy);
195 gst_type_find_element_class_init (GstTypeFindElementClass * typefind_class)
197 GObjectClass *gobject_class = G_OBJECT_CLASS (typefind_class);
198 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (typefind_class);
200 gobject_class->set_property = gst_type_find_element_set_property;
201 gobject_class->get_property = gst_type_find_element_get_property;
202 gobject_class->dispose = gst_type_find_element_dispose;
204 g_object_class_install_property (gobject_class, PROP_CAPS,
205 g_param_spec_boxed ("caps", _("caps"),
206 _("detected capabilities in stream"), GST_TYPE_CAPS,
207 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
208 g_object_class_install_property (gobject_class, PROP_MINIMUM,
209 g_param_spec_uint ("minimum", _("minimum"),
210 "minimum probability required to accept caps", GST_TYPE_FIND_MINIMUM,
211 GST_TYPE_FIND_MAXIMUM, GST_TYPE_FIND_MINIMUM,
212 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
213 g_object_class_install_property (gobject_class, PROP_MAXIMUM,
214 g_param_spec_uint ("maximum", _("maximum"),
215 "probability to stop typefinding (deprecated; non-functional)",
216 GST_TYPE_FIND_MINIMUM, GST_TYPE_FIND_MAXIMUM, GST_TYPE_FIND_MAXIMUM,
217 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
218 g_object_class_install_property (gobject_class, PROP_FORCE_CAPS,
219 g_param_spec_boxed ("force-caps", _("force caps"),
220 _("force caps without doing a typefind"), GST_TYPE_CAPS,
221 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
223 * GstTypeFindElement::have-type:
224 * @typefind: the typefind instance
225 * @probability: the probability of the type found
226 * @caps: the caps of the type found
228 * This signal gets emitted when the type and its probability has
231 gst_type_find_element_signals[HAVE_TYPE] = g_signal_new ("have-type",
232 G_TYPE_FROM_CLASS (typefind_class), G_SIGNAL_RUN_FIRST,
233 G_STRUCT_OFFSET (GstTypeFindElementClass, have_type), NULL, NULL,
234 gst_marshal_VOID__UINT_BOXED, G_TYPE_NONE, 2,
235 G_TYPE_UINT, GST_TYPE_CAPS | G_SIGNAL_TYPE_STATIC_SCOPE);
237 typefind_class->have_type =
238 GST_DEBUG_FUNCPTR (gst_type_find_element_have_type);
240 gst_element_class_set_details_simple (gstelement_class,
243 "Finds the media type of a stream",
244 "Benjamin Otte <in7y118@public.uni-hamburg.de>");
245 gst_element_class_add_pad_template (gstelement_class,
246 gst_static_pad_template_get (&type_find_element_src_template));
247 gst_element_class_add_pad_template (gstelement_class,
248 gst_static_pad_template_get (&type_find_element_sink_template));
250 gstelement_class->change_state =
251 GST_DEBUG_FUNCPTR (gst_type_find_element_change_state);
255 gst_type_find_element_init (GstTypeFindElement * typefind)
259 gst_pad_new_from_static_template (&type_find_element_sink_template,
262 gst_pad_set_activate_function (typefind->sink,
263 GST_DEBUG_FUNCPTR (gst_type_find_element_activate));
264 gst_pad_set_chain_function (typefind->sink,
265 GST_DEBUG_FUNCPTR (gst_type_find_element_chain));
266 gst_pad_set_event_function (typefind->sink,
267 GST_DEBUG_FUNCPTR (gst_type_find_element_sink_event));
268 gst_element_add_pad (GST_ELEMENT (typefind), typefind->sink);
272 gst_pad_new_from_static_template (&type_find_element_src_template, "src");
274 gst_pad_set_activatepull_function (typefind->src,
275 GST_DEBUG_FUNCPTR (gst_type_find_element_activate_src_pull));
276 gst_pad_set_getrange_function (typefind->src,
277 GST_DEBUG_FUNCPTR (gst_type_find_element_getrange));
278 gst_pad_set_event_function (typefind->src,
279 GST_DEBUG_FUNCPTR (gst_type_find_element_src_event));
280 gst_pad_set_query_function (typefind->src,
281 GST_DEBUG_FUNCPTR (gst_type_find_handle_src_query));
282 gst_pad_use_fixed_caps (typefind->src);
283 gst_element_add_pad (GST_ELEMENT (typefind), typefind->src);
285 typefind->mode = MODE_TYPEFIND;
286 typefind->caps = NULL;
287 typefind->min_probability = 1;
288 typefind->max_probability = GST_TYPE_FIND_MAXIMUM;
290 typefind->adapter = gst_adapter_new ();
294 gst_type_find_element_dispose (GObject * object)
296 GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (object);
298 if (typefind->adapter) {
299 g_object_unref (typefind->adapter);
300 typefind->adapter = NULL;
303 if (typefind->force_caps) {
304 gst_caps_unref (typefind->force_caps);
305 typefind->force_caps = NULL;
308 G_OBJECT_CLASS (parent_class)->dispose (object);
312 gst_type_find_element_set_property (GObject * object, guint prop_id,
313 const GValue * value, GParamSpec * pspec)
315 GstTypeFindElement *typefind;
317 typefind = GST_TYPE_FIND_ELEMENT (object);
321 typefind->min_probability = g_value_get_uint (value);
324 typefind->max_probability = g_value_get_uint (value);
326 case PROP_FORCE_CAPS:
327 GST_OBJECT_LOCK (typefind);
328 if (typefind->force_caps)
329 gst_caps_unref (typefind->force_caps);
330 typefind->force_caps = g_value_dup_boxed (value);
331 GST_OBJECT_UNLOCK (typefind);
334 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
340 gst_type_find_element_get_property (GObject * object, guint prop_id,
341 GValue * value, GParamSpec * pspec)
343 GstTypeFindElement *typefind;
345 typefind = GST_TYPE_FIND_ELEMENT (object);
349 GST_OBJECT_LOCK (typefind);
350 g_value_set_boxed (value, typefind->caps);
351 GST_OBJECT_UNLOCK (typefind);
354 g_value_set_uint (value, typefind->min_probability);
357 g_value_set_uint (value, typefind->max_probability);
359 case PROP_FORCE_CAPS:
360 GST_OBJECT_LOCK (typefind);
361 g_value_set_boxed (value, typefind->force_caps);
362 GST_OBJECT_UNLOCK (typefind);
365 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
371 gst_type_find_handle_src_query (GstPad * pad, GstObject * parent,
374 GstTypeFindElement *typefind;
375 gboolean res = FALSE;
377 typefind = GST_TYPE_FIND_ELEMENT (parent);
379 res = gst_pad_peer_query (typefind->sink, query);
383 switch (GST_QUERY_TYPE (query)) {
384 case GST_QUERY_POSITION:
389 gst_query_parse_position (query, &format, &peer_pos);
391 GST_OBJECT_LOCK (typefind);
392 /* FIXME: this code assumes that there's no discont in the queue */
394 case GST_FORMAT_BYTES:
395 peer_pos -= gst_adapter_available (typefind->adapter);
401 GST_OBJECT_UNLOCK (typefind);
402 gst_query_set_position (query, format, peer_pos);
414 static const GstEventMask *
415 gst_type_find_element_src_event_mask (GstPad * pad)
417 static const GstEventMask mask[] = {
419 GST_SEEK_METHOD_SET | GST_SEEK_METHOD_CUR | GST_SEEK_METHOD_END |
420 GST_SEEK_FLAG_FLUSH},
421 /* add more if you want, event masks suck and need to die anyway */
430 gst_type_find_element_src_event (GstPad * pad, GstObject * parent,
433 GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (parent);
435 if (typefind->mode != MODE_NORMAL) {
436 /* need to do more? */
437 gst_mini_object_unref (GST_MINI_OBJECT_CAST (event));
440 return gst_pad_push_event (typefind->sink, event);
444 start_typefinding (GstTypeFindElement * typefind)
446 GST_DEBUG_OBJECT (typefind, "starting typefinding");
448 GST_OBJECT_LOCK (typefind);
450 gst_caps_replace (&typefind->caps, NULL);
451 GST_OBJECT_UNLOCK (typefind);
453 typefind->mode = MODE_TYPEFIND;
457 stop_typefinding (GstTypeFindElement * typefind)
460 gboolean push_cached_buffers;
464 gst_element_get_state (GST_ELEMENT (typefind), &state, NULL, 0);
466 push_cached_buffers = (state >= GST_STATE_PAUSED);
468 GST_DEBUG_OBJECT (typefind, "stopping typefinding%s",
469 push_cached_buffers ? " and pushing cached buffers" : "");
471 GST_OBJECT_LOCK (typefind);
472 avail = gst_adapter_available (typefind->adapter);
476 buffer = gst_adapter_take_buffer (typefind->adapter, avail);
477 GST_OBJECT_UNLOCK (typefind);
479 if (!push_cached_buffers) {
480 gst_buffer_unref (buffer);
482 GstPad *peer = gst_pad_get_peer (typefind->src);
484 typefind->mode = MODE_NORMAL;
486 /* make sure the user gets a meaningful error message in this case,
487 * which is not a core bug or bug of any kind (as the default error
488 * message emitted by gstpad.c otherwise would make you think) */
489 if (peer && GST_PAD_CHAINFUNC (peer) == NULL) {
490 GST_DEBUG_OBJECT (typefind, "upstream only supports push mode, while "
491 "downstream element only works in pull mode, erroring out");
492 GST_ELEMENT_ERROR (typefind, STREAM, FAILED,
493 ("%s cannot work in push mode. The operation is not supported "
494 "with this source element or protocol.",
495 G_OBJECT_TYPE_NAME (GST_PAD_PARENT (peer))),
496 ("Downstream pad %s:%s has no chainfunction, and the upstream "
497 "element does not support pull mode", GST_DEBUG_PAD_NAME (peer)));
498 typefind->mode = MODE_ERROR; /* make the chain function error out */
499 gst_buffer_unref (buffer);
501 gst_type_find_element_send_cached_events (typefind);
502 gst_pad_push (typefind->src, buffer);
505 gst_object_unref (peer);
512 GST_DEBUG_OBJECT (typefind, "we have no data to typefind");
513 GST_OBJECT_UNLOCK (typefind);
519 gst_type_find_element_sink_event (GstPad * pad, GstObject * parent,
522 gboolean res = FALSE;
523 GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (parent);
525 GST_DEBUG_OBJECT (typefind, "got %s event in mode %d",
526 GST_EVENT_TYPE_NAME (event), typefind->mode);
528 switch (typefind->mode) {
530 switch (GST_EVENT_TYPE (event)) {
535 /* first pass the caps event downstream */
536 res = gst_pad_push_event (typefind->src, gst_event_ref (event));
538 /* then parse and push out our data */
539 gst_event_parse_caps (event, &caps);
540 res = gst_type_find_element_setcaps (typefind, caps);
542 gst_event_unref (event);
547 GST_INFO_OBJECT (typefind, "Got EOS and no type found yet");
548 gst_type_find_element_chain_do_typefinding (typefind, FALSE);
550 res = gst_pad_push_event (typefind->src, event);
553 case GST_EVENT_FLUSH_STOP:
554 GST_OBJECT_LOCK (typefind);
555 g_list_foreach (typefind->cached_events,
556 (GFunc) gst_mini_object_unref, NULL);
557 g_list_free (typefind->cached_events);
558 typefind->cached_events = NULL;
559 gst_adapter_clear (typefind->adapter);
560 GST_OBJECT_UNLOCK (typefind);
562 case GST_EVENT_FLUSH_START:
563 res = gst_pad_push_event (typefind->src, event);
566 GST_DEBUG_OBJECT (typefind, "Saving %s event to send later",
567 GST_EVENT_TYPE_NAME (event));
568 GST_OBJECT_LOCK (typefind);
569 typefind->cached_events =
570 g_list_append (typefind->cached_events, event);
571 GST_OBJECT_UNLOCK (typefind);
577 res = gst_pad_push_event (typefind->src, event);
582 g_assert_not_reached ();
588 gst_type_find_element_send_cached_events (GstTypeFindElement * typefind)
590 GList *l, *cached_events;
592 GST_OBJECT_LOCK (typefind);
593 cached_events = typefind->cached_events;
594 typefind->cached_events = NULL;
595 GST_OBJECT_UNLOCK (typefind);
597 for (l = cached_events; l != NULL; l = l->next) {
598 GstEvent *event = GST_EVENT (l->data);
600 GST_DEBUG_OBJECT (typefind, "sending cached %s event",
601 GST_EVENT_TYPE_NAME (event));
602 gst_pad_push_event (typefind->src, event);
604 g_list_free (cached_events);
608 gst_type_find_element_setcaps (GstTypeFindElement * typefind, GstCaps * caps)
610 /* don't operate on ANY caps */
611 if (gst_caps_is_any (caps))
614 g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
615 GST_TYPE_FIND_MAXIMUM, caps);
617 /* Shortcircuit typefinding if we get caps */
618 if (typefind->mode == MODE_TYPEFIND) {
622 GST_DEBUG_OBJECT (typefind, "Skipping typefinding, using caps from "
623 "upstream buffer: %" GST_PTR_FORMAT, caps);
624 typefind->mode = MODE_NORMAL;
626 gst_type_find_element_send_cached_events (typefind);
627 GST_OBJECT_LOCK (typefind);
628 avail = gst_adapter_available (typefind->adapter);
632 buffer = gst_adapter_take_buffer (typefind->adapter, avail);
633 GST_OBJECT_UNLOCK (typefind);
635 GST_DEBUG_OBJECT (typefind, "Pushing buffer: %" G_GSIZE_FORMAT, avail);
636 gst_pad_push (typefind->src, buffer);
643 GST_DEBUG_OBJECT (typefind, "no data to push");
644 GST_OBJECT_UNLOCK (typefind);
650 gst_type_find_get_extension (GstTypeFindElement * typefind, GstPad * pad)
657 query = gst_query_new_uri ();
659 /* try getting the caps with an uri query and from the extension */
660 if (!gst_pad_peer_query (pad, query))
661 goto peer_query_failed;
663 gst_query_parse_uri (query, &uri);
667 GST_DEBUG_OBJECT (typefind, "finding extension of %s", uri);
669 /* find the extension on the uri, this is everything after a '.' */
674 if (uri[find] == '.')
681 result = g_strdup (&uri[find + 1]);
683 GST_DEBUG_OBJECT (typefind, "found extension %s", result);
684 gst_query_unref (query);
692 GST_WARNING_OBJECT (typefind, "failed to query peer uri");
693 gst_query_unref (query);
698 GST_WARNING_OBJECT (typefind, "could not parse the peer uri");
699 gst_query_unref (query);
704 GST_WARNING_OBJECT (typefind, "could not find uri extension in %s", uri);
705 gst_query_unref (query);
712 gst_type_find_guess_by_extension (GstTypeFindElement * typefind, GstPad * pad,
713 GstTypeFindProbability * probability)
718 ext = gst_type_find_get_extension (typefind, pad);
722 caps = gst_type_find_helper_for_extension (GST_OBJECT_CAST (typefind), ext);
724 *probability = GST_TYPE_FIND_MAXIMUM;
732 gst_type_find_element_chain (GstPad * pad, GstObject * parent,
735 GstTypeFindElement *typefind;
736 GstFlowReturn res = GST_FLOW_OK;
738 typefind = GST_TYPE_FIND_ELEMENT (parent);
740 GST_LOG_OBJECT (typefind, "handling buffer in mode %d", typefind->mode);
742 switch (typefind->mode) {
744 /* we should already have called GST_ELEMENT_ERROR */
745 return GST_FLOW_ERROR;
747 /* don't take object lock as typefind->caps should not change anymore */
748 return gst_pad_push (typefind->src, buffer);
751 GST_OBJECT_LOCK (typefind);
752 gst_adapter_push (typefind->adapter, buffer);
753 GST_OBJECT_UNLOCK (typefind);
755 res = gst_type_find_element_chain_do_typefinding (typefind, TRUE);
757 if (typefind->mode == MODE_ERROR)
758 res = GST_FLOW_ERROR;
763 g_assert_not_reached ();
764 return GST_FLOW_ERROR;
771 gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind,
772 gboolean check_avail)
774 GstTypeFindProbability probability;
778 gboolean have_min, have_max;
780 GST_OBJECT_LOCK (typefind);
781 avail = gst_adapter_available (typefind->adapter);
784 have_min = avail >= TYPE_FIND_MIN_SIZE;
785 have_max = avail >= TYPE_FIND_MAX_SIZE;
792 goto not_enough_data;
794 /* map all available data */
795 data = gst_adapter_map (typefind->adapter, avail);
796 caps = gst_type_find_helper_for_data (GST_OBJECT (typefind),
797 data, avail, &probability);
798 gst_adapter_unmap (typefind->adapter);
800 if (caps == NULL && have_max)
802 else if (caps == NULL)
806 if (probability < typefind->min_probability)
807 goto low_probability;
808 GST_OBJECT_UNLOCK (typefind);
810 /* probability is good enough too, so let's make it known ... emiting this
811 * signal calls our object handler which sets the caps. */
812 g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0,
815 /* .. and send out the accumulated data */
816 stop_typefinding (typefind);
817 gst_caps_unref (caps);
823 GST_DEBUG_OBJECT (typefind, "not enough data for typefinding yet "
824 "(%" G_GSIZE_FORMAT " bytes)", avail);
825 GST_OBJECT_UNLOCK (typefind);
830 GST_OBJECT_UNLOCK (typefind);
831 GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
832 stop_typefinding (typefind);
833 return GST_FLOW_ERROR;
837 GST_DEBUG_OBJECT (typefind,
838 "no caps found with %" G_GSIZE_FORMAT " bytes of data, "
839 "waiting for more data", avail);
840 GST_OBJECT_UNLOCK (typefind);
845 GST_DEBUG_OBJECT (typefind, "found caps %" GST_PTR_FORMAT ", but "
846 "probability is %u which is lower than the required minimum of %u",
847 caps, probability, typefind->min_probability);
849 gst_caps_unref (caps);
854 GST_OBJECT_UNLOCK (typefind);
855 GST_DEBUG_OBJECT (typefind, "waiting for more data to try again");
861 gst_type_find_element_getrange (GstPad * srcpad, GstObject * parent,
862 guint64 offset, guint length, GstBuffer ** buffer)
864 GstTypeFindElement *typefind;
867 typefind = GST_TYPE_FIND_ELEMENT (parent);
869 ret = gst_pad_pull_range (typefind->sink, offset, length, buffer);
875 gst_type_find_element_activate_src_pull (GstPad * pad, GstObject * parent,
878 GstTypeFindElement *typefind;
880 typefind = GST_TYPE_FIND_ELEMENT (parent);
882 return gst_pad_activate_pull (typefind->sink, active);
886 gst_type_find_element_activate (GstPad * pad, GstObject * parent)
888 GstTypeFindProbability probability = GST_TYPE_FIND_NONE;
889 GstCaps *found_caps = NULL;
890 GstTypeFindElement *typefind;
894 typefind = GST_TYPE_FIND_ELEMENT (parent);
896 /* if we have force caps, use those */
897 GST_OBJECT_LOCK (typefind);
898 if (typefind->force_caps) {
899 found_caps = gst_caps_ref (typefind->force_caps);
900 probability = GST_TYPE_FIND_MAXIMUM;
901 GST_OBJECT_UNLOCK (typefind);
904 GST_OBJECT_UNLOCK (typefind);
906 /* 1. try to activate in pull mode. if not, switch to push and succeed.
907 2. try to pull type find.
908 3. deactivate pull mode.
909 4. src pad might have been activated push by the state change. deactivate.
910 5. if we didn't find any caps, try getting the uri extension by doing an uri
912 6. if we didn't find any caps, fail.
913 7. emit have-type; maybe the app connected the source pad to something.
914 8. if the sink pad is activated, we are in pull mode. succeed.
915 otherwise activate both pads in push mode and succeed.
919 query = gst_query_new_scheduling ();
921 if (!gst_pad_peer_query (pad, query)) {
922 gst_query_unref (query);
926 gst_query_parse_scheduling (query, &pull_mode, NULL, NULL, NULL, NULL, NULL);
927 gst_query_unref (query);
932 if (!gst_pad_activate_pull (pad, TRUE))
936 GST_DEBUG_OBJECT (typefind, "find type in pull mode");
941 peer = gst_pad_get_peer (pad);
946 if (!gst_pad_query_duration (peer, GST_FORMAT_BYTES, &size)) {
947 GST_WARNING_OBJECT (typefind, "Could not query upstream length!");
948 gst_object_unref (peer);
949 gst_pad_activate_pull (pad, FALSE);
953 /* the size if 0, we cannot continue */
955 /* keep message in sync with message in sink event handler */
956 GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND,
957 (_("Stream contains no data.")), ("Can't typefind empty stream"));
958 gst_object_unref (peer);
959 gst_pad_activate_pull (pad, FALSE);
962 ext = gst_type_find_get_extension (typefind, pad);
965 gst_type_find_helper_get_range (GST_OBJECT_CAST (peer),
966 GST_OBJECT_PARENT (peer),
967 (GstTypeFindHelperGetRangeFunction) (GST_PAD_GETRANGEFUNC (peer)),
968 (guint64) size, ext, &probability);
971 GST_DEBUG ("Found caps %" GST_PTR_FORMAT, found_caps);
973 gst_object_unref (peer);
977 /* the type find helpers might have triggered setcaps here (due to upstream)
978 * setting caps on buffers, which emits typefound signal and an element
979 * could have been linked and have its pads activated
981 * If we deactivate the pads in the following steps we might mess up
982 * downstream element. We should prevent that.
984 if (typefind->mode == MODE_NORMAL) {
985 /* this means we already emitted typefound */
986 GST_DEBUG ("Already managed to typefind !");
991 GST_DEBUG ("Deactivate pull mode");
992 gst_pad_activate_pull (pad, FALSE);
996 GST_DEBUG ("Deactivate push mode mode");
997 gst_pad_activate_push (typefind->src, FALSE);
1001 if (!found_caps || probability < typefind->min_probability) {
1002 GST_DEBUG ("Trying to guess using extension");
1003 found_caps = gst_type_find_guess_by_extension (typefind, pad, &probability);
1007 if (!found_caps || probability < typefind->min_probability) {
1008 GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
1009 gst_caps_replace (&found_caps, NULL);
1015 GST_DEBUG ("Emiting found caps %" GST_PTR_FORMAT, found_caps);
1016 g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
1017 0, probability, found_caps);
1018 typefind->mode = MODE_NORMAL;
1021 gst_caps_unref (found_caps);
1024 if (gst_pad_is_active (pad))
1029 GST_DEBUG ("Activating in push mode");
1030 ret = gst_pad_activate_push (typefind->src, TRUE);
1031 ret &= gst_pad_activate_push (pad, TRUE);
1036 start_typefinding (typefind);
1037 return gst_pad_activate_push (pad, TRUE);
1041 static GstStateChangeReturn
1042 gst_type_find_element_change_state (GstElement * element,
1043 GstStateChange transition)
1045 GstStateChangeReturn ret;
1046 GstTypeFindElement *typefind;
1048 typefind = GST_TYPE_FIND_ELEMENT (element);
1051 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1053 switch (transition) {
1054 case GST_STATE_CHANGE_PAUSED_TO_READY:
1055 case GST_STATE_CHANGE_READY_TO_NULL:
1056 GST_OBJECT_LOCK (typefind);
1057 gst_caps_replace (&typefind->caps, NULL);
1059 g_list_foreach (typefind->cached_events,
1060 (GFunc) gst_mini_object_unref, NULL);
1061 g_list_free (typefind->cached_events);
1062 typefind->cached_events = NULL;
1063 typefind->mode = MODE_TYPEFIND;
1064 GST_OBJECT_UNLOCK (typefind);