From: Ronald S. Bultje Date: Fri, 3 Dec 2004 21:08:17 +0000 (+0000) Subject: gst/matroska/: Disgustingly evil hack for working around INTERRUPT events and their... X-Git-Tag: BRANCH-GSTREAMER-0_8-ROOT~304 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=75ff7535dda96f7b271b15ddc4486245291f9b1d;p=platform%2Fupstream%2Fgst-plugins-good.git gst/matroska/: Disgustingly evil hack for working around INTERRUPT events and their extremely annoying habit of being... Original commit message from CVS: * gst/matroska/ebml-read.c: (gst_ebml_read_class_init), (gst_ebml_read_init), (gst_ebml_read_use_event), (gst_ebml_read_element_id), (gst_ebml_peek_id), (gst_ebml_read_seek), (gst_ebml_read_skip), (gst_ebml_read_reserve), (gst_ebml_read_buffer), (gst_ebml_read_master): * gst/matroska/ebml-read.h: * gst/matroska/matroska-demux.c: (gst_matroska_demux_parse_contents), (gst_matroska_demux_loop_stream), (gst_matroska_demux_audio_caps): Disgustingly evil hack for working around INTERRUPT events and their extremely annoying habit of being a pain in the ass. We simply peek a cluster before reading any of it. --- diff --git a/ChangeLog b/ChangeLog index fd74d8881..4baa93ad7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2004-12-03 Ronald S. Bultje + + * gst/matroska/ebml-read.c: (gst_ebml_read_class_init), + (gst_ebml_read_init), (gst_ebml_read_use_event), + (gst_ebml_read_element_id), (gst_ebml_peek_id), + (gst_ebml_read_seek), (gst_ebml_read_skip), + (gst_ebml_read_reserve), (gst_ebml_read_buffer), + (gst_ebml_read_master): + * gst/matroska/ebml-read.h: + * gst/matroska/matroska-demux.c: + (gst_matroska_demux_parse_contents), + (gst_matroska_demux_loop_stream), (gst_matroska_demux_audio_caps): + Disgustingly evil hack for working around INTERRUPT events and + their extremely annoying habit of being a pain in the ass. We + simply peek a cluster before reading any of it. + 2004-12-03 Ronald S. Bultje * ext/musepack/gstmusepackdec.cpp: diff --git a/gst/matroska/ebml-read.c b/gst/matroska/ebml-read.c index 72a3bb7e5..c9e9828f8 100644 --- a/gst/matroska/ebml-read.c +++ b/gst/matroska/ebml-read.c @@ -28,6 +28,9 @@ #include "ebml-read.h" #include "ebml-ids.h" +GST_DEBUG_CATEGORY_STATIC (ebmlread_debug); +#define GST_CAT_DEFAULT ebmlread_debug + enum { /* FILL ME */ @@ -73,6 +76,9 @@ gst_ebml_read_class_init (GstEbmlReadClass * klass) parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + GST_DEBUG_CATEGORY_INIT (ebmlread_debug, "ebmlread", + 0, "EBML stream helper class"); + gstelement_class->change_state = gst_ebml_read_change_state; } @@ -82,6 +88,7 @@ gst_ebml_read_init (GstEbmlRead * ebml) ebml->sinkpad = NULL; ebml->bs = NULL; ebml->level = NULL; + ebml->id_cache = 0; } static GstElementStateReturn @@ -132,6 +139,8 @@ gst_ebml_read_use_event (GstEbmlRead * ebml, GstEvent * event) return FALSE; } + GST_LOG ("Received event of type %d", GST_EVENT_TYPE (event)); + switch (GST_EVENT_TYPE (event)) { case GST_EVENT_EOS: gst_pad_event_default (ebml->sinkpad, event); @@ -143,7 +152,7 @@ gst_ebml_read_use_event (GstEbmlRead * ebml, GstEvent * event) case GST_EVENT_DISCONTINUOUS: GST_WARNING_OBJECT (ebml, "Unexpected discont - might lose sync"); - gst_pad_event_default (ebml->sinkpad, event); + gst_event_unref (event); return TRUE; case GST_EVENT_FLUSH: @@ -212,6 +221,14 @@ gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up) gint len_mask = 0x80, read = 1, n = 1; guint32 total; + if (ebml->id_cache) { + *id = ebml->id_cache; + if (level_up) + *level_up = 0; + + return 0; + } + while (gst_bytestream_peek_bytes (ebml->bs, &data, 1) != 1) { if (!gst_ebml_read_handle_event (ebml)) return -1; @@ -237,13 +254,15 @@ gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up) while (n < read) total = (total << 8) | data[n++]; - *id = total; + *id = ebml->id_cache = total; /* level */ if (level_up) *level_up = gst_ebml_read_element_level_up (ebml); - return read; + gst_bytestream_flush_fast (ebml->bs, read); + + return 0; } /* @@ -330,7 +349,7 @@ gst_ebml_peek_id (GstEbmlRead * ebml, guint * level_up) g_assert (level_up); - if (gst_ebml_read_element_id (ebml, &id, level_up) <= 0) + if (gst_ebml_read_element_id (ebml, &id, level_up) < 0) return 0; return id; @@ -385,6 +404,9 @@ gst_ebml_read_seek (GstEbmlRead * ebml, guint64 offset) } } + /* at the end of a seek, we have no cached ID anymore */ + ebml->id_cache = 0; + return event; } @@ -416,8 +438,12 @@ gst_ebml_read_skip (GstEbmlRead * ebml) return FALSE; } - if (remaining >= length) - return gst_bytestream_flush (ebml->bs, length); + if (remaining >= length) { + ebml->id_cache = 0; + gst_bytestream_flush_fast (ebml->bs, length); + + return TRUE; + } if (!(event = gst_ebml_read_seek (ebml, gst_bytestream_tell (ebml->bs) + length))) { @@ -425,7 +451,40 @@ gst_ebml_read_skip (GstEbmlRead * ebml) } gst_event_unref (event); + ebml->id_cache = 0; + + return TRUE; +} + +/* + * Make sure there's one whole next chunk available + * for uninterrupted reading. + */ + +gboolean +gst_ebml_read_reserve (GstEbmlRead * ebml) +{ + guint64 length; + gint bytes; + guint8 *data; + guint32 id; + + /* make sure the ID is cached */ + if (gst_ebml_read_element_id (ebml, &id, NULL) < 0) + return FALSE; + + /* now we can peek the length */ + if ((bytes = gst_ebml_read_element_length (ebml, &length)) < 0) + return FALSE; + length += bytes; + + /* now check if we have that amount available */ + while (gst_bytestream_peek_bytes (ebml->bs, &data, length) != length) { + if (!gst_ebml_read_handle_event (ebml)) + return FALSE; + } + /* yes, available */ return TRUE; } @@ -446,6 +505,7 @@ gst_ebml_read_buffer (GstEbmlRead * ebml, guint32 * id, GstBuffer ** buf) if ((bytes = gst_ebml_read_element_length (ebml, &length)) < 0) return FALSE; gst_bytestream_flush_fast (ebml->bs, bytes); + ebml->id_cache = 0; return ((*buf = gst_ebml_read_element_data (ebml, length)) != NULL); } @@ -662,6 +722,7 @@ gst_ebml_read_master (GstEbmlRead * ebml, guint32 * id) level->start = gst_bytestream_tell (ebml->bs); level->length = length; ebml->level = g_list_append (ebml->level, level); + ebml->id_cache = 0; return TRUE; } diff --git a/gst/matroska/ebml-read.h b/gst/matroska/ebml-read.h index d78d13ce7..e9528955a 100644 --- a/gst/matroska/ebml-read.h +++ b/gst/matroska/ebml-read.h @@ -53,6 +53,9 @@ typedef struct _GstEbmlRead { GstByteStream *bs; GList *level; + + /* cache of ID (peeking) */ + guint32 id_cache; } GstEbmlRead; typedef struct _GstEbmlReadClass { @@ -66,6 +69,7 @@ guint32 gst_ebml_peek_id (GstEbmlRead *ebml, GstEvent *gst_ebml_read_seek (GstEbmlRead *ebml, guint64 offset); gboolean gst_ebml_read_skip (GstEbmlRead *ebml); +gboolean gst_ebml_read_reserve (GstEbmlRead *ebml); gboolean gst_ebml_read_buffer (GstEbmlRead *ebml, guint32 *id, GstBuffer **buf); diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index 9b32c5f5b..5bfcecf5e 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -2142,6 +2142,7 @@ gst_matroska_demux_parse_contents (GstMatroskaDemux * demux) case GST_MATROSKA_ID_TAGS:{ guint level_up = demux->level_up; guint64 before_pos, length; + guint32 id_cache = ebml->id_cache; GstEbmlLevel *level; GstEvent *event; @@ -2224,6 +2225,7 @@ gst_matroska_demux_parse_contents (GstMatroskaDemux * demux) return FALSE; gst_event_unref (event); demux->level_up = level_up; + ebml->id_cache = id_cache; break; } @@ -2333,6 +2335,10 @@ gst_matroska_demux_loop_stream (GstMatroskaDemux * demux) demux->state = GST_MATROSKA_DEMUX_STATE_DATA; gst_element_no_more_pads (GST_ELEMENT (demux)); } else { + if (!gst_ebml_read_reserve (ebml)) { + res = FALSE; + break; + } if (!gst_ebml_read_master (ebml, &id)) { res = FALSE; break; @@ -2670,7 +2676,6 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext * audiocontext, } } else { GST_WARNING ("Unknown codec '%s', cannot build Caps", codec_id); - g_print ("Codec=%s\n", codec_id); return NULL; }