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.
This commit is contained in:
Tim-Philipp Müller 2009-07-21 19:46:55 +01:00
parent 8990398733
commit 375976c847
2 changed files with 33 additions and 5 deletions

View file

@ -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;

View file

@ -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 */