matroska-demux: Don't handle parse errors at the end of file as an error

But only if they happen after the Matroska segment.

https://bugzilla.gnome.org/show_bug.cgi?id=735833
This commit is contained in:
Sebastian Dröge 2014-09-04 16:21:20 +03:00
parent 4b697df494
commit a3a5530518
2 changed files with 28 additions and 10 deletions

View file

@ -3890,7 +3890,7 @@ gst_matroska_demux_check_read_size (GstMatroskaDemux * demux, guint64 bytes)
} }
/* returns TRUE if we truely are in error state, and should give up */ /* returns TRUE if we truely are in error state, and should give up */
static inline gboolean static inline GstFlowReturn
gst_matroska_demux_check_parse_error (GstMatroskaDemux * demux) gst_matroska_demux_check_parse_error (GstMatroskaDemux * demux)
{ {
if (!demux->streaming && demux->next_cluster_offset > 0) { if (!demux->streaming && demux->next_cluster_offset > 0) {
@ -3899,22 +3899,23 @@ gst_matroska_demux_check_parse_error (GstMatroskaDemux * demux)
G_GUINT64_FORMAT, demux->next_cluster_offset); G_GUINT64_FORMAT, demux->next_cluster_offset);
demux->common.offset = demux->next_cluster_offset; demux->common.offset = demux->next_cluster_offset;
demux->next_cluster_offset = 0; demux->next_cluster_offset = 0;
return FALSE; return GST_FLOW_OK;
} else { } else {
gint64 pos; gint64 pos;
GstFlowReturn ret;
/* sigh, one last attempt above and beyond call of duty ...; /* sigh, one last attempt above and beyond call of duty ...;
* search for cluster mark following current pos */ * search for cluster mark following current pos */
pos = demux->common.offset; pos = demux->common.offset;
GST_WARNING_OBJECT (demux, "parse error, looking for next cluster"); GST_WARNING_OBJECT (demux, "parse error, looking for next cluster");
if (gst_matroska_demux_search_cluster (demux, &pos) != GST_FLOW_OK) { if ((ret = gst_matroska_demux_search_cluster (demux, &pos)) != GST_FLOW_OK) {
/* did not work, give up */ /* did not work, give up */
return TRUE; return ret;
} else { } else {
GST_DEBUG_OBJECT (demux, "... found at %" G_GUINT64_FORMAT, pos); GST_DEBUG_OBJECT (demux, "... found at %" G_GUINT64_FORMAT, pos);
/* try that position */ /* try that position */
demux->common.offset = pos; demux->common.offset = pos;
return FALSE; return GST_FLOW_OK;
} }
} }
} }
@ -4113,11 +4114,14 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id,
/* eat segment prefix */ /* eat segment prefix */
GST_READ_CHECK (gst_matroska_demux_flush (demux, needed)); GST_READ_CHECK (gst_matroska_demux_flush (demux, needed));
GST_DEBUG_OBJECT (demux, GST_DEBUG_OBJECT (demux,
"Found Segment start at offset %" G_GUINT64_FORMAT, "Found Segment start at offset %" G_GUINT64_FORMAT " with size %"
demux->common.offset); G_GUINT64_FORMAT, demux->common.offset, length);
/* seeks are from the beginning of the segment, /* seeks are from the beginning of the segment,
* after the segment ID/length */ * after the segment ID/length */
demux->common.ebml_segment_start = demux->common.offset; demux->common.ebml_segment_start = demux->common.offset;
if (length == 0)
length = G_MAXUINT64;
demux->common.ebml_segment_length = length;
demux->common.state = GST_MATROSKA_READ_STATE_HEADER; demux->common.state = GST_MATROSKA_READ_STATE_HEADER;
break; break;
default: default:
@ -4385,7 +4389,15 @@ gst_matroska_demux_loop (GstPad * pad)
} else if (ret == GST_FLOW_FLUSHING) { } else if (ret == GST_FLOW_FLUSHING) {
goto pause; goto pause;
} else if (ret != GST_FLOW_OK) { } else if (ret != GST_FLOW_OK) {
if (gst_matroska_demux_check_parse_error (demux)) ret = gst_matroska_demux_check_parse_error (demux);
/* Only handle EOS as no error if we're outside the segment already */
if (ret == GST_FLOW_EOS && (demux->common.ebml_segment_length != G_MAXUINT64
&& demux->common.offset >=
demux->common.ebml_segment_start +
demux->common.ebml_segment_length))
goto eos;
else if (ret != GST_FLOW_OK)
goto pause; goto pause;
else else
return; return;
@ -4552,8 +4564,13 @@ next:
ret = gst_matroska_read_common_peek_id_length_push (&demux->common, ret = gst_matroska_read_common_peek_id_length_push (&demux->common,
GST_ELEMENT_CAST (demux), &id, &length, &needed); GST_ELEMENT_CAST (demux), &id, &length, &needed);
if (G_UNLIKELY (ret != GST_FLOW_OK && ret != GST_FLOW_EOS)) if (G_UNLIKELY (ret != GST_FLOW_OK && ret != GST_FLOW_EOS)) {
if (demux->common.ebml_segment_length != G_MAXUINT64
&& demux->common.offset >=
demux->common.ebml_segment_start + demux->common.ebml_segment_length)
ret = GST_FLOW_EOS;
return ret; return ret;
}
GST_LOG_OBJECT (demux, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, " GST_LOG_OBJECT (demux, "Offset %" G_GUINT64_FORMAT ", Element id 0x%x, "
"size %" G_GUINT64_FORMAT ", needed %d, available %d", "size %" G_GUINT64_FORMAT ", needed %d, available %d",

View file

@ -76,8 +76,9 @@ typedef struct _GstMatroskaReadCommon {
GstToc *toc; GstToc *toc;
gboolean toc_updated; gboolean toc_updated;
/* start-of-segment */ /* start-of-segment and length */
guint64 ebml_segment_start; guint64 ebml_segment_start;
guint64 ebml_segment_length;
/* a cue (index) table */ /* a cue (index) table */
GArray *index; GArray *index;