diff options
author | Tim-Philipp Müller <tim.muller@collabora.co.uk> | 2009-07-21 19:46:55 +0100 |
---|---|---|
committer | Tim-Philipp Müller <tim.muller@collabora.co.uk> | 2009-07-21 19:58:04 +0100 |
commit | 375976c847b80ab40ff30e1e5cef91ff12bddf50 (patch) | |
tree | 509bfafb8ecae5193adabcc7001ae48f6e394cb8 /ext | |
parent | 89903987332864891691e511b8ef56022ac85ea4 (diff) |
flacdec: fix intermittent FLAC__STREAM_DECODER_ABORTED errors when seeking
When seeking in a local flac file (ie. operating pull-based), the decoder
would often just error out after the loop function sees a DECODER_ABORTED
status. This, however, is the read callback's way of telling our loop
function that pull_range failed and streaming should stop, in this case
because of the flush-start event that the seek handler pushed upstream
from the seeking thread. Handle this slightly better by storing the last
flow return from pull_range, so the loop function can evaluate it properly
when it encounters a DECODER_ABORTED and take the right action.
Fixes #578612.
Diffstat (limited to 'ext')
-rw-r--r-- | ext/flac/gstflacdec.c | 36 | ||||
-rw-r--r-- | ext/flac/gstflacdec.h | 2 |
2 files changed, 33 insertions, 5 deletions
diff --git a/ext/flac/gstflacdec.c b/ext/flac/gstflacdec.c index 3f9c75f4..4d047021 100644 --- a/ext/flac/gstflacdec.c +++ b/ext/flac/gstflacdec.c @@ -773,15 +773,25 @@ static FLAC__StreamDecoderReadStatus gst_flac_dec_read_seekable (const FLAC__StreamDecoder * decoder, FLAC__byte buffer[], size_t * bytes, void *client_data) { + GstFlowReturn flow; GstFlacDec *flacdec; - GstBuffer *buf; flacdec = GST_FLAC_DEC (client_data); - if (gst_pad_pull_range (flacdec->sinkpad, flacdec->offset, *bytes, - &buf) != GST_FLOW_OK) - return FLAC__STREAM_DECODER_READ_STATUS_ABORT; + flow = gst_pad_pull_range (flacdec->sinkpad, flacdec->offset, *bytes, &buf); + + GST_PAD_STREAM_LOCK (flacdec->sinkpad); + flacdec->pull_flow = flow; + GST_PAD_STREAM_UNLOCK (flacdec->sinkpad); + + if (G_UNLIKELY (flow != GST_FLOW_OK)) { + GST_INFO_OBJECT (flacdec, "pull_range flow: %s", gst_flow_get_name (flow)); + if (flow == GST_FLOW_UNEXPECTED) + return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; + else + return FLAC__STREAM_DECODER_READ_STATUS_ABORT; + } GST_DEBUG_OBJECT (flacdec, "Read %d bytes at %" G_GUINT64_FORMAT, GST_BUFFER_SIZE (buf), flacdec->offset); @@ -1152,9 +1162,23 @@ analyze_state: goto eos_and_pause; } + /* gst_flac_dec_read_seekable() returned ABORTED */ + case FLAC__STREAM_DECODER_ABORTED: + { + GST_INFO_OBJECT (flacdec, "read aborted: last pull_range flow = %s", + gst_flow_get_name (flacdec->pull_flow)); + if (!GST_FLOW_IS_FATAL (flacdec->pull_flow)) { + /* it seems we need to flush the decoder here to reset the decoder + * state after the abort for FLAC__stream_decoder_seek_absolute() + * to work properly */ + GST_DEBUG_OBJECT (flacdec, "flushing decoder to reset decoder state"); + FLAC__stream_decoder_flush (flacdec->seekable_decoder); + goto pause; + } + /* fall through */ + } case FLAC__STREAM_DECODER_OGG_ERROR: case FLAC__STREAM_DECODER_SEEK_ERROR: - case FLAC__STREAM_DECODER_ABORTED: case FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR: case FLAC__STREAM_DECODER_UNINITIALIZED: default:{ @@ -1782,8 +1806,10 @@ gst_flac_dec_handle_seek_event (GstFlacDec * flacdec, GstEvent * event) * callbacks that need to behave differently when seeking */ flacdec->seeking = TRUE; + GST_LOG_OBJECT (flacdec, "calling seek_absolute"); seek_ok = FLAC__stream_decoder_seek_absolute (flacdec->seekable_decoder, flacdec->segment.last_stop); + GST_LOG_OBJECT (flacdec, "done with seek_absolute, seek_ok=%d", seek_ok); flacdec->seeking = FALSE; diff --git a/ext/flac/gstflacdec.h b/ext/flac/gstflacdec.h index a9daf3e9..e6a76bbb 100644 --- a/ext/flac/gstflacdec.h +++ b/ext/flac/gstflacdec.h @@ -74,6 +74,8 @@ struct _GstFlacDec { GstEvent *start_segment; GstTagList *tags; + GstFlowReturn pull_flow; /* last flow from pull_range */ /* STREAM_LOCK */ + GstFlowReturn last_flow; /* the last flow return received from either * gst_pad_push or gst_pad_buffer_alloc */ |