mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 08:46:40 +00:00
fix typefind discont handling, #153657
Original commit message from CVS: fix typefind discont handling, #153657
This commit is contained in:
parent
3cd8266b12
commit
e45b8c2be6
5 changed files with 193 additions and 90 deletions
13
ChangeLog
13
ChangeLog
|
@ -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:
|
||||||
|
|
|
@ -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_pad_push (typefind->src, GST_DATA (gst_event_new_discontinuous (TRUE,
|
gst_buffer_store_clear (typefind->store);
|
||||||
GST_FORMAT_DEFAULT, (guint64) 0, GST_FORMAT_BYTES, (guint64) 0,
|
|
||||||
GST_FORMAT_UNDEFINED)));
|
|
||||||
if (size
|
|
||||||
&& (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
|
|
||||||
GST_DEBUG_OBJECT (typefind, "pushing cached data (%u bytes)", size);
|
|
||||||
gst_pad_push (typefind->src, GST_DATA (buffer));
|
|
||||||
} else {
|
} else {
|
||||||
size = 0;
|
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_FORMAT_DEFAULT, (guint64) 0, GST_FORMAT_BYTES, (guint64) 0,
|
||||||
|
GST_FORMAT_UNDEFINED)));
|
||||||
|
if (size && (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
|
||||||
|
GST_DEBUG_OBJECT (typefind, "pushing cached data (%u bytes)", size);
|
||||||
|
gst_pad_push (typefind->src, GST_DATA (buffer));
|
||||||
|
} else {
|
||||||
|
/* FIXME: shouldn't we throw an error here? */
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
gst_buffer_store_clear (typefind->store);
|
gst_buffer_store_clear (typefind->store);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,40 +432,65 @@ 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 */
|
||||||
entry =
|
entry =
|
||||||
(TypeFindEntry *) typefind->possibilities ? typefind->
|
(TypeFindEntry *) typefind->possibilities ? typefind->
|
||||||
possibilities->data : NULL;
|
possibilities->data : NULL;
|
||||||
if (entry && entry->probability >= typefind->min_probability) {
|
if (entry && entry->probability >= typefind->min_probability) {
|
||||||
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 {
|
||||||
|
gst_pad_event_default (pad, event);
|
||||||
|
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL),
|
||||||
|
(NULL));
|
||||||
|
stop_typefinding (typefind);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gst_data_unref (GST_DATA (event));
|
||||||
|
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 {
|
||||||
gst_pad_event_default (pad, event);
|
guint64 off;
|
||||||
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
|
|
||||||
stop_typefinding (typefind);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
} else {
|
||||||
default:
|
gst_event_unref (event);
|
||||||
gst_data_unref (GST_DATA (event));
|
}
|
||||||
break;
|
break;
|
||||||
}
|
case MODE_NORMAL:
|
||||||
} else {
|
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);
|
gst_event_unref (event);
|
||||||
gst_event_unref (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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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_pad_push (typefind->src, GST_DATA (gst_event_new_discontinuous (TRUE,
|
gst_buffer_store_clear (typefind->store);
|
||||||
GST_FORMAT_DEFAULT, (guint64) 0, GST_FORMAT_BYTES, (guint64) 0,
|
|
||||||
GST_FORMAT_UNDEFINED)));
|
|
||||||
if (size
|
|
||||||
&& (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
|
|
||||||
GST_DEBUG_OBJECT (typefind, "pushing cached data (%u bytes)", size);
|
|
||||||
gst_pad_push (typefind->src, GST_DATA (buffer));
|
|
||||||
} else {
|
} else {
|
||||||
size = 0;
|
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_FORMAT_DEFAULT, (guint64) 0, GST_FORMAT_BYTES, (guint64) 0,
|
||||||
|
GST_FORMAT_UNDEFINED)));
|
||||||
|
if (size && (buffer = gst_buffer_store_get_buffer (typefind->store, 0, size))) {
|
||||||
|
GST_DEBUG_OBJECT (typefind, "pushing cached data (%u bytes)", size);
|
||||||
|
gst_pad_push (typefind->src, GST_DATA (buffer));
|
||||||
|
} else {
|
||||||
|
/* FIXME: shouldn't we throw an error here? */
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
gst_buffer_store_clear (typefind->store);
|
gst_buffer_store_clear (typefind->store);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,40 +432,65 @@ 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 */
|
||||||
entry =
|
entry =
|
||||||
(TypeFindEntry *) typefind->possibilities ? typefind->
|
(TypeFindEntry *) typefind->possibilities ? typefind->
|
||||||
possibilities->data : NULL;
|
possibilities->data : NULL;
|
||||||
if (entry && entry->probability >= typefind->min_probability) {
|
if (entry && entry->probability >= typefind->min_probability) {
|
||||||
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 {
|
||||||
|
gst_pad_event_default (pad, event);
|
||||||
|
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL),
|
||||||
|
(NULL));
|
||||||
|
stop_typefinding (typefind);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
gst_data_unref (GST_DATA (event));
|
||||||
|
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 {
|
||||||
gst_pad_event_default (pad, event);
|
guint64 off;
|
||||||
GST_ELEMENT_ERROR (typefind, STREAM, TYPE_NOT_FOUND, (NULL), (NULL));
|
|
||||||
stop_typefinding (typefind);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
} else {
|
||||||
default:
|
gst_event_unref (event);
|
||||||
gst_data_unref (GST_DATA (event));
|
}
|
||||||
break;
|
break;
|
||||||
}
|
case MODE_NORMAL:
|
||||||
} else {
|
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);
|
gst_event_unref (event);
|
||||||
gst_event_unref (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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue