summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/options.rst16
-rw-r--r--demux/demux.c20
-rw-r--r--options/options.c2
-rw-r--r--options/options.h1
4 files changed, 35 insertions, 4 deletions
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 9320a244ac..edbbc35419 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -2048,11 +2048,21 @@ Demuxer
Run the demuxer in a separate thread, and let it prefetch a certain amount
of packets (default: no).
+``--demuxer-readahead-secs=N``
+ If ``--demuxer-thread`` is enabled, this controls how much the demuxer
+ should buffer ahead in seconds (default: 0.2). As long as no packet has
+ a timestamp difference higher than the readahead amount relative to the
+ last packet returned to the decoder, the demuxer keeps reading.
+
+ (This value tends to be fuzzy, because many file formats don't store linear
+ timestamps.)
+
``--demuxer-readahead-packets=N``
If ``--demuxer-thread`` is enabled, this controls how much the demuxer
- should buffer ahead. If the number of packets in the packet queue exceeds
- ``--demuxer-readahead-packets``, or the total number of bytes exceeds
- ``--demuxer-readahead-bytes``, the thread stops reading ahead.
+ should buffer ahead. As long as the number of packets in the packet queue
+ doesn't exceed ``--demuxer-readahead-packets``, and the total number of
+ bytes doesn't exceed ``--demuxer-readahead-bytes``, the thread keeps
+ reading ahead.
Note that if you set these options near the maximum, you might get a
packet queue overflow warning.
diff --git a/demux/demux.c b/demux/demux.c
index 5918da51a9..bb9363815e 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -110,6 +110,7 @@ struct demux_internal {
bool last_eof; // last actual global EOF status
bool eof; // whether we're in EOF state (reset for retry)
bool autoselect;
+ double min_secs;
int min_packs;
int min_bytes;
@@ -137,6 +138,8 @@ struct demux_stream {
bool eof; // end of demuxed stream? (true if all buffer empty)
size_t packs; // number of packets in buffer
size_t bytes; // total bytes of packets in buffer
+ double base_ts; // timestamp of the last packet returned to decoder
+ double last_ts; // timestamp of the last packet added to queue
struct demux_packet *head;
struct demux_packet *tail;
};
@@ -157,6 +160,7 @@ static void ds_flush(struct demux_stream *ds)
ds->head = ds->tail = NULL;
ds->packs = 0;
ds->bytes = 0;
+ ds->last_ts = ds->base_ts = MP_NOPTS_VALUE;
ds->eof = false;
ds->active = false;
}
@@ -294,6 +298,7 @@ int demux_add_packet(struct sh_stream *stream, demux_packet_t *dp)
// first packet in stream
ds->head = ds->tail = dp;
}
+
// obviously not true anymore
ds->eof = false;
in->last_eof = in->eof = false;
@@ -303,6 +308,12 @@ int demux_add_packet(struct sh_stream *stream, demux_packet_t *dp)
if (stream->type != STREAM_VIDEO && dp->pts == MP_NOPTS_VALUE)
dp->pts = dp->dts;
+ double ts = dp->dts == MP_NOPTS_VALUE ? dp->pts : dp->dts;
+ if (ts != MP_NOPTS_VALUE && (ts > ds->last_ts || ts + 10 < ds->last_ts))
+ ds->last_ts = ts;
+ if (ds->base_ts == MP_NOPTS_VALUE)
+ ds->base_ts = ds->last_ts;
+
MP_DBG(in, "append packet to %s: size=%d pts=%f dts=%f pos=%"PRIi64" "
"[num=%zd size=%zd]\n", stream_type_name(stream->type),
dp->len, dp->pts, dp->dts, dp->pos, ds->packs, ds->bytes);
@@ -326,10 +337,12 @@ static bool read_packet(struct demux_internal *in)
size_t packs = 0, bytes = 0;
for (int n = 0; n < in->d_buffer->num_streams; n++) {
struct demux_stream *ds = in->d_buffer->streams[n]->ds;
- active |= ds->selected && ds->active;
+ active |= ds->active;
read_more |= ds->active && !ds->head;
packs += ds->packs;
bytes += ds->bytes;
+ if (ds->active && ds->last_ts != MP_NOPTS_VALUE && in->min_secs > 0)
+ read_more |= ds->last_ts - ds->base_ts < in->min_secs;
}
MP_DBG(in, "packets=%zd, bytes=%zd, active=%d, more=%d\n",
packs, bytes, active, read_more);
@@ -475,6 +488,10 @@ static struct demux_packet *dequeue_packet(struct demux_stream *ds)
ds->bytes -= pkt->len;
ds->packs--;
+ double ts = pkt->dts == MP_NOPTS_VALUE ? pkt->pts : pkt->dts;
+ if (ts != MP_NOPTS_VALUE)
+ ds->base_ts = ts;
+
// This implies this function is actually called from "the" user thread.
if (pkt && pkt->pos >= 0)
ds->in->d_user->filepos = pkt->pos;
@@ -791,6 +808,7 @@ static struct demuxer *open_given_type(struct mpv_global *global,
.d_thread = talloc(demuxer, struct demuxer),
.d_buffer = talloc(demuxer, struct demuxer),
.d_user = demuxer,
+ .min_secs = demuxer->opts->demuxer_min_secs,
.min_packs = demuxer->opts->demuxer_min_packs,
.min_bytes = demuxer->opts->demuxer_min_bytes,
};
diff --git a/options/options.c b/options/options.c
index aacb1b725a..c96f6578b6 100644
--- a/options/options.c
+++ b/options/options.c
@@ -216,6 +216,7 @@ const m_option_t mp_opts[] = {
OPT_STRING("audio-demuxer", audio_demuxer_name, 0),
OPT_STRING("sub-demuxer", sub_demuxer_name, 0),
OPT_FLAG("demuxer-thread", demuxer_thread, 0),
+ OPT_DOUBLE("demuxer-readahead-secs", demuxer_min_secs, M_OPT_MIN, .min = 0),
OPT_INTRANGE("demuxer-readahead-packets", demuxer_min_packs, 0, 0, MAX_PACKS),
OPT_INTRANGE("demuxer-readahead-bytes", demuxer_min_bytes, 0, 0, MAX_PACK_BYTES),
@@ -600,6 +601,7 @@ const struct MPOpts mp_default_opts = {
.demuxer_thread = 0,
.demuxer_min_packs = MIN_PACKS,
.demuxer_min_bytes = MIN_PACK_BYTES,
+ .demuxer_min_secs = 0.2,
.network_rtsp_transport = 2,
.chapterrange = {-1, -1},
.edition_id = -1,
diff --git a/options/options.h b/options/options.h
index 65007bd22e..7b3bf4b69d 100644
--- a/options/options.h
+++ b/options/options.h
@@ -184,6 +184,7 @@ typedef struct MPOpts {
int demuxer_thread;
int demuxer_min_packs;
int demuxer_min_bytes;
+ double demuxer_min_secs;
char *audio_demuxer_name;
char *sub_demuxer_name;
int mkv_subtitle_preroll;