demux_mkv: fix issues with unseekable streams

A user reported a webm stream that couldn't be played. The issue was
that this stream 1. was on an unseekable HTTP connection, and 2. had a
SeekHead element (wtf?). The code reading the SeekHead marked the
element as unreadable too early: although you can't seek in the stream,
reading the header elements after the SeekHead read them anyway. Marking
them as unreadable only after the normal header reading fixes this.

(The way the failing stream was setup was pretty retarded: inserting
these SeekHead elements makes absolutely no sense for a stream that
cannot be seeked.)

Fixes #1656.
This commit is contained in:
wm4 2015-03-06 15:06:59 +01:00
parent 4ff29f33b0
commit 12dcc5eaac
1 changed files with 16 additions and 14 deletions

View File

@ -1035,9 +1035,6 @@ static int demux_mkv_read_seekhead(demuxer_t *demuxer)
struct ebml_seek_head seekhead = {0};
struct ebml_parse_ctx parse_ctx = {demuxer->log};
int64_t end = 0;
stream_control(s, STREAM_CTRL_GET_SIZE, &end);
MP_VERBOSE(demuxer, "/---- [ parsing seek head ] ---------\n");
if (ebml_read_element(s, &parse_ctx, &seekhead, &ebml_seek_head_desc) < 0) {
res = -1;
@ -1052,16 +1049,7 @@ static int demux_mkv_read_seekhead(demuxer_t *demuxer)
uint64_t pos = seek->seek_position + mkv_d->segment_start;
MP_DBG(demuxer, "Element 0x%x at %"PRIu64".\n",
(unsigned)seek->seek_id, pos);
struct header_elem *elem = get_header_element(demuxer, seek->seek_id, pos);
// Warn against incomplete files.
if (elem && pos >= end) {
elem->parsed = true; // don't bother
if (!mkv_d->eof_warning) {
MP_WARN(demuxer, "SeekHead position beyond "
"end of file - incomplete file?\n");
mkv_d->eof_warning = true;
}
}
get_header_element(demuxer, seek->seek_id, pos);
}
out:
MP_VERBOSE(demuxer, "\\---- [ parsing seek head ] ---------\n");
@ -1809,12 +1797,26 @@ static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check)
return -1;
}
int64_t end = 0;
stream_control(s, STREAM_CTRL_GET_SIZE, &end);
// Read headers that come after the first cluster (i.e. require seeking).
// Note: reading might increase ->num_headers.
// Likewise, ->headers might be reallocated.
for (int n = 0; n < mkv_d->num_headers; n++) {
struct header_elem *elem = &mkv_d->headers[n];
if (elem->id == MATROSKA_ID_CUES && !elem->parsed) {
if (elem->parsed)
continue;
// Warn against incomplete files.
if (elem->pos >= end) {
elem->parsed = true; // don't bother if file is incomplete
if (!mkv_d->eof_warning) {
MP_WARN(demuxer, "SeekHead position beyond "
"end of file - incomplete file?\n");
mkv_d->eof_warning = true;
}
}
if (elem->id == MATROSKA_ID_CUES) {
// Read cues when they are needed, to avoid seeking on opening.
MP_VERBOSE(demuxer, "Deferring reading cues.\n");
continue;