mirror of
https://github.com/mpv-player/mpv.git
synced 2026-10-28 23:13:18 +08:00
cache, dvd, bluray: simplify stream time handling
We used a complicated and approximate method to cache the stream timestamp, which is basically per-byte. (To reduce overhead, it was only cached per 8KB-block, so it was approximate.) Simplify this, and read/keep the timestamp only on discontinuities. This is when demux_disc.c actually needs the timestamp. Note that caching is currently disabled for dvdnav, but we still read the timestamp only after some data is read. libdvdread behaves well, but I don't know about libbluray, and the previous code also read the timestamp only after reading data, so try to keep it safe. Also drop the start_time offset. It wouldn't be correct anymore if used with the cache, and the idea behind it wasn't very sane either (making the player to offset the initial playback time to 0).
This commit is contained in:
@@ -285,8 +285,6 @@ static int d_open(demuxer_t *demuxer, enum demux_check check)
|
|||||||
if (demuxer->stream->uncached_type == STREAMTYPE_CDDA)
|
if (demuxer->stream->uncached_type == STREAMTYPE_CDDA)
|
||||||
demux = "+rawaudio";
|
demux = "+rawaudio";
|
||||||
|
|
||||||
reset_pts(demuxer);
|
|
||||||
|
|
||||||
p->slave = demux_open(demuxer->stream, demux, NULL, demuxer->global);
|
p->slave = demux_open(demuxer->stream, demux, NULL, demuxer->global);
|
||||||
if (!p->slave)
|
if (!p->slave)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -294,8 +292,6 @@ static int d_open(demuxer_t *demuxer, enum demux_check check)
|
|||||||
// So that we don't miss initial packets of delayed subtitle streams.
|
// So that we don't miss initial packets of delayed subtitle streams.
|
||||||
p->slave->stream_select_default = true;
|
p->slave->stream_select_default = true;
|
||||||
|
|
||||||
demuxer->start_time = p->pts[STREAM_VIDEO].base_time;
|
|
||||||
|
|
||||||
// Can be seekable even if the stream isn't.
|
// Can be seekable even if the stream isn't.
|
||||||
demuxer->seekable = true;
|
demuxer->seekable = true;
|
||||||
|
|
||||||
|
|||||||
+16
-42
@@ -76,7 +76,6 @@ struct priv {
|
|||||||
int64_t buffer_size; // size of the allocated buffer memory
|
int64_t buffer_size; // size of the allocated buffer memory
|
||||||
int64_t back_size; // keep back_size amount of old bytes for backward seek
|
int64_t back_size; // keep back_size amount of old bytes for backward seek
|
||||||
int64_t seek_limit; // keep filling cache if distance is less that seek limit
|
int64_t seek_limit; // keep filling cache if distance is less that seek limit
|
||||||
struct byte_meta *bm; // additional per-byte metadata
|
|
||||||
bool seekable; // underlying stream is seekable
|
bool seekable; // underlying stream is seekable
|
||||||
|
|
||||||
struct mp_log *log;
|
struct mp_log *log;
|
||||||
@@ -116,17 +115,10 @@ struct priv {
|
|||||||
int stream_cache_fill;
|
int stream_cache_fill;
|
||||||
struct mp_tags *stream_metadata;
|
struct mp_tags *stream_metadata;
|
||||||
char *disc_name;
|
char *disc_name;
|
||||||
};
|
double start_pts;
|
||||||
|
|
||||||
// Store additional per-byte metadata. Since per-byte would be way too
|
|
||||||
// inefficient, store it only for every BYTE_META_CHUNK_SIZE byte.
|
|
||||||
struct byte_meta {
|
|
||||||
float stream_pts;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
BYTE_META_CHUNK_SIZE = 8 * 1024,
|
|
||||||
|
|
||||||
CACHE_INTERRUPTED = -1,
|
CACHE_INTERRUPTED = -1,
|
||||||
|
|
||||||
CACHE_CTRL_NONE = 0,
|
CACHE_CTRL_NONE = 0,
|
||||||
@@ -134,7 +126,7 @@ enum {
|
|||||||
CACHE_CTRL_PING = -2,
|
CACHE_CTRL_PING = -2,
|
||||||
|
|
||||||
// we should fill buffer only if space>=FILL_LIMIT
|
// we should fill buffer only if space>=FILL_LIMIT
|
||||||
FILL_LIMIT = FFMAX(16 * 1024, BYTE_META_CHUNK_SIZE * 2),
|
FILL_LIMIT = 16 * 1024,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int64_t mp_clipi64(int64_t val, int64_t min, int64_t max)
|
static int64_t mp_clipi64(int64_t val, int64_t min, int64_t max)
|
||||||
@@ -179,6 +171,7 @@ static void cache_drop_contents(struct priv *s)
|
|||||||
{
|
{
|
||||||
s->offset = s->min_filepos = s->max_filepos = s->read_filepos;
|
s->offset = s->min_filepos = s->max_filepos = s->read_filepos;
|
||||||
s->eof = false;
|
s->eof = false;
|
||||||
|
s->start_pts = MP_NOPTS_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy at most dst_size from the cache at the given absolute file position pos.
|
// Copy at most dst_size from the cache at the given absolute file position pos.
|
||||||
@@ -278,13 +271,12 @@ static bool cache_fill(struct priv *s)
|
|||||||
len = stream_read_partial(s->stream, &s->buffer[pos], space);
|
len = stream_read_partial(s->stream, &s->buffer[pos], space);
|
||||||
pthread_mutex_lock(&s->mutex);
|
pthread_mutex_lock(&s->mutex);
|
||||||
|
|
||||||
double pts;
|
// Do this after reading a block, because at least libdvdnav updates the
|
||||||
if (stream_control(s->stream, STREAM_CTRL_GET_CURRENT_TIME, &pts) <= 0)
|
// stream position only after actually reading something after a seek.
|
||||||
pts = MP_NOPTS_VALUE;
|
if (s->start_pts == MP_NOPTS_VALUE) {
|
||||||
for (int64_t b_pos = pos; b_pos < pos + len + BYTE_META_CHUNK_SIZE;
|
double pts;
|
||||||
b_pos += BYTE_META_CHUNK_SIZE)
|
if (stream_control(s->stream, STREAM_CTRL_GET_CURRENT_TIME, &pts) > 0)
|
||||||
{
|
s->start_pts = pts;
|
||||||
s->bm[b_pos / BYTE_META_CHUNK_SIZE] = (struct byte_meta){.stream_pts = pts};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s->max_filepos += len;
|
s->max_filepos += len;
|
||||||
@@ -311,11 +303,8 @@ static int resize_cache(struct priv *s, int64_t size)
|
|||||||
int64_t buffer_size = MPMIN(MPMAX(size, min_size), max_size);
|
int64_t buffer_size = MPMIN(MPMAX(size, min_size), max_size);
|
||||||
|
|
||||||
unsigned char *buffer = malloc(buffer_size);
|
unsigned char *buffer = malloc(buffer_size);
|
||||||
struct byte_meta *bm = calloc(buffer_size / BYTE_META_CHUNK_SIZE + 2,
|
if (!buffer) {
|
||||||
sizeof(struct byte_meta));
|
|
||||||
if (!buffer || !bm) {
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
free(bm);
|
|
||||||
return STREAM_ERROR;
|
return STREAM_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,12 +335,10 @@ static int resize_cache(struct priv *s, int64_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
free(s->buffer);
|
free(s->buffer);
|
||||||
free(s->bm);
|
|
||||||
|
|
||||||
s->buffer_size = buffer_size;
|
s->buffer_size = buffer_size;
|
||||||
s->back_size = buffer_size / 2;
|
s->back_size = buffer_size / 2;
|
||||||
s->buffer = buffer;
|
s->buffer = buffer;
|
||||||
s->bm = bm;
|
|
||||||
s->idle = false;
|
s->idle = false;
|
||||||
s->eof = false;
|
s->eof = false;
|
||||||
|
|
||||||
@@ -360,9 +347,6 @@ static int resize_cache(struct priv *s, int64_t size)
|
|||||||
if (s->seek_limit > s->buffer_size - FILL_LIMIT)
|
if (s->seek_limit > s->buffer_size - FILL_LIMIT)
|
||||||
s->seek_limit = s->buffer_size - FILL_LIMIT;
|
s->seek_limit = s->buffer_size - FILL_LIMIT;
|
||||||
|
|
||||||
for (size_t n = 0; n < s->buffer_size / BYTE_META_CHUNK_SIZE + 2; n++)
|
|
||||||
s->bm[n] = (struct byte_meta){.stream_pts = MP_NOPTS_VALUE};
|
|
||||||
|
|
||||||
return STREAM_OK;
|
return STREAM_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -419,21 +403,10 @@ static int cache_get_cached_control(stream_t *cache, int cmd, void *arg)
|
|||||||
*(unsigned int *)arg = s->stream_num_chapters;
|
*(unsigned int *)arg = s->stream_num_chapters;
|
||||||
return STREAM_OK;
|
return STREAM_OK;
|
||||||
case STREAM_CTRL_GET_CURRENT_TIME: {
|
case STREAM_CTRL_GET_CURRENT_TIME: {
|
||||||
if (s->read_filepos >= s->min_filepos &&
|
if (s->start_pts == MP_NOPTS_VALUE)
|
||||||
s->read_filepos <= s->max_filepos &&
|
return STREAM_UNSUPPORTED;
|
||||||
s->min_filepos < s->max_filepos)
|
*(double *)arg = s->start_pts;
|
||||||
{
|
return STREAM_OK;
|
||||||
int64_t fpos = FFMIN(s->read_filepos, s->max_filepos - 1);
|
|
||||||
int64_t pos = fpos - s->offset;
|
|
||||||
if (pos < 0)
|
|
||||||
pos += s->buffer_size;
|
|
||||||
else if (pos >= s->buffer_size)
|
|
||||||
pos -= s->buffer_size;
|
|
||||||
double pts = s->bm[pos / BYTE_META_CHUNK_SIZE].stream_pts;
|
|
||||||
*(double *)arg = pts;
|
|
||||||
return pts == MP_NOPTS_VALUE ? STREAM_UNSUPPORTED : STREAM_OK;
|
|
||||||
}
|
|
||||||
return STREAM_UNSUPPORTED;
|
|
||||||
}
|
}
|
||||||
case STREAM_CTRL_GET_METADATA: {
|
case STREAM_CTRL_GET_METADATA: {
|
||||||
if (s->stream_metadata) {
|
if (s->stream_metadata) {
|
||||||
@@ -642,7 +615,6 @@ static void cache_uninit(stream_t *cache)
|
|||||||
pthread_mutex_destroy(&s->mutex);
|
pthread_mutex_destroy(&s->mutex);
|
||||||
pthread_cond_destroy(&s->wakeup);
|
pthread_cond_destroy(&s->wakeup);
|
||||||
free(s->buffer);
|
free(s->buffer);
|
||||||
free(s->bm);
|
|
||||||
talloc_free(s);
|
talloc_free(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -657,6 +629,8 @@ int stream_cache_init(stream_t *cache, stream_t *stream,
|
|||||||
struct priv *s = talloc_zero(NULL, struct priv);
|
struct priv *s = talloc_zero(NULL, struct priv);
|
||||||
s->log = cache->log;
|
s->log = cache->log;
|
||||||
|
|
||||||
|
cache_drop_contents(s);
|
||||||
|
|
||||||
s->seek_limit = opts->seek_min * 1024ULL;
|
s->seek_limit = opts->seek_min * 1024ULL;
|
||||||
|
|
||||||
if (resize_cache(s, opts->size * 1024ULL) != STREAM_OK) {
|
if (resize_cache(s, opts->size * 1024ULL) != STREAM_OK) {
|
||||||
|
|||||||
Reference in New Issue
Block a user