/* GStreamer
* Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
- * 2000,2005 Wim Taymans <wim@fluendo.com>
+ * Copyright (C) 2000,2005 Wim Taymans <wim@fluendo.com>
+ * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
*
* gsttypefindhelper.c:
*
return result;
}
+
+/* ********************** typefinding for buffers ************************* */
+
+typedef struct
+{
+ guint8 *data;
+ guint size;
+ guint best_probability;
+ GstCaps *caps;
+ GstObject *factory; /* for logging */
+ GstObject *obj; /* for logging */
+} GstTypeFindBufHelper;
+
+static guint8 *
+buf_helper_find_peek (gpointer data, gint64 off, guint size)
+{
+ GstTypeFindBufHelper *helper;
+
+ helper = (GstTypeFindBufHelper *) data;
+ GST_LOG_OBJECT (helper->obj, "'%s' called peek (%" G_GINT64_FORMAT ", %u)",
+ GST_PLUGIN_FEATURE_NAME (helper->factory), off, size);
+
+ if (size == 0)
+ return NULL;
+
+ if (off < 0) {
+ GST_LOG_OBJECT (helper->obj, "'%s' wanted to peek at end; not supported",
+ GST_PLUGIN_FEATURE_NAME (helper->factory));
+ return NULL;
+ }
+
+ if ((off + size) < helper->size)
+ return helper->data + off;
+
+ return NULL;
+}
+
+static void
+buf_helper_find_suggest (gpointer data, guint prob, const GstCaps * caps)
+{
+ GstTypeFindBufHelper *helper = (GstTypeFindBufHelper *) data;
+
+ GST_LOG_OBJECT (helper->obj,
+ "'%s' called called suggest (%u, %" GST_PTR_FORMAT ")",
+ GST_PLUGIN_FEATURE_NAME (helper->factory), prob, caps);
+
+ /* Note: not >= as we call typefinders in order of rank, highest first */
+ if (prob > helper->best_probability) {
+ GstCaps *copy = gst_caps_copy (caps);
+
+ gst_caps_replace (&helper->caps, copy);
+ gst_caps_unref (copy);
+ helper->best_probability = prob;
+ }
+}
+
+static gint
+type_find_factory_rank_cmp (gconstpointer fac1, gconstpointer fac2)
+{
+ if (GST_PLUGIN_FEATURE (fac1)->rank != GST_PLUGIN_FEATURE (fac2)->rank)
+ return GST_PLUGIN_FEATURE (fac2)->rank - GST_PLUGIN_FEATURE (fac1)->rank;
+
+ /* to make the order in which things happen more deterministic,
+ * sort by name when the ranks are the same. */
+ return strcmp (GST_PLUGIN_FEATURE_NAME (fac1),
+ GST_PLUGIN_FEATURE_NAME (fac2));
+}
+
+/**
+ * gst_type_find_helper_for_buffer:
+ * @obj: object doing the typefinding, or NULL (used for logging)
+ * @buf: a #GstBuffer with data to typefind
+ * @prob: location to store the probability of the found caps, or #NULL
+ *
+ * Tries to find what type of data is contained in the given #GstBuffer, the
+ * assumption being that the buffer represents the beginning of the stream or
+ * file.
+ *
+ * All available typefinders will be called on the data in order of rank. If
+ * a typefinding function returns a probability of #GST_TYPE_FIND_MAXIMUM,
+ * typefinding is stopped immediately and the found caps will be returned
+ * right away. Otherwise, all available typefind functions will the tried,
+ * and the caps with the highest probability will be returned, or #NULL if
+ * the content of the buffer could not be identified.
+ *
+ * Returns: The #GstCaps corresponding to the data, or #NULL if no type could
+ * be found. The caller should free the caps returned with gst_caps_unref().
+ */
+GstCaps *
+gst_type_find_helper_for_buffer (GstObject * obj, GstBuffer * buf,
+ GstTypeFindProbability * prob)
+{
+ GstTypeFindBufHelper helper;
+ GstTypeFind find;
+ GList *l, *type_list;
+
+ g_return_val_if_fail (buf != NULL, NULL);
+ g_return_val_if_fail (GST_IS_BUFFER (buf), NULL);
+ g_return_val_if_fail (GST_BUFFER_OFFSET (buf) == 0 ||
+ GST_BUFFER_OFFSET (buf) == GST_BUFFER_OFFSET_NONE, NULL);
+
+ helper.data = GST_BUFFER_DATA (buf);
+ helper.size = GST_BUFFER_SIZE (buf);
+ helper.best_probability = 0;
+ helper.caps = NULL;
+ helper.obj = obj;
+
+ if (helper.data == NULL || helper.size == 0)
+ return NULL;
+
+ find.data = &helper;
+ find.peek = buf_helper_find_peek;
+ find.suggest = buf_helper_find_suggest;
+ find.get_length = NULL;
+
+ type_list = gst_type_find_factory_get_list ();
+
+ type_list = g_list_sort (type_list, type_find_factory_rank_cmp);
+
+ for (l = type_list; l != NULL; l = l->next) {
+ GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (l->data);
+
+ helper.factory = GST_OBJECT (factory);
+
+ gst_type_find_factory_call_function (factory, &find);
+ if (helper.best_probability >= GST_TYPE_FIND_MAXIMUM)
+ break;
+ }
+
+ gst_plugin_feature_list_free (type_list);
+
+ if (helper.best_probability == 0)
+ return NULL;
+
+ if (prob)
+ *prob = helper.best_probability;
+
+ GST_LOG_OBJECT (obj, "Returning %" GST_PTR_FORMAT " (probability = %u)",
+ helper.caps, (guint) helper.best_probability);
+
+ return helper.caps;
+}