fix typefind discont handling, #153657

Original commit message from CVS:
fix typefind discont handling, #153657
This commit is contained in:
Thomas Vander Stichele 2004-09-26 17:48:05 +00:00
parent 3cd8266b12
commit e45b8c2be6
5 changed files with 193 additions and 90 deletions

View file

@ -1,3 +1,16 @@
2004-09-26 Thomas Vander Stichele <thomas at apestaart dot org>
patch by: Ronald Bultje
* gst/elements/gsttypefindelement.c: (stop_typefinding),
(gst_type_find_element_handle_event),
(gst_type_find_element_chain):
* gst/elements/gsttypefindelement.h:
#153657.
Filter out discont event from seekable sources when typefind
asks them to seek. Fixes typefind with demuxers for
avi, asf and matroska.
2004-09-26 Thomas Vander Stichele <thomas at apestaart dot org> 2004-09-26 Thomas Vander Stichele <thomas at apestaart dot org>
* docs/gst/gstreamer-sections.txt: * docs/gst/gstreamer-sections.txt:

View file

@ -84,6 +84,8 @@ enum
enum enum
{ {
MODE_NORMAL, /* act as identity */ MODE_NORMAL, /* act as identity */
MODE_TRANSITION, /* wait for the discont between the two
* other modes */
MODE_TYPEFIND /* do typefinding */ MODE_TYPEFIND /* do typefinding */
}; };
@ -277,7 +279,7 @@ gst_type_find_element_src_event (GstPad * pad, GstEvent * event)
{ {
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad)); GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
if (typefind->mode == MODE_TYPEFIND) { if (typefind->mode != MODE_NORMAL) {
/* need to do more? */ /* need to do more? */
gst_data_unref (GST_DATA (event)); gst_data_unref (GST_DATA (event));
return FALSE; return FALSE;
@ -350,10 +352,11 @@ stop_typefinding (GstTypeFindElement * typefind)
typefind->possibilities = NULL; typefind->possibilities = NULL;
} }
typefind->mode = MODE_NORMAL; typefind->mode = MODE_TRANSITION;
if (push_cached_buffers) { if (!push_cached_buffers) {
GstBuffer *buffer; gst_buffer_store_clear (typefind->store);
} else {
guint size = gst_buffer_store_get_size (typefind->store, 0); guint size = gst_buffer_store_get_size (typefind->store, 0);
GST_DEBUG_OBJECT (typefind, "seeking back to current position %u", size); GST_DEBUG_OBJECT (typefind, "seeking back to current position %u", size);
@ -362,18 +365,31 @@ stop_typefinding (GstTypeFindElement * typefind)
size))) { size))) {
GST_WARNING_OBJECT (typefind, GST_WARNING_OBJECT (typefind,
"could not seek to required position %u, hope for the best", size); "could not seek to required position %u, hope for the best", size);
typefind->mode = MODE_NORMAL;
gst_buffer_store_clear (typefind->store);
} else {
typefind->waiting_for_discont_offset = size;
} }
}
}
static void
push_buffer_store (GstTypeFindElement * typefind)
{
guint size = gst_buffer_store_get_size (typefind->store, 0);
GstBuffer *buffer;
gst_pad_push (typefind->src, GST_DATA (gst_event_new_discontinuous (TRUE, gst_pad_push (typefind->src, GST_DATA (gst_event_new_discontinuous (TRUE,
GST_FORMAT_DEFAULT, (guint64) 0, GST_FORMAT_BYTES, (guint64) 0, GST_FORMAT_DEFAULT, (guint64) 0, GST_FORMAT_BYTES, (guint64) 0,
GST_FORMAT_UNDEFINED))); GST_FORMAT_UNDEFINED)));
if (size if (size && (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
&& (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
GST_DEBUG_OBJECT (typefind, "pushing cached data (%u bytes)", size); GST_DEBUG_OBJECT (typefind, "pushing cached data (%u bytes)", size);
gst_pad_push (typefind->src, GST_DATA (buffer)); gst_pad_push (typefind->src, GST_DATA (buffer));
} else { } else {
/* FIXME: shouldn't we throw an error here? */
size = 0; size = 0;
} }
}
gst_buffer_store_clear (typefind->store); gst_buffer_store_clear (typefind->store);
} }
@ -416,8 +432,8 @@ gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
TypeFindEntry *entry; TypeFindEntry *entry;
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad)); GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
if (typefind->mode == MODE_TYPEFIND) { switch (typefind->mode) {
/* need to do more? */ case MODE_TYPEFIND:
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_EOS: case GST_EVENT_EOS:
/* this should only happen when we got all available data */ /* this should only happen when we got all available data */
@ -428,13 +444,14 @@ gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
GST_INFO_OBJECT (typefind, GST_INFO_OBJECT (typefind,
"'%s' is the best typefind left after we got all data, using it now (probability %u)", "'%s' is the best typefind left after we got all data, using it now (probability %u)",
GST_PLUGIN_FEATURE_NAME (entry->factory), entry->probability); GST_PLUGIN_FEATURE_NAME (entry->factory), entry->probability);
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0, g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
entry->probability, entry->caps); 0, entry->probability, entry->caps);
stop_typefinding (typefind); stop_typefinding (typefind);
gst_pad_event_default (pad, event); gst_pad_event_default (pad, event);
} else { } else {
gst_pad_event_default (pad, event); gst_pad_event_default (pad, event);
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL)); GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL),
(NULL));
stop_typefinding (typefind); stop_typefinding (typefind);
} }
break; break;
@ -442,7 +459,28 @@ gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
gst_data_unref (GST_DATA (event)); gst_data_unref (GST_DATA (event));
break; break;
} }
break;
case MODE_TRANSITION:
if (GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS) {
if (GST_EVENT_DISCONT_NEW_MEDIA (event)) {
start_typefinding (typefind);
gst_event_unref (event);
} else { } else {
guint64 off;
if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &off) &&
off == typefind->waiting_for_discont_offset) {
typefind->mode = MODE_NORMAL;
push_buffer_store (typefind);
} else {
gst_event_unref (event);
}
}
} else {
gst_event_unref (event);
}
break;
case MODE_NORMAL:
if (GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS && if (GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS &&
GST_EVENT_DISCONT_NEW_MEDIA (event)) { GST_EVENT_DISCONT_NEW_MEDIA (event)) {
start_typefinding (typefind); start_typefinding (typefind);
@ -450,6 +488,9 @@ gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
} else { } else {
gst_pad_event_default (pad, event); gst_pad_event_default (pad, event);
} }
break;
default:
g_assert_not_reached ();
} }
} }
static guint8 * static guint8 *
@ -537,6 +578,9 @@ gst_type_find_element_chain (GstPad * pad, GstData * data)
case MODE_NORMAL: case MODE_NORMAL:
gst_pad_push (typefind->src, data); gst_pad_push (typefind->src, data);
return; return;
case MODE_TRANSITION:
gst_data_unref (data);
return;
case MODE_TYPEFIND:{ case MODE_TYPEFIND:{
guint64 current_offset; guint64 current_offset;

View file

@ -53,6 +53,7 @@ struct _GstTypeFindElement {
GstCaps * caps; GstCaps * caps;
guint mode; guint mode;
guint64 waiting_for_discont_offset;
GstBufferStore * store; GstBufferStore * store;
guint64 stream_length; guint64 stream_length;
gboolean stream_length_available; gboolean stream_length_available;

View file

@ -84,6 +84,8 @@ enum
enum enum
{ {
MODE_NORMAL, /* act as identity */ MODE_NORMAL, /* act as identity */
MODE_TRANSITION, /* wait for the discont between the two
* other modes */
MODE_TYPEFIND /* do typefinding */ MODE_TYPEFIND /* do typefinding */
}; };
@ -277,7 +279,7 @@ gst_type_find_element_src_event (GstPad * pad, GstEvent * event)
{ {
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad)); GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
if (typefind->mode == MODE_TYPEFIND) { if (typefind->mode != MODE_NORMAL) {
/* need to do more? */ /* need to do more? */
gst_data_unref (GST_DATA (event)); gst_data_unref (GST_DATA (event));
return FALSE; return FALSE;
@ -350,10 +352,11 @@ stop_typefinding (GstTypeFindElement * typefind)
typefind->possibilities = NULL; typefind->possibilities = NULL;
} }
typefind->mode = MODE_NORMAL; typefind->mode = MODE_TRANSITION;
if (push_cached_buffers) { if (!push_cached_buffers) {
GstBuffer *buffer; gst_buffer_store_clear (typefind->store);
} else {
guint size = gst_buffer_store_get_size (typefind->store, 0); guint size = gst_buffer_store_get_size (typefind->store, 0);
GST_DEBUG_OBJECT (typefind, "seeking back to current position %u", size); GST_DEBUG_OBJECT (typefind, "seeking back to current position %u", size);
@ -362,18 +365,31 @@ stop_typefinding (GstTypeFindElement * typefind)
size))) { size))) {
GST_WARNING_OBJECT (typefind, GST_WARNING_OBJECT (typefind,
"could not seek to required position %u, hope for the best", size); "could not seek to required position %u, hope for the best", size);
typefind->mode = MODE_NORMAL;
gst_buffer_store_clear (typefind->store);
} else {
typefind->waiting_for_discont_offset = size;
} }
}
}
static void
push_buffer_store (GstTypeFindElement * typefind)
{
guint size = gst_buffer_store_get_size (typefind->store, 0);
GstBuffer *buffer;
gst_pad_push (typefind->src, GST_DATA (gst_event_new_discontinuous (TRUE, gst_pad_push (typefind->src, GST_DATA (gst_event_new_discontinuous (TRUE,
GST_FORMAT_DEFAULT, (guint64) 0, GST_FORMAT_BYTES, (guint64) 0, GST_FORMAT_DEFAULT, (guint64) 0, GST_FORMAT_BYTES, (guint64) 0,
GST_FORMAT_UNDEFINED))); GST_FORMAT_UNDEFINED)));
if (size if (size && (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
&& (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
GST_DEBUG_OBJECT (typefind, "pushing cached data (%u bytes)", size); GST_DEBUG_OBJECT (typefind, "pushing cached data (%u bytes)", size);
gst_pad_push (typefind->src, GST_DATA (buffer)); gst_pad_push (typefind->src, GST_DATA (buffer));
} else { } else {
/* FIXME: shouldn't we throw an error here? */
size = 0; size = 0;
} }
}
gst_buffer_store_clear (typefind->store); gst_buffer_store_clear (typefind->store);
} }
@ -416,8 +432,8 @@ gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
TypeFindEntry *entry; TypeFindEntry *entry;
GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad)); GstTypeFindElement *typefind = GST_TYPE_FIND_ELEMENT (GST_PAD_PARENT (pad));
if (typefind->mode == MODE_TYPEFIND) { switch (typefind->mode) {
/* need to do more? */ case MODE_TYPEFIND:
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_EOS: case GST_EVENT_EOS:
/* this should only happen when we got all available data */ /* this should only happen when we got all available data */
@ -428,13 +444,14 @@ gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
GST_INFO_OBJECT (typefind, GST_INFO_OBJECT (typefind,
"'%s' is the best typefind left after we got all data, using it now (probability %u)", "'%s' is the best typefind left after we got all data, using it now (probability %u)",
GST_PLUGIN_FEATURE_NAME (entry->factory), entry->probability); GST_PLUGIN_FEATURE_NAME (entry->factory), entry->probability);
g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE], 0, g_signal_emit (typefind, gst_type_find_element_signals[HAVE_TYPE],
entry->probability, entry->caps); 0, entry->probability, entry->caps);
stop_typefinding (typefind); stop_typefinding (typefind);
gst_pad_event_default (pad, event); gst_pad_event_default (pad, event);
} else { } else {
gst_pad_event_default (pad, event); gst_pad_event_default (pad, event);
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL)); GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL),
(NULL));
stop_typefinding (typefind); stop_typefinding (typefind);
} }
break; break;
@ -442,7 +459,28 @@ gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
gst_data_unref (GST_DATA (event)); gst_data_unref (GST_DATA (event));
break; break;
} }
break;
case MODE_TRANSITION:
if (GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS) {
if (GST_EVENT_DISCONT_NEW_MEDIA (event)) {
start_typefinding (typefind);
gst_event_unref (event);
} else { } else {
guint64 off;
if (gst_event_discont_get_value (event, GST_FORMAT_BYTES, &off) &&
off == typefind->waiting_for_discont_offset) {
typefind->mode = MODE_NORMAL;
push_buffer_store (typefind);
} else {
gst_event_unref (event);
}
}
} else {
gst_event_unref (event);
}
break;
case MODE_NORMAL:
if (GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS && if (GST_EVENT_TYPE (event) == GST_EVENT_DISCONTINUOUS &&
GST_EVENT_DISCONT_NEW_MEDIA (event)) { GST_EVENT_DISCONT_NEW_MEDIA (event)) {
start_typefinding (typefind); start_typefinding (typefind);
@ -450,6 +488,9 @@ gst_type_find_element_handle_event (GstPad * pad, GstEvent * event)
} else { } else {
gst_pad_event_default (pad, event); gst_pad_event_default (pad, event);
} }
break;
default:
g_assert_not_reached ();
} }
} }
static guint8 * static guint8 *
@ -537,6 +578,9 @@ gst_type_find_element_chain (GstPad * pad, GstData * data)
case MODE_NORMAL: case MODE_NORMAL:
gst_pad_push (typefind->src, data); gst_pad_push (typefind->src, data);
return; return;
case MODE_TRANSITION:
gst_data_unref (data);
return;
case MODE_TYPEFIND:{ case MODE_TYPEFIND:{
guint64 current_offset; guint64 current_offset;

View file

@ -53,6 +53,7 @@ struct _GstTypeFindElement {
GstCaps * caps; GstCaps * caps;
guint mode; guint mode;
guint64 waiting_for_discont_offset;
GstBufferStore * store; GstBufferStore * store;
guint64 stream_length; guint64 stream_length;
gboolean stream_length_available; gboolean stream_length_available;