From d196b0b904e00f254b0cc54ca18d0deb47b823ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 24 Jul 2018 17:28:45 +0300 Subject: [PATCH] typefind: Add _with_extension() variants for typefinding data or a buffer 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 | 2 + libs/gst/base/gsttypefindhelper.c | 181 +++++++++++++++++++------- libs/gst/base/gsttypefindhelper.h | 15 +++ plugins/elements/gsttypefindelement.c | 7 +- win32/common/libgstbase.def | 2 + 5 files changed, 161 insertions(+), 46 deletions(-) diff --git a/docs/libs/gstreamer-libs-sections.txt b/docs/libs/gstreamer-libs-sections.txt index f9f051b672..688083bd1d 100644 --- a/docs/libs/gstreamer-libs-sections.txt +++ b/docs/libs/gstreamer-libs-sections.txt @@ -946,8 +946,10 @@ gst_push_src_get_type gst/base/gsttypefindhelper.h 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 diff --git a/libs/gst/base/gsttypefindhelper.c b/libs/gst/base/gsttypefindhelper.c index 1723f3472e..32f7d9abd1 100644 --- a/libs/gst/base/gsttypefindhelper.c +++ b/libs/gst/base/gsttypefindhelper.c @@ -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); @@ -518,6 +527,48 @@ buf_helper_find_suggest (gpointer data, guint probability, GstCaps * caps) 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; @@ -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); @@ -589,6 +641,45 @@ gst_type_find_helper_for_data (GstObject * obj, const guint8 * data, gsize size, 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; diff --git a/libs/gst/base/gsttypefindhelper.h b/libs/gst/base/gsttypefindhelper.h index 6f032ca789..b722a13366 100644 --- a/libs/gst/base/gsttypefindhelper.h +++ b/libs/gst/base/gsttypefindhelper.h @@ -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); diff --git a/plugins/elements/gsttypefindelement.c b/plugins/elements/gsttypefindelement.c index 30f902be78..bd48152537 100644 --- a/plugins/elements/gsttypefindelement.c +++ b/plugins/elements/gsttypefindelement.c @@ -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; diff --git a/win32/common/libgstbase.def b/win32/common/libgstbase.def index ebc1d5418b..648c0bb016 100644 --- a/win32/common/libgstbase.def +++ b/win32/common/libgstbase.def @@ -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