summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>2012-03-16 18:23:29 +0100
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>2012-03-19 12:02:42 +0100
commit19121249bd5dcfca440f276e2e05faf84245002c (patch)
tree12266f1f906c6253ec33ea99a202f6d4c24c28f5 /ext
parente300675384f5a70f27508274201462714a2e4bb5 (diff)
flacdec: improve error handling and resilience
... by noting that one occurred in the first place, and then appropriately ignoring some transient ones.
Diffstat (limited to 'ext')
-rw-r--r--ext/flac/gstflacdec.c37
-rw-r--r--ext/flac/gstflacdec.h2
2 files changed, 37 insertions, 2 deletions
diff --git a/ext/flac/gstflacdec.c b/ext/flac/gstflacdec.c
index 10f8916c6..19a866cea 100644
--- a/ext/flac/gstflacdec.c
+++ b/ext/flac/gstflacdec.c
@@ -542,6 +542,26 @@ gst_flac_dec_scan_for_last_block (GstFlacDec * flacdec, gint64 * samples)
}
}
+static gboolean
+gst_flac_dec_handle_decoder_error (GstFlacDec * dec, gboolean msg)
+{
+ gboolean ret;
+
+ dec->error_count++;
+ if (dec->error_count > 10) {
+ if (msg)
+ GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), (NULL));
+ dec->last_flow = GST_FLOW_ERROR;
+ ret = TRUE;
+ } else {
+ GST_DEBUG_OBJECT (dec, "ignoring error for now at count %d",
+ dec->error_count);
+ ret = FALSE;
+ }
+
+ return ret;
+}
+
static void
gst_flac_extract_picture_buffer (GstFlacDec * dec,
const FLAC__StreamMetadata * metadata)
@@ -672,8 +692,8 @@ gst_flac_dec_error_cb (const FLAC__StreamDecoder * d,
break;
}
- GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("%s (%d)", error, status));
- dec->last_flow = GST_FLOW_ERROR;
+ if (gst_flac_dec_handle_decoder_error (dec, FALSE))
+ GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("%s (%d)", error, status));
}
static FLAC__StreamDecoderSeekStatus
@@ -1023,6 +1043,9 @@ gst_flac_dec_write (GstFlacDec * flacdec, const FLAC__Frame * frame,
g_assert_not_reached ();
}
+ if (flacdec->error_count)
+ flacdec->error_count--;
+
if (!flacdec->seeking) {
GST_DEBUG_OBJECT (flacdec, "pushing %d samples at offset %" G_GINT64_FORMAT
" (%" GST_TIME_FORMAT " + %" GST_TIME_FORMAT ")",
@@ -1503,6 +1526,15 @@ gst_flac_dec_chain (GstPad * pad, GstBuffer * buf)
if (!FLAC__stream_decoder_process_single (dec->decoder)) {
GST_DEBUG_OBJECT (dec, "process_single failed");
}
+
+ if (FLAC__stream_decoder_get_state (dec->decoder) ==
+ FLAC__STREAM_DECODER_ABORTED) {
+ GST_WARNING_OBJECT (dec, "Read callback caused internal abort");
+ /* allow recovery */
+ gst_adapter_clear (dec->adapter);
+ FLAC__stream_decoder_flush (dec->decoder);
+ gst_flac_dec_handle_decoder_error (dec, TRUE);
+ }
} else {
GST_DEBUG_OBJECT (dec, "don't have all headers yet");
}
@@ -2154,6 +2186,7 @@ gst_flac_dec_change_state (GstElement * element, GstStateChange transition)
flacdec->width = 0;
flacdec->sample_rate = 0;
gst_segment_init (&flacdec->segment, GST_FORMAT_DEFAULT);
+ flacdec->error_count = 0;
break;
default:
break;
diff --git a/ext/flac/gstflacdec.h b/ext/flac/gstflacdec.h
index 835bdbd8c..f3882a2b0 100644
--- a/ext/flac/gstflacdec.h
+++ b/ext/flac/gstflacdec.h
@@ -88,6 +88,8 @@ struct _GstFlacDec {
guint16 max_blocksize;
gint64 cur_granulepos; /* only used in framed mode (flac-in-ogg) */
+
+ gint error_count;
};
struct _GstFlacDecClass {