demux_lavf: bluray: don't skip stream data when flushing

This code meant to flush demuxer internal buffers by doing a byte seek
to the current position. In theory this shouldn't drop any stream data.
However, if the stream positions mismatch, then avio_seek() (called by
av_seek_frame()) stops being a no-op, and might for example read some
data to skip to the seek target. (This can happen if the distance is
less than SHORT_SEEK_THRESHOLD.)

The positions get out of sync because we drop data at one point (which
is what we _want_ to do). Strictly speaking, the AVIOContext flushing is
done incorrectly, becuase pb->pos points to the start of the buffer, not
the current position. So we have to increment pb->pos by the buffered
amount.

Since there are other weird reasons why the positions might go out of
sync (such as stream_dvd.c dropping buffers itself), and they don't
necessarily need to be in sync in the first place unless AVIOContext has
nothing buffered internally, just use the sledgehammer approach and
correct the position manually.

Also run av_seek_frame() after this. Currently, it shouldn't read
anything, but who knows how that might change with future libavformat
development.

This whole change didn't have any observable effect for me, but I'm
hoping it fixes a reported problem.
This commit is contained in:
wm4 2014-09-29 17:52:11 +02:00
parent 39451732e9
commit b0cb2977ed
1 changed files with 4 additions and 3 deletions

View File

@ -1010,12 +1010,13 @@ redo:
* call the new API instead of relying on av_seek_frame() to do this * call the new API instead of relying on av_seek_frame() to do this
* for us. * for us.
*/ */
av_seek_frame(priv->avfc, 0, stream_tell(demuxer->stream),
AVSEEK_FLAG_BYTE);
// avio_flush() is designed for write-only streams, and does the wrong // avio_flush() is designed for write-only streams, and does the wrong
// thing when reading. Flush it manually instead. // thing when reading. Flush it manually instead.
priv->avfc->pb->buf_ptr = priv->avfc->pb->buf_end = priv->avfc->pb->buffer;
stream_drop_buffers(demuxer->stream); stream_drop_buffers(demuxer->stream);
priv->avfc->pb->buf_ptr = priv->avfc->pb->buf_end = priv->avfc->pb->buffer;
priv->avfc->pb->pos = stream_tell(demuxer->stream);
av_seek_frame(priv->avfc, 0, stream_tell(demuxer->stream),
AVSEEK_FLAG_BYTE);
return DEMUXER_CTRL_OK; return DEMUXER_CTRL_OK;
default: default:
return DEMUXER_CTRL_NOTIMPL; return DEMUXER_CTRL_NOTIMPL;