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