typefind: Add _with_extension() variants for typefinding data or a buffer
authorSebastian Dröge <sebastian@centricular.com>
Tue, 24 Jul 2018 14:28:45 +0000 (17:28 +0300)
committerSebastian Dröge <sebastian@centricular.com>
Tue, 24 Jul 2018 22:12:11 +0000 (01:12 +0300)
And make use of that in the typefind element to also be able to make use
of the extension in push mode. It previously only did that in pull mode
and this potentially speeds up typefinding and might also prevent false
positives.

https://bugzilla.gnome.org/show_bug.cgi?id=796865

docs/libs/gstreamer-libs-sections.txt
libs/gst/base/gsttypefindhelper.c
libs/gst/base/gsttypefindhelper.h
plugins/elements/gsttypefindelement.c
win32/common/libgstbase.def

index f9f051b..688083b 100644 (file)
@@ -946,8 +946,10 @@ gst_push_src_get_type
 <INCLUDE>gst/base/gsttypefindhelper.h</INCLUDE>
 gst_type_find_helper
 gst_type_find_helper_for_buffer
+gst_type_find_helper_for_buffer_with_extension
 gst_type_find_helper_for_extension
 gst_type_find_helper_for_data
+gst_type_find_helper_for_data_with_extension
 GstTypeFindHelperGetRangeFunction
 gst_type_find_helper_get_range
 <SUBSECTION Private>
index 1723f34..32f7d9a 100644 (file)
@@ -248,6 +248,57 @@ helper_find_get_length (gpointer data)
   return helper->size;
 }
 
+static GList *
+prioritize_extension (GstObject * obj, GList * type_list,
+    const gchar * extension)
+{
+  gint pos = 0;
+  GList *next, *l;
+
+  if (!extension)
+    return type_list;
+
+  /* move the typefinders for the extension first in the list. The idea is that
+   * when one of them returns MAX we don't need to search further as there is a
+   * very high chance we got the right type. */
+
+  GST_LOG_OBJECT (obj, "sorting typefind for extension %s to head", extension);
+
+  for (l = type_list; l; l = next) {
+    const gchar *const *ext;
+    GstTypeFindFactory *factory;
+
+    next = l->next;
+
+    factory = GST_TYPE_FIND_FACTORY (l->data);
+
+    ext = gst_type_find_factory_get_extensions (factory);
+    if (ext == NULL)
+      continue;
+
+    GST_LOG_OBJECT (obj, "testing factory %s for extension %s",
+        GST_OBJECT_NAME (factory), extension);
+
+    while (*ext != NULL) {
+      if (strcmp (*ext, extension) == 0) {
+        /* found extension, move in front */
+        GST_LOG_OBJECT (obj, "moving typefind for extension %s to head",
+            extension);
+        /* remove entry from list */
+        type_list = g_list_delete_link (type_list, l);
+        /* insert at the position */
+        type_list = g_list_insert (type_list, factory, pos);
+        /* next element will be inserted after this one */
+        pos++;
+        break;
+      }
+      ++ext;
+    }
+  }
+
+  return type_list;
+}
+
 /**
  * gst_type_find_helper_get_range:
  * @obj: A #GstObject that will be passed as first argument to @func
@@ -287,7 +338,6 @@ gst_type_find_helper_get_range (GstObject * obj, GstObject * parent,
   GSList *walk;
   GList *l, *type_list;
   GstCaps *result = NULL;
-  gint pos = 0;
 
   g_return_val_if_fail (GST_IS_OBJECT (obj), NULL);
   g_return_val_if_fail (func != NULL, NULL);
@@ -312,48 +362,7 @@ gst_type_find_helper_get_range (GstObject * obj, GstObject * parent,
   }
 
   type_list = gst_type_find_factory_get_list ();
-
-  /* move the typefinders for the extension first in the list. The idea is that
-   * when one of them returns MAX we don't need to search further as there is a
-   * very high chance we got the right type. */
-  if (extension) {
-    GList *next;
-
-    GST_LOG_OBJECT (obj, "sorting typefind for extension %s to head",
-        extension);
-
-    for (l = type_list; l; l = next) {
-      const gchar *const *ext;
-      GstTypeFindFactory *factory;
-
-      next = l->next;
-
-      factory = GST_TYPE_FIND_FACTORY (l->data);
-
-      ext = gst_type_find_factory_get_extensions (factory);
-      if (ext == NULL)
-        continue;
-
-      GST_LOG_OBJECT (obj, "testing factory %s for extension %s",
-          GST_OBJECT_NAME (factory), extension);
-
-      while (*ext != NULL) {
-        if (strcmp (*ext, extension) == 0) {
-          /* found extension, move in front */
-          GST_LOG_OBJECT (obj, "moving typefind for extension %s to head",
-              extension);
-          /* remove entry from list */
-          type_list = g_list_delete_link (type_list, l);
-          /* insert at the position */
-          type_list = g_list_insert (type_list, factory, pos);
-          /* next element will be inserted after this one */
-          pos++;
-          break;
-        }
-        ++ext;
-      }
-    }
-  }
+  type_list = prioritize_extension (obj, type_list, extension);
 
   for (l = type_list; l; l = l->next) {
     helper.factory = GST_TYPE_FIND_FACTORY (l->data);
@@ -519,6 +528,48 @@ GstCaps *
 gst_type_find_helper_for_data (GstObject * obj, const guint8 * data, gsize size,
     GstTypeFindProbability * prob)
 {
+  return gst_type_find_helper_for_data_with_extension (obj, data, size, NULL,
+      prob);
+}
+
+/**
+ * gst_type_find_helper_for_data_with_extension:
+ * @obj: (allow-none): object doing the typefinding, or %NULL (used for logging)
+ * @data: (transfer none) (array length=size): * a pointer with data to typefind
+ * @size: the size of @data
+ * @extension: (allow-none): extension of the media, or %NULL
+ * @prob: (out) (allow-none): location to store the probability of the found
+ *     caps, or %NULL
+ *
+ * Tries to find what type of data is contained in the given @data, the
+ * assumption being that the data 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 @data could not be identified.
+ *
+ * When @extension is not %NULL, this function will first try the typefind
+ * functions for the given extension, which might speed up the typefinding
+ * in many cases.
+ *
+ * Free-function: gst_caps_unref
+ *
+ * Returns: (transfer full) (nullable): 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().
+ *
+ * Since: 1.16
+ *
+ */
+GstCaps *
+gst_type_find_helper_for_data_with_extension (GstObject * obj,
+    const guint8 * data, gsize size, const gchar * extension,
+    GstTypeFindProbability * prob)
+{
   GstTypeFindBufHelper helper;
   GstTypeFind find;
   GList *l, *type_list;
@@ -541,6 +592,7 @@ gst_type_find_helper_for_data (GstObject * obj, const guint8 * data, gsize size,
   find.get_length = NULL;
 
   type_list = gst_type_find_factory_get_list ();
+  type_list = prioritize_extension (obj, type_list, extension);
 
   for (l = type_list; l; l = l->next) {
     helper.factory = GST_TYPE_FIND_FACTORY (l->data);
@@ -590,6 +642,45 @@ GstCaps *
 gst_type_find_helper_for_buffer (GstObject * obj, GstBuffer * buf,
     GstTypeFindProbability * prob)
 {
+  return gst_type_find_helper_for_buffer_with_extension (obj, buf, NULL, prob);
+}
+
+/**
+ * gst_type_find_helper_for_buffer_with_extension:
+ * @obj: (allow-none): object doing the typefinding, or %NULL (used for logging)
+ * @buf: (in) (transfer none): a #GstBuffer with data to typefind
+ * @extension: (allow-none): extension of the media, or %NULL
+ * @prob: (out) (allow-none): 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.
+ *
+ * When @extension is not %NULL, this function will first try the typefind
+ * functions for the given extension, which might speed up the typefinding
+ * in many cases.
+ *
+ * Free-function: gst_caps_unref
+ *
+ * Returns: (transfer full) (nullable): 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().
+ *
+ * Since: 1.16
+ *
+ */
+GstCaps *
+gst_type_find_helper_for_buffer_with_extension (GstObject * obj,
+    GstBuffer * buf, const gchar * extension, GstTypeFindProbability * prob)
+{
   GstCaps *result;
   GstMapInfo info;
 
@@ -600,7 +691,9 @@ gst_type_find_helper_for_buffer (GstObject * obj, GstBuffer * buf,
 
   if (!gst_buffer_map (buf, &info, GST_MAP_READ))
     return NULL;
-  result = gst_type_find_helper_for_data (obj, info.data, info.size, prob);
+  result =
+      gst_type_find_helper_for_data_with_extension (obj, info.data, info.size,
+      extension, prob);
   gst_buffer_unmap (buf, &info);
 
   return result;
index 6f032ca..b722a13 100644 (file)
@@ -37,10 +37,25 @@ GstCaps * gst_type_find_helper_for_data   (GstObject              *obj,
                                            const guint8           *data,
                                            gsize                   size,
                                            GstTypeFindProbability *prob);
+
+GST_BASE_API
+GstCaps * gst_type_find_helper_for_data_with_extension (GstObject              *obj,
+                                                        const guint8           *data,
+                                                        gsize                   size,
+                                                        const gchar            *extension,
+                                                        GstTypeFindProbability *prob);
+
 GST_BASE_API
 GstCaps * gst_type_find_helper_for_buffer (GstObject              *obj,
                                            GstBuffer              *buf,
                                            GstTypeFindProbability *prob);
+
+GST_BASE_API
+GstCaps * gst_type_find_helper_for_buffer_with_extension (GstObject              *obj,
+                                                          GstBuffer              *buf,
+                                                          const gchar            *extension,
+                                                          GstTypeFindProbability *prob);
+
 GST_BASE_API
 GstCaps * gst_type_find_helper_for_extension (GstObject * obj,
                                               const gchar * extension);
index 30f902b..bd48152 100644 (file)
@@ -930,6 +930,7 @@ gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind,
   gsize avail;
   const guint8 *data;
   gboolean have_min, have_max;
+  gchar *ext;
 
   GST_OBJECT_LOCK (typefind);
   if (typefind->force_caps) {
@@ -951,11 +952,13 @@ gst_type_find_element_chain_do_typefinding (GstTypeFindElement * typefind,
     if (!have_min)
       goto not_enough_data;
 
+    ext = gst_type_find_get_extension (typefind, typefind->sink);
     /* map all available data */
     data = gst_adapter_map (typefind->adapter, avail);
-    caps = gst_type_find_helper_for_data (GST_OBJECT (typefind),
-        data, avail, &probability);
+    caps = gst_type_find_helper_for_data_with_extension (GST_OBJECT (typefind),
+        data, avail, ext, &probability);
     gst_adapter_unmap (typefind->adapter);
+    g_free (ext);
 
     if (caps == NULL && have_max)
       goto no_type_found;
index ebc1d54..648c0bb 100644 (file)
@@ -353,6 +353,8 @@ EXPORTS
        gst_queue_array_push_tail_struct
        gst_type_find_helper
        gst_type_find_helper_for_buffer
+       gst_type_find_helper_for_buffer_with_extension
        gst_type_find_helper_for_data
+       gst_type_find_helper_for_data_with_extension
        gst_type_find_helper_for_extension
        gst_type_find_helper_get_range