mirror of
https://github.com/mpv-player/mpv
synced 2024-11-14 22:48:35 +01:00
demux_mkv, stream: attempt to improve behavior in unseekable streams
stream_skip() semantics were kind of bad, especially after the recent change to the stream code. Forward stream_skip() calls could still trigger a seek and fail, even if it was supposed to actually skip data. (Maybe the idea that stream_skip() should try to seek is worthless in the first place.) Rename it to stream_seek_skip() (takes absolute position now because I think that's better), and make it always skip if the stream is marked as forward. While we're at it, make EOF detection more robust. I guess s->eof shouldn't exist at all, since it's valid only "sometimes". It should be removed... but not today. A 1-byte stream_read_peek() call is good to get the s->eof flag set to a correct value.
This commit is contained in:
parent
dcc3c2eb38
commit
ac7f67b3f2
@ -1954,7 +1954,7 @@ static int read_mkv_segment_header(demuxer_t *demuxer, int64_t *segment_end)
|
||||
if (demuxer->params)
|
||||
num_skip = demuxer->params->matroska_wanted_segment;
|
||||
|
||||
while (!s->eof) {
|
||||
while (stream_read_peek(s, &(char){0}, 1)) {
|
||||
if (ebml_read_id(s) != MATROSKA_ID_SEGMENT) {
|
||||
MP_VERBOSE(demuxer, "segment not found\n");
|
||||
return 0;
|
||||
@ -2580,7 +2580,7 @@ static int read_block(demuxer_t *demuxer, int64_t end, struct block_info *block)
|
||||
exit:
|
||||
if (res <= 0)
|
||||
free_block(block);
|
||||
stream_seek(s, endpos);
|
||||
stream_seek_skip(s, endpos);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ static int read_characters(stream_t *s, uint8_t *dst, int dstsize, int utf16)
|
||||
if (len > dstsize)
|
||||
return -1; // line too long
|
||||
memcpy(dst, buf, len);
|
||||
stream_skip(s, len);
|
||||
stream_seek_skip(s, len);
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
@ -180,14 +180,14 @@ int ebml_read_skip(struct mp_log *log, int64_t end, stream_t *s)
|
||||
if (len >= INT64_MAX - pos2 || (end > 0 && pos2 + len > end))
|
||||
goto invalid;
|
||||
|
||||
if (!stream_skip(s, len))
|
||||
if (!stream_seek_skip(s, pos2 + len))
|
||||
goto invalid;
|
||||
|
||||
return 0;
|
||||
|
||||
invalid:
|
||||
mp_err(log, "Invalid EBML length at position %"PRId64"\n", pos);
|
||||
stream_seek(s, pos);
|
||||
stream_seek_skip(s, pos);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -198,6 +198,7 @@ int ebml_resync_cluster(struct mp_log *log, stream_t *s)
|
||||
{
|
||||
int64_t pos = stream_tell(s);
|
||||
uint32_t last_4_bytes = 0;
|
||||
stream_read_peek(s, &(char){0}, 1);
|
||||
if (!s->eof) {
|
||||
mp_err(log, "Corrupt file detected. "
|
||||
"Trying to resync starting from position %"PRId64"...\n", pos);
|
||||
|
@ -692,13 +692,13 @@ bool stream_seek(stream_t *s, int64_t pos)
|
||||
return stream_seek_unbuffered(s, pos);
|
||||
}
|
||||
|
||||
bool stream_skip(stream_t *s, int64_t len)
|
||||
// Like stream_seek(), but strictly prefer skipping data instead of failing, if
|
||||
// it's a forward-seek.
|
||||
bool stream_seek_skip(stream_t *s, int64_t pos)
|
||||
{
|
||||
if (!stream_seek(s, stream_tell(s) + len))
|
||||
return false;
|
||||
// Make sure s->eof is set correctly, even if a seek happened.
|
||||
stream_read_more(s, 1);
|
||||
return true;
|
||||
return !s->seekable && pos > stream_tell(s)
|
||||
? stream_skip_read(s, pos - stream_tell(s))
|
||||
: stream_seek(s, pos);
|
||||
}
|
||||
|
||||
int stream_control(stream_t *s, int cmd, void *arg)
|
||||
@ -732,7 +732,7 @@ int stream_skip_bom(struct stream *s)
|
||||
bstr data = {buf, len};
|
||||
for (int n = 0; n < 3; n++) {
|
||||
if (bstr_startswith0(data, bom[n])) {
|
||||
stream_skip(s, strlen(bom[n]));
|
||||
stream_seek_skip(s, stream_tell(s) + strlen(bom[n]));
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ typedef struct stream {
|
||||
void (*close)(struct stream *s);
|
||||
|
||||
int64_t pos;
|
||||
int eof;
|
||||
int eof; // valid only after read calls that returned a short result
|
||||
int mode; //STREAM_READ or STREAM_WRITE
|
||||
void *priv; // used for DVD, TV, RTSP etc
|
||||
char *url; // filename/url (possibly including protocol prefix)
|
||||
@ -194,7 +194,7 @@ inline static int64_t stream_tell(stream_t *s)
|
||||
return s->pos + s->buf_cur - s->buf_end;
|
||||
}
|
||||
|
||||
bool stream_skip(stream_t *s, int64_t len);
|
||||
bool stream_seek_skip(stream_t *s, int64_t pos);
|
||||
bool stream_seek(stream_t *s, int64_t pos);
|
||||
int stream_read(stream_t *s, void *mem, int total);
|
||||
int stream_read_partial(stream_t *s, void *buf, int buf_size);
|
||||
|
@ -84,7 +84,7 @@ static int64_t skip_cb(struct archive *arch, void *priv, int64_t request)
|
||||
if (!volume_seek(vol))
|
||||
return -1;
|
||||
int64_t old = stream_tell(vol->src);
|
||||
stream_skip(vol->src, request);
|
||||
stream_seek_skip(vol->src, old + request);
|
||||
return stream_tell(vol->src) - old;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user