diff options
Diffstat (limited to 'gst/matroska/ebml-read.c')
-rw-r--r-- | gst/matroska/ebml-read.c | 127 |
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) |