diff options
author | wm4 <wm4@nowhere> | 2013-07-20 02:15:15 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2013-07-20 02:15:39 +0200 |
commit | 235f744f48ccecd9432c3fc5ced724bec0e4bb3e (patch) | |
tree | 9a72650d0f9dfa193fb376eb5c72a9808e140c25 | |
parent | 62268893fbf7bbc279400a24b6f43fa1dfeb7049 (diff) | |
download | mpv-matroska2.tar.bz2 mpv-matroska2.tar.xz |
demux_mkv: fix some potential issues with small backwards seeksmatroska2
In some cases, the demuxer seeks backwards to unread EBML tags, so that
other code can parse the properly. In theory, it could happen that a
small backwards seek requires the stream buffer to be refilled (for
example, because the preceding read caused a buffer refill and threw
away the previous contents.
So insert some strategical stream_peek() calls, which will transparently
memmove() the buffer contents if needed.
(Also, get rid of the pos variable in ebml_resync_cluster. This is an
unrelated cosmetic change, I guess.)
-rw-r--r-- | demux/demux_mkv.c | 1 | ||||
-rw-r--r-- | demux/ebml.c | 13 | ||||
-rw-r--r-- | stream/stream.h | 6 |
3 files changed, 14 insertions, 6 deletions
diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 8013aa3527..2cfb7de422 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -1777,6 +1777,7 @@ static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check) *demuxer->params->matroska_was_valid = true; while (1) { + stream_peek(s, 4); uint32_t id = ebml_read_id(s, NULL); if (s->eof) { mp_tmsg(MSGT_DEMUX, MSGL_WARN, diff --git a/demux/ebml.c b/demux/ebml.c index 98ab1ef306..9b198fc132 100644 --- a/demux/ebml.c +++ b/demux/ebml.c @@ -274,20 +274,21 @@ int ebml_read_skip(stream_t *s, uint64_t *length) */ int ebml_resync_cluster(stream_t *s) { - int64_t pos = stream_tell(s); uint32_t last_4_bytes = 0; - mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] Corrupt file detected. " - "Trying to resync starting from position %"PRId64"...\n", pos); + mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] Corrupt file detected. Trying to " + "resync starting from position %"PRId64"...\n", stream_tell(s)); while (!s->eof) { // Assumes MATROSKA_ID_CLUSTER is 4 bytes, with no 0 bytes. if (last_4_bytes == MATROSKA_ID_CLUSTER) { + int64_t pos = stream_tell(s) - 4; mp_msg(MSGT_DEMUX, MSGL_ERR, - "[mkv] Cluster found at %"PRId64".\n", pos - 4); - stream_seek(s, pos - 4); + "[mkv] Cluster found at %"PRId64".\n", pos); + stream_seek(s, pos); return 0; } + if (stream_buffered(s) < 4) + stream_peek(s, STREAM_BUFFER_SIZE); last_4_bytes = (last_4_bytes << 8) | stream_read_char(s); - pos++; } return -1; } diff --git a/stream/stream.h b/stream/stream.h index a0cd3d58fc..b637461eda 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -215,6 +215,12 @@ inline static int64_t stream_tell(stream_t *s) return s->pos + s->buf_pos - s->buf_len; } +// Return number of buffered bytes. (Useful for optimization purposes.) +inline static int stream_buffered(stream_t *s) +{ + return s->buf_len - s->buf_pos; +} + int stream_skip(stream_t *s, int64_t len); int stream_seek(stream_t *s, int64_t pos); int stream_read(stream_t *s, char *mem, int total); |