typefind: Add new gst_type_find_helper_get_range_full() that returns flow return

And make use of it in the typefind element. It's useful to distinguish
between the different errors why typefinding can fail, and especially to
not consider GST_FLOW_FLUSHING as an actual error.

https://bugzilla.gnome.org/show_bug.cgi?id=796894
This commit is contained in:
Sebastian Dröge 2018-07-30 18:10:31 +03:00
parent c4cd50f734
commit bb3fbfbe7f
4 changed files with 91 additions and 11 deletions

View file

@ -63,6 +63,7 @@ typedef struct
GstTypeFindFactory *factory; /* for logging */
GstObject *obj; /* for logging */
GstObject *parent;
GstFlowReturn flow_ret;
} GstTypeFindHelper;
/*
@ -83,7 +84,6 @@ helper_find_peek (gpointer data, gint64 offset, guint size)
{
GstTypeFindHelper *helper;
GstBuffer *buffer;
GstFlowReturn ret;
GSList *insert_pos = NULL;
gsize buf_size;
guint64 buf_offset;
@ -140,11 +140,11 @@ helper_find_peek (gpointer data, gint64 offset, guint size)
* of the file is also not a problem here, we'll just get a truncated buffer
* in that case (and we'll have to double-check the size we actually get
* anyway, see below) */
ret =
helper->flow_ret =
helper->func (helper->obj, helper->parent, offset, MAX (size, 4096),
&buffer);
if (ret != GST_FLOW_OK)
if (helper->flow_ret != GST_FLOW_OK)
goto error;
#if 0
@ -202,7 +202,8 @@ helper_find_peek (gpointer data, gint64 offset, guint size)
error:
{
GST_INFO ("typefind function returned: %s", gst_flow_get_name (ret));
GST_INFO ("typefind function returned: %s",
gst_flow_get_name (helper->flow_ret));
return NULL;
}
map_failed:
@ -281,6 +282,49 @@ GstCaps *
gst_type_find_helper_get_range (GstObject * obj, GstObject * parent,
GstTypeFindHelperGetRangeFunction func, guint64 size,
const gchar * extension, GstTypeFindProbability * prob)
{
GstCaps *caps = NULL;
gst_type_find_helper_get_range_full (obj, parent, func, size, extension,
&caps, prob);
return caps;
}
/**
* gst_type_find_helper_get_range_full:
* @obj: A #GstObject that will be passed as first argument to @func
* @parent: (allow-none): the parent of @obj or %NULL
* @func: (scope call): A generic #GstTypeFindHelperGetRangeFunction that will
* be used to access data at random offsets when doing the typefinding
* @size: The length in bytes
* @extension: (allow-none): extension of the media, or %NULL
* @caps: (out) (transfer full): returned caps
* @prob: (out) (allow-none): location to store the probability of the found
* caps, or %NULL
*
* Utility function to do pull-based typefinding. Unlike gst_type_find_helper()
* however, this function will use the specified function @func to obtain the
* data needed by the typefind functions, rather than operating on a given
* source pad. This is useful mostly for elements like tag demuxers which
* strip off data at the beginning and/or end of a file and want to typefind
* the stripped data stream before adding their own source pad (the specified
* callback can then call the upstream peer pad with offsets adjusted for the
* tag size, for example).
*
* 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.
*
* Returns: the last %GstFlowReturn from pulling a buffer or %GST_FLOW_OK if
* typefinding was successful.
*
* Since: 1.16
*/
GstFlowReturn
gst_type_find_helper_get_range_full (GstObject * obj, GstObject * parent,
GstTypeFindHelperGetRangeFunction func, guint64 size,
const gchar * extension, GstCaps ** caps, GstTypeFindProbability * prob)
{
GstTypeFindHelper helper;
GstTypeFind find;
@ -289,8 +333,11 @@ gst_type_find_helper_get_range (GstObject * obj, GstObject * parent,
GstCaps *result = NULL;
gint pos = 0;
g_return_val_if_fail (GST_IS_OBJECT (obj), NULL);
g_return_val_if_fail (func != NULL, NULL);
g_return_val_if_fail (GST_IS_OBJECT (obj), GST_FLOW_ERROR);
g_return_val_if_fail (func != NULL, GST_FLOW_ERROR);
g_return_val_if_fail (caps != NULL, GST_FLOW_ERROR);
*caps = NULL;
helper.buffers = NULL;
helper.size = size;
@ -300,6 +347,7 @@ gst_type_find_helper_get_range (GstObject * obj, GstObject * parent,
helper.caps = NULL;
helper.obj = obj;
helper.parent = parent;
helper.flow_ret = GST_FLOW_OK;
find.data = &helper;
find.peek = helper_find_peek;
@ -358,8 +406,19 @@ gst_type_find_helper_get_range (GstObject * obj, GstObject * parent,
for (l = type_list; l; l = l->next) {
helper.factory = GST_TYPE_FIND_FACTORY (l->data);
gst_type_find_factory_call_function (helper.factory, &find);
if (helper.best_probability >= GST_TYPE_FIND_MAXIMUM)
if (helper.best_probability >= GST_TYPE_FIND_MAXIMUM) {
/* Any other flow return can be ignored here, we found
* something before any error with highest probability */
helper.flow_ret = GST_FLOW_OK;
break;
} else if (helper.flow_ret != GST_FLOW_OK
&& helper.flow_ret != GST_FLOW_EOS) {
/* We had less than maximum probability and an error, don't return
* any caps as they might be with a lower probability than what
* we would've gotten when continuing if there was no error */
gst_caps_replace (&helper.caps, NULL);
break;
}
}
gst_plugin_feature_list_free (type_list);
@ -378,10 +437,18 @@ gst_type_find_helper_get_range (GstObject * obj, GstObject * parent,
if (prob)
*prob = helper.best_probability;
*caps = result;
if (helper.flow_ret == GST_FLOW_EOS) {
/* Some typefinder might've tried to read too much, if we
* didn't get any meaningful caps because of that this is
* just a normal error */
helper.flow_ret = GST_FLOW_ERROR;
}
GST_LOG_OBJECT (obj, "Returning %" GST_PTR_FORMAT " (probability = %u)",
result, (guint) helper.best_probability);
return result;
return helper.flow_ret;
}
/**

View file

@ -76,6 +76,15 @@ GstCaps * gst_type_find_helper_get_range (GstObject *obj
const gchar *extension,
GstTypeFindProbability *prob);
GST_BASE_API
GstFlowReturn gst_type_find_helper_get_range_full (GstObject *obj,
GstObject *parent,
GstTypeFindHelperGetRangeFunction func,
guint64 size,
const gchar *extension,
GstCaps **caps,
GstTypeFindProbability *prob);
G_END_DECLS
#endif /* __GST_TYPEFINDHELPER_H__ */

View file

@ -1136,16 +1136,19 @@ gst_type_find_element_loop (GstPad * pad)
}
ext = gst_type_find_get_extension (typefind, pad);
found_caps =
gst_type_find_helper_get_range (GST_OBJECT_CAST (peer),
ret =
gst_type_find_helper_get_range_full (GST_OBJECT_CAST (peer),
GST_OBJECT_PARENT (peer),
(GstTypeFindHelperGetRangeFunction) (GST_PAD_GETRANGEFUNC (peer)),
(guint64) size, ext, &probability);
(guint64) size, ext, &found_caps, &probability);
g_free (ext);
GST_DEBUG ("Found caps %" GST_PTR_FORMAT, found_caps);
gst_object_unref (peer);
if (ret != GST_FLOW_OK)
goto pause;
}
}

View file

@ -330,3 +330,4 @@ EXPORTS
gst_type_find_helper_for_data
gst_type_find_helper_for_extension
gst_type_find_helper_get_range
gst_type_find_helper_get_range_full