plugins/elements/gsttypefindelement.c: Catch the special case where we are operating chain-based, but the downstream ...

Original commit message from CVS:
* plugins/elements/gsttypefindelement.c: (stop_typefinding):
Catch the special case where we are operating chain-based,
but the downstream peer pad has no chain function. Emit a
custom error message in this case instead of letting the
core generate one implying that this is some sort of core
bug. It's not, it just means that whatever got plugged
into the pipeline downstream when we announced the type
can only operate pull-based, while our source can only
operate push-based (e.g. http://foo/bar.mov ! qtdemux ! ...)
Error string has not been marked for translation yet, as
it probably needs some more work first.
(gst_type_find_element_get_best_possibility):
Add helper function to find the best of all available
found possibilities that qualify given the min. threshold.
(gst_type_find_element_handle_event):
Fix the case where we get an EOS while still in TYPEFIND
mode (we want to chose the best of all possible types,
not just the first type that happens to be in our unsorted
list of possible types).
(gst_type_find_element_chain):
Make sure we return GST_FLOW_ERROR when we errored out
in stop_typefinding(); also, don't just find the best of
all found type entries and then use the last examined
type entry, but actually use the best entry.
This commit is contained in:
Tim-Philipp Müller 2005-12-12 17:09:04 +00:00
parent ed1d0dfd9d
commit c821be101e
2 changed files with 100 additions and 33 deletions

View file

@ -1,3 +1,33 @@
2005-12-12 Tim-Philipp Müller <tim at centricular dot net>
* plugins/elements/gsttypefindelement.c: (stop_typefinding):
Catch the special case where we are operating chain-based,
but the downstream peer pad has no chain function. Emit a
custom error message in this case instead of letting the
core generate one implying that this is some sort of core
bug. It's not, it just means that whatever got plugged
into the pipeline downstream when we announced the type
can only operate pull-based, while our source can only
operate push-based (e.g. http://foo/bar.mov ! qtdemux ! ...)
Error string has not been marked for translation yet, as
it probably needs some more work first.
(gst_type_find_element_get_best_possibility):
Add helper function to find the best of all available
found possibilities that qualify given the min. threshold.
(gst_type_find_element_handle_event):
Fix the case where we get an EOS while still in TYPEFIND
mode (we want to chose the best of all possible types,
not just the first type that happens to be in our unsorted
list of possible types).
(gst_type_find_element_chain):
Make sure we return GST_FLOW_ERROR when we errored out
in stop_typefinding(); also, don't just find the best of
all found type entries and then use the last examined
type entry, but actually use the best entry.
2005-12-12 Tim-Philipp Müller <tim at centricular dot net>
* tests/examples/typefind/typefind.c: (type_found):

View file

@ -98,7 +98,8 @@ enum
enum
{
MODE_NORMAL, /* act as identity */
MODE_TYPEFIND /* do typefinding */
MODE_TYPEFIND, /* do typefinding */
MODE_ERROR /* had fatal error */
};
@ -410,6 +411,7 @@ start_typefinding (GstTypeFindElement * typefind)
typefind->stream_length_available = TRUE;
typefind->stream_length = 0;
}
static void
stop_typefinding (GstTypeFindElement * typefind)
{
@ -437,9 +439,31 @@ stop_typefinding (GstTypeFindElement * typefind)
if (!push_cached_buffers) {
gst_buffer_unref (typefind->store);
} else {
GstPad *peer = gst_pad_get_peer (typefind->src);
typefind->mode = MODE_NORMAL;
gst_buffer_set_caps (typefind->store, typefind->caps);
gst_pad_push (typefind->src, typefind->store);
/* make sure the user gets a meaningful error message in this case,
* which is not a core bug or bug of any kind (as the default error
* message emitted by gstpad.c otherwise would make you think) */
if (peer && GST_PAD_CHAINFUNC (peer) == NULL) {
GST_DEBUG_OBJECT (typefind, "upstream only supports push mode, while "
"downstream element only works in pull mode, erroring out");
GST_ELEMENT_ERROR (typefind, STREAM, FAILED,
("%s cannot work in push mode. The operation is not supported "
"with this source element or protocol.",
G_OBJECT_TYPE_NAME (GST_PAD_PARENT (peer))),
("Downstream pad %s:%s has no chainfunction, and the upstream "
"element does not support pull mode",
GST_DEBUG_PAD_NAME (peer)));
typefind->mode = MODE_ERROR; /* make the chain function error out */
} else {
gst_pad_push (typefind->src, typefind->store);
}
if (peer)
gst_object_unref (peer);
}
typefind->store = NULL;
}
@ -484,44 +508,58 @@ no_length:
}
}
static TypeFindEntry *
gst_type_find_element_get_best_possibility (GstTypeFindElement * typefind)
{
TypeFindEntry *best = NULL;
GList *walk;
for (walk = typefind->possibilities; walk != NULL; walk = walk->next) {
TypeFindEntry *entry;
entry = (TypeFindEntry *) walk->data;
if ((!best || entry->probability > best->probability) &&
entry->probability >= typefind->min_probability) {
best = entry;
}
}
return best;
}
static gboolean
gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
{
gboolean res = FALSE;
TypeFindEntry *entry;
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
GST_DEBUG_OBJECT (typefind, "got event %d in mode %d", GST_EVENT_TYPE (event),
typefind->mode);
GST_DEBUG_OBJECT (typefind, "got %s event in mode %d",
GST_EVENT_TYPE_NAME (event), typefind->mode);
switch (typefind->mode) {
case MODE_TYPEFIND:
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_EOS:
/* this should only happen when we got all available data */
entry =
(TypeFindEntry *) typefind->possibilities ? typefind->
possibilities->data : NULL;
case GST_EVENT_EOS:{
TypeFindEntry *entry;
entry = gst_type_find_element_get_best_possibility (typefind);
if (entry && entry->probability >= typefind->min_probability) {
GST_INFO_OBJECT (typefind,
"'%s' is the best typefind left after we got all data, using it now (probability %u)",
GST_PLUGIN_FEATURE_NAME (entry->factory), entry->probability);
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
0, entry->probability, entry->caps);
stop_typefinding (typefind);
gst_buffer_set_caps (typefind->store, typefind->caps);
gst_pad_push (typefind->src, typefind->store);
typefind->store = NULL;
res = gst_pad_event_default (pad, event);
} else {
res = gst_pad_event_default (pad, event);
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL),
(NULL));
stop_typefinding (typefind);
}
stop_typefinding (typefind);
res = gst_pad_event_default (pad, event);
break;
}
default:
gst_mini_object_unref (GST_MINI_OBJECT (event));
gst_event_unref (event);
res = TRUE;
break;
}
@ -535,6 +573,8 @@ gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
res = gst_pad_event_default (pad, event);
}
break;
case MODE_ERROR:
break;
default:
g_assert_not_reached ();
}
@ -610,6 +650,9 @@ gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
switch (typefind->mode) {
case MODE_ERROR:
/* we should already have called GST_ELEMENT_ERROR */
return GST_FLOW_ERROR;
case MODE_NORMAL:
gst_buffer_set_caps (buffer, typefind->caps);
return gst_pad_push (typefind->src, buffer);
@ -704,24 +747,14 @@ gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
stop_typefinding (typefind);
return GST_FLOW_ERROR;
} else if (done) {
TypeFindEntry *best = NULL;
TypeFindEntry *best;
walk = typefind->possibilities;
while (walk) {
entry = (TypeFindEntry *) typefind->possibilities->data;
if ((!best || entry->probability > best->probability) &&
entry->probability >= typefind->min_probability) {
best = entry;
}
walk = g_list_next (walk);
}
if (best) {
if ((best = gst_type_find_element_get_best_possibility (typefind))) {
GST_INFO_OBJECT (typefind,
"'%s' is the only typefind left, using it now (probability %u)",
GST_PLUGIN_FEATURE_NAME (entry->factory), entry->probability);
"'%s' is the best typefind left, using it now (probability %u)",
GST_PLUGIN_FEATURE_NAME (best->factory), best->probability);
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
0, entry->probability, entry->caps);
0, best->probability, best->caps);
g_list_foreach (typefind->possibilities, (GFunc) free_entry, NULL);
g_list_free (typefind->possibilities);
typefind->possibilities = NULL;
@ -732,6 +765,10 @@ gst_type_find_element_chain (GstPad * pad, GstBuffer * buffer)
return GST_FLOW_ERROR;
}
}
if (typefind->mode == MODE_ERROR)
res = GST_FLOW_ERROR;
break;
}
default: