mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-18 07:47:17 +00:00
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:
parent
8990398733
commit
375976c847
2 changed files with 33 additions and 5 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
Loading…
Reference in a new issue