diff options
-rw-r--r-- | DOCS/man/options.rst | 16 | ||||
-rw-r--r-- | demux/demux.c | 20 | ||||
-rw-r--r-- | options/options.c | 2 | ||||
-rw-r--r-- | options/options.h | 1 |
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; |