summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-07-20 02:15:15 +0200
committerwm4 <wm4@nowhere>2013-07-20 02:15:39 +0200
commit235f744f48ccecd9432c3fc5ced724bec0e4bb3e (patch)
tree9a72650d0f9dfa193fb376eb5c72a9808e140c25
parent62268893fbf7bbc279400a24b6f43fa1dfeb7049 (diff)
downloadmpv-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.c1
-rw-r--r--demux/ebml.c13
-rw-r--r--stream/stream.h6
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);