summaryrefslogtreecommitdiffstats
path: root/gst/matroska/ebml-read.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/matroska/ebml-read.c')
-rw-r--r--gst/matroska/ebml-read.c127
1 files changed, 77 insertions, 50 deletions
diff --git a/gst/matroska/ebml-read.c b/gst/matroska/ebml-read.c
index 6face5ad..0ec5aac3 100644
--- a/gst/matroska/ebml-read.c
+++ b/gst/matroska/ebml-read.c
@@ -115,6 +115,64 @@ gst_ebml_read_change_state (GstElement * element)
}
/*
+ * Event handler. Basic:
+ * - EOS: end-of-file, stop processing, forward EOS.
+ * - Interrupt: stop processing.
+ * - Discont: shouldn't be handled here but in the seek handler. Error.
+ * - Flush: ignore, since we check for flush flags manually. Don't forward.
+ * - Others: warn, ignore.
+ * Return value indicates whether to continue processing.
+ */
+
+static gboolean
+gst_ebml_read_use_event (GstEbmlRead * ebml, GstEvent * event)
+{
+ if (!event) {
+ GST_ELEMENT_ERROR (ebml, RESOURCE, READ, (NULL), (NULL));
+ return FALSE;
+ }
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_EOS:
+ gst_pad_event_default (ebml->sinkpad, event);
+ return FALSE;
+
+ case GST_EVENT_INTERRUPT:
+ gst_event_unref (event);
+ return FALSE;
+
+ case GST_EVENT_DISCONTINUOUS:
+ GST_WARNING_OBJECT (ebml, "Unexected discont - might lose sync");
+ gst_pad_event_default (ebml->sinkpad, event);
+ return TRUE;
+
+ case GST_EVENT_FLUSH:
+ gst_event_unref (event);
+ return TRUE;
+
+ default:
+ GST_WARNING ("don't know how to handle event %d", GST_EVENT_TYPE (event));
+ gst_pad_event_default (ebml->sinkpad, event);
+ return FALSE;
+ }
+
+ /* happy */
+ g_assert_not_reached ();
+ return FALSE;
+}
+
+static gboolean
+gst_ebml_read_handle_event (GstEbmlRead * ebml)
+{
+ GstEvent *event = NULL;
+ guint32 remaining;
+
+ gst_bytestream_get_status (ebml->bs, &remaining, &event);
+
+ return gst_ebml_read_use_event (ebml, event);
+}
+
+/*
* Return: the amount of levels in the hierarchy that the
* current element lies higher than the previous one.
* The opposite isn't done - that's auto-done using master
@@ -155,25 +213,8 @@ gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up)
guint32 total;
while (gst_bytestream_peek_bytes (ebml->bs, &data, 1) != 1) {
- GstEvent *event = NULL;
- guint32 remaining;
-
- /* Here, we might encounter EOS */
- gst_bytestream_get_status (ebml->bs, &remaining, &event);
- if (event && GST_IS_EVENT (event)) {
- gboolean eos = (GST_EVENT_TYPE (event) == GST_EVENT_EOS);
-
- gst_pad_event_default (ebml->sinkpad, event);
- if (eos)
- return FALSE;
- } else {
- guint64 pos = gst_bytestream_tell (ebml->bs);
-
- gst_event_unref (event);
- GST_ELEMENT_ERROR (ebml, RESOURCE, READ, (NULL),
- ("Read error at position %llu (0x%llx)", pos, pos));
+ if (!gst_ebml_read_handle_event (ebml))
return -1;
- }
}
total = data[0];
while (read <= 4 && !(total & len_mask)) {
@@ -189,12 +230,9 @@ gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up)
return -1;
}
- if (gst_bytestream_peek_bytes (ebml->bs, &data, read) != read) {
- guint64 pos = gst_bytestream_tell (ebml->bs);
-
- GST_ELEMENT_ERROR (ebml, RESOURCE, READ, (NULL),
- ("Read error at position %llu (0x%llx)", pos, pos));
- return -1;
+ while (gst_bytestream_peek_bytes (ebml->bs, &data, read) != read) {
+ if (!gst_ebml_read_handle_event (ebml))
+ return -1;
}
while (n < read)
total = (total << 8) | data[n++];
@@ -220,12 +258,9 @@ gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length)
gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
guint64 total;
- if (gst_bytestream_peek_bytes (ebml->bs, &data, 1) != 1) {
- guint64 pos = gst_bytestream_tell (ebml->bs);
-
- GST_ELEMENT_ERROR (ebml, RESOURCE, READ, (NULL),
- ("Read error at position %llu (0x%llx)", pos, pos));
- return -1;
+ while (gst_bytestream_peek_bytes (ebml->bs, &data, 1) != 1) {
+ if (!gst_ebml_read_handle_event (ebml))
+ return -1;
}
total = data[0];
while (read <= 8 && !(total & len_mask)) {
@@ -243,12 +278,9 @@ gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length)
if ((total &= (len_mask - 1)) == len_mask - 1)
num_ffs++;
- if (gst_bytestream_peek_bytes (ebml->bs, &data, read) != read) {
- guint64 pos = gst_bytestream_tell (ebml->bs);
-
- GST_ELEMENT_ERROR (ebml, RESOURCE, READ, (NULL),
- ("Read error at position %llu (0x%llx)", pos, pos));
- return -1;
+ while (gst_bytestream_peek_bytes (ebml->bs, &data, read) != read) {
+ if (!gst_ebml_read_handle_event (ebml))
+ return -1;
}
while (n < read) {
if (data[n] == 0xff)
@@ -276,13 +308,8 @@ gst_ebml_read_element_data (GstEbmlRead * ebml, guint64 length)
GstBuffer *buf = NULL;
if (gst_bytestream_peek (ebml->bs, &buf, length) != length) {
- guint64 pos = gst_bytestream_tell (ebml->bs);
-
- GST_ELEMENT_ERROR (ebml, RESOURCE, READ, (NULL),
- ("Read error at position %llu (0x%llx)", pos, pos));
- if (buf)
- gst_buffer_unref (buf);
- return NULL;
+ if (!gst_ebml_read_handle_event (ebml))
+ return NULL;
}
gst_bytestream_flush_fast (ebml->bs, length);
@@ -323,8 +350,10 @@ gst_ebml_read_seek (GstEbmlRead * ebml, guint64 offset)
/* first, flush remaining buffers */
gst_bytestream_get_status (ebml->bs, &remaining, &event);
if (event) {
- g_warning ("Unexpected event before seek");
- gst_event_unref (event);
+ GST_WARNING ("Unexpected event before seek");
+ if (!gst_ebml_read_use_event (ebml, event))
+ return NULL;
+ event = NULL;
}
if (remaining)
gst_bytestream_flush_fast (ebml->bs, remaining);
@@ -350,10 +379,7 @@ gst_ebml_read_seek (GstEbmlRead * ebml, guint64 offset)
GST_WARNING ("No discontinuity event after seek - seek failed");
break;
} else if (GST_EVENT_TYPE (event) != GST_EVENT_DISCONTINUOUS) {
- GstEventType type = GST_EVENT_TYPE (event);
-
- gst_pad_event_default (ebml->sinkpad, event);
- if (type == GST_EVENT_EOS || type == GST_EVENT_INTERRUPT)
+ if (!gst_ebml_read_use_event (ebml, event))
return NULL;
event = NULL;
}
@@ -386,7 +412,8 @@ gst_ebml_read_skip (GstEbmlRead * ebml)
gst_bytestream_get_status (ebml->bs, &remaining, &event);
if (event) {
g_warning ("Unexpected event before skip");
- gst_event_unref (event);
+ if (!gst_ebml_read_use_event (ebml, event))
+ return FALSE;
}
if (remaining >= length)