diff options
author | Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> | 2012-03-16 18:23:29 +0100 |
---|---|---|
committer | Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> | 2012-03-19 12:02:42 +0100 |
commit | 19121249bd5dcfca440f276e2e05faf84245002c (patch) | |
tree | 12266f1f906c6253ec33ea99a202f6d4c24c28f5 /ext | |
parent | e300675384f5a70f27508274201462714a2e4bb5 (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.c | 37 | ||||
-rw-r--r-- | ext/flac/gstflacdec.h | 2 |
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 { |