From 680eb51b686041cc040f4f0c2a9fa8c944074ff6 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 26 Jul 2010 15:51:49 +0200 Subject: [PATCH] matroskademux: additional parse recovery In particular, upon parse failure in one cluster, we may forego remaining content and try resuming from next cluster onwards. Fixes #620790. --- gst/matroska/matroska-demux.c | 29 +++++++++++++++++++++++++++-- gst/matroska/matroska-demux.h | 1 + 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index 9247805..ab0fe04 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -424,6 +424,7 @@ gst_matroska_demux_reset (GstElement * element) demux->offset = 0; demux->cluster_time = GST_CLOCK_TIME_NONE; demux->cluster_offset = 0; + demux->next_cluster_offset = 0; demux->index_offset = 0; demux->seekable = FALSE; demux->need_newsegment = FALSE; @@ -5413,6 +5414,23 @@ gst_matroska_demux_check_read_size (GstMatroskaDemux * demux, guint64 bytes) } } +/* returns TRUE if we truely are in error state, and should give up */ +static inline gboolean +gst_matroska_demux_check_parse_error (GstMatroskaDemux * demux) +{ + if (!demux->streaming && demux->next_cluster_offset > 0) { + /* just repositioning to where next cluster should be and try from there */ + GST_WARNING_OBJECT (demux, "parse error, trying next cluster expected at %" + G_GUINT64_FORMAT, demux->next_cluster_offset); + demux->offset = demux->next_cluster_offset; + demux->next_cluster_offset = 0; + return FALSE; + } else { + /* nowhere to try next, give up */ + return TRUE; + } +} + /* initializes @ebml with @bytes from input stream at current offset. * Returns UNEXPECTED if insufficient available, * ERROR if too much was attempted to read. */ @@ -5662,6 +5680,9 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id, demux->seek_block = 0; } demux->seek_first = FALSE; + /* record next cluster for recovery */ + if (read != G_MAXUINT64) + demux->next_cluster_offset = demux->cluster_offset + read; /* eat cluster prefix */ gst_matroska_demux_flush (demux, needed); break; @@ -5845,8 +5866,12 @@ gst_matroska_demux_loop (GstPad * pad) ret = gst_matroska_demux_peek_id_length_pull (demux, &id, &length, &needed); if (ret == GST_FLOW_UNEXPECTED) goto eos; - if (ret != GST_FLOW_OK) - goto pause; + if (ret != GST_FLOW_OK) { + if (gst_matroska_demux_check_parse_error (demux)) + goto pause; + else + return; + } GST_LOG_OBJECT (demux, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, " "size %" G_GUINT64_FORMAT ", needed %d", demux->offset, id, diff --git a/gst/matroska/matroska-demux.h b/gst/matroska/matroska-demux.h index f796428..b31f79c 100644 --- a/gst/matroska/matroska-demux.h +++ b/gst/matroska/matroska-demux.h @@ -114,6 +114,7 @@ typedef struct _GstMatroskaDemux { GstClockTime cluster_time; guint64 cluster_offset; guint64 first_cluster_offset; + guint64 next_cluster_offset; /* push based mode usual suspects */ GstAdapter *adapter; -- 2.7.4