mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-22 16:26:39 +00:00
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
This commit is contained in:
parent
b079334c1c
commit
d196b0b904
5 changed files with 161 additions and 46 deletions
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue