1
0
mirror of https://github.com/mpv-player/mpv synced 2025-02-17 04:58:06 +00:00

stream: minor cleanups

Fix return types and return values to make them more consistent. Some
reformatting and making code more concise.

In stream_reconnect(), avoid the additional mp_cancel_test() call by
moving the "connection lost" message below the mp_cancel_wait() call,
which effectively leads to the same behavior when the stream was already
canceled. (The goal is not to show the message in this case.)

Merge stream_seek_long() into stream_seek(). It was the only caller.

Always clear the eof flag on seeks.

Reduce access to stream internals in cache.c and stream_lavf.c.
This commit is contained in:
wm4 2015-02-06 21:15:21 +01:00
parent 45e214d7ae
commit 347cf97231
4 changed files with 65 additions and 89 deletions

View File

@ -581,9 +581,8 @@ static int cache_control(stream_t *cache, int cmd, void *arg)
}
r = s->control_res;
if (s->control_flush) {
stream_drop_buffers(cache);
cache->pos = s->read_filepos;
cache->eof = 0;
cache->buf_pos = cache->buf_len = 0;
}
done:

View File

@ -121,7 +121,7 @@ static const stream_info_t *const stream_list[] = {
NULL
};
static int stream_seek_unbuffered(stream_t *s, int64_t newpos);
static bool stream_seek_unbuffered(stream_t *s, int64_t newpos);
static int from_hex(unsigned char c)
{
@ -414,32 +414,29 @@ stream_t *open_output_stream(const char *filename, struct mpv_global *global)
return stream_create(filename, STREAM_WRITE, NULL, global);
}
static int stream_reconnect(stream_t *s)
static bool stream_reconnect(stream_t *s)
{
if (!s->streaming || s->uncached_stream)
return 0;
if (!s->seekable)
return 0;
if (mp_cancel_test(s->cancel) || !s->cancel)
return 0;
if (!s->streaming || s->uncached_stream || !s->seekable || !s->cancel)
return false;
int64_t pos = s->pos;
double sleep_secs = 0;
for (int retry = 0; retry < 6; retry++) {
MP_WARN(s, "Connection lost! Attempting to reconnect (%d)...\n", retry + 1);
if (mp_cancel_wait(s->cancel, sleep_secs))
break;
sleep_secs = MPMAX(sleep_secs, 0.1);
sleep_secs = MPMIN(sleep_secs * 4, 10.0);
MP_WARN(s, "Connection lost! Attempting to reconnect (%d)...\n", retry + 1);
int r = stream_control(s, STREAM_CTRL_RECONNECT, NULL);
if (r == STREAM_UNSUPPORTED)
break;
if (r == STREAM_OK && stream_seek_unbuffered(s, pos) < 0 && s->pos == pos)
return 1;
if (r == STREAM_OK && stream_seek_unbuffered(s, pos) && s->pos == pos)
return true;
sleep_secs = MPMAX(sleep_secs, 0.1);
sleep_secs = MPMIN(sleep_secs * 4, 10.0);
}
return 0;
return false;
}
static void stream_capture_write(stream_t *s, void *buf, size_t len)
@ -475,7 +472,7 @@ void stream_set_capture_file(stream_t *s, const char *filename)
// Read function bypassing the local stream buffer. This will not write into
// s->buffer, but into buf[0..len] instead.
// Returns < 0 on error, 0 on EOF, and length of bytes read on success.
// Returns 0 on error or EOF, and length of bytes read on success.
// Partial reads are possible, even if EOF is not reached.
static int stream_read_unbuffered(stream_t *s, void *buf, int len)
{
@ -486,21 +483,16 @@ static int stream_read_unbuffered(stream_t *s, void *buf, int len)
if (len < 0)
len = 0;
if (len == 0) {
// just in case this is an error e.g. due to network
// timeout reset and retry
// do not retry if this looks like proper eof
int64_t size = -1;
stream_control(s, STREAM_CTRL_GET_SIZE, &size);
if (s->eof || s->pos == size)
goto eof_out;
if (!s->eof && s->pos != size && stream_reconnect(s)) {
s->eof = 1; // make sure EOF is set to ensure no endless recursion
return stream_read_unbuffered(s, buf, orig_len);
}
// just in case this is an error e.g. due to network
// timeout reset and retry
if (!stream_reconnect(s))
goto eof_out;
// make sure EOF is set to ensure no endless loops
s->eof = 1;
return stream_read_unbuffered(s, buf, orig_len);
eof_out:
s->eof = 1;
return 0;
}
@ -613,13 +605,13 @@ int stream_write_buffer(stream_t *s, unsigned char *buf, int len)
return rd;
}
static int stream_skip_read(struct stream *s, int64_t len)
static bool stream_skip_read(struct stream *s, int64_t len)
{
while (len > 0) {
int x = s->buf_len - s->buf_pos;
if (x == 0) {
if (!stream_fill_buffer_by(s, len))
return 0; // EOF
return false; // EOF
x = s->buf_len - s->buf_pos;
}
if (x > len)
@ -627,7 +619,7 @@ static int stream_skip_read(struct stream *s, int64_t len)
s->buf_pos += x;
len -= x;
}
return 1;
return true;
}
// Drop the internal buffer. Note that this will advance the stream position
@ -641,37 +633,50 @@ void stream_drop_buffers(stream_t *s)
}
// Seek function bypassing the local stream buffer.
static int stream_seek_unbuffered(stream_t *s, int64_t newpos)
static bool stream_seek_unbuffered(stream_t *s, int64_t newpos)
{
if (newpos != s->pos) {
if (newpos > s->pos && !s->seekable) {
MP_ERR(s, "Cannot seek forward in this stream\n");
return 0;
return false;
}
if (newpos < s->pos && !s->seekable) {
MP_ERR(s, "Cannot seek backward in linear streams!\n");
return 1;
return false;
}
if (s->seek(s, newpos) <= 0) {
MP_ERR(s, "Seek failed\n");
return 0;
return false;
}
stream_drop_buffers(s);
s->pos = newpos;
}
s->eof = 0; // EOF reset when seek succeeds.
return -1;
return true;
}
// Unlike stream_seek, does not try to seek within local buffer.
// Unlike stream_seek_unbuffered(), it still fills the local buffer.
static int stream_seek_long(stream_t *s, int64_t pos)
bool stream_seek(stream_t *s, int64_t pos)
{
if (s->mode == STREAM_WRITE) {
if (!s->seekable || !s->seek(s, pos))
return 0;
return 1;
MP_TRACE(s, "seek to %lld\n", (long long)pos);
s->eof = 0; // eof should be set only on read; seeking always clears it
if (pos == stream_tell(s))
return true;
if (pos < 0) {
MP_ERR(s, "Invalid seek to negative position %lld!\n", (long long)pos);
pos = 0;
}
if (pos < s->pos) {
int64_t x = pos - (s->pos - (int)s->buf_len);
if (x >= 0) {
s->buf_pos = x;
return true;
}
}
if (s->mode == STREAM_WRITE)
return s->seekable && s->seek(s, pos));
int64_t newpos = pos;
if (s->sector_size)
@ -682,44 +687,18 @@ static int stream_seek_long(stream_t *s, int64_t pos)
if (pos >= s->pos && !s->seekable && s->fast_skip) {
// skipping is handled by generic code below
} else if (stream_seek_unbuffered(s, newpos) >= 0) {
return 0;
} else if (!stream_seek_unbuffered(s, newpos)) {
return false;
}
if (pos >= s->pos && stream_skip_read(s, pos - s->pos) > 0)
return 1; // success
// Fill failed, but seek still is a success (partially).
s->eof = 0; // eof should be set only on read
MP_VERBOSE(s, "Seek to/past EOF: no buffer preloaded.\n");
return 1;
bool r = pos >= s->pos && stream_skip_read(s, pos - s->pos);
if (!r)
MP_VERBOSE(s, "Seek to/past EOF: no buffer preloaded.\n");
s->eof = 0;
return r;
}
int stream_seek(stream_t *s, int64_t pos)
{
MP_TRACE(s, "seek to 0x%llX\n", (long long)pos);
if (pos == stream_tell(s))
return 1;
if (pos < 0) {
MP_ERR(s, "Invalid seek to negative position %llx!\n", (long long)pos);
pos = 0;
}
if (pos < s->pos) {
int64_t x = pos - (s->pos - (int)s->buf_len);
if (x >= 0) {
s->buf_pos = x;
s->eof = 0;
return 1;
}
}
return stream_seek_long(s, pos);
}
int stream_skip(stream_t *s, int64_t len)
bool stream_skip(stream_t *s, int64_t len)
{
int64_t target = stream_tell(s) + len;
if (len < 0)
@ -728,12 +707,10 @@ int stream_skip(stream_t *s, int64_t len)
// Seek to 1 byte before target - this is the only way to distinguish
// skip-to-EOF and skip-past-EOF in general. Successful seeking means
// absolutely nothing, so test by doing a real read of the last byte.
int r = stream_seek(s, target - 1);
if (r) {
stream_read_char(s);
return !stream_eof(s) && stream_tell(s) == target;
}
return r;
if (!stream_seek(s, target - 1))
return false;
stream_read_char(s);
return !stream_eof(s) && stream_tell(s) == target;
}
return stream_skip_read(s, len);
}

View File

@ -252,8 +252,8 @@ inline static int64_t stream_tell(stream_t *s)
return s->pos + s->buf_pos - s->buf_len;
}
int stream_skip(stream_t *s, int64_t len);
int stream_seek(stream_t *s, int64_t pos);
bool stream_skip(stream_t *s, int64_t len);
bool stream_seek(stream_t *s, int64_t pos);
int stream_read(stream_t *s, char *mem, int total);
int stream_read_partial(stream_t *s, char *buf, int buf_size);
struct bstr stream_peek(stream_t *s, int len);

View File

@ -134,6 +134,8 @@ static int control(stream_t *s, int cmd, void *arg)
// avio doesn't seem to support this - emulate it by reopening
close_f(s);
s->priv = NULL;
stream_drop_buffers(s);
s->pos = 0;
return open_f(s);
}
}
@ -291,8 +293,6 @@ static int open_f(stream_t *stream)
stream->close = close_f;
// enable cache (should be avoided for files, but no way to detect this)
stream->streaming = true;
stream->pos = 0; // reset specifically for STREAM_CTRL_RECONNECT
stream->buf_pos = stream->buf_len = 0;
res = STREAM_OK;
out: