summaryrefslogtreecommitdiffstats
path: root/demux
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-08-16 17:07:36 +0200
committerwm4 <wm4@nowhere>2014-08-16 17:10:08 +0200
commitb822faa6cfdae2c530d68f257a811c6184d237a6 (patch)
tree073cee68af958d205b00648cfacc4439b6d5d471 /demux
parente6e3bc7cd97e7dc27d91bbf89902191b4408cb40 (diff)
downloadmpv-b822faa6cfdae2c530d68f257a811c6184d237a6.tar.bz2
mpv-b822faa6cfdae2c530d68f257a811c6184d237a6.tar.xz
demux: add option to control the readahead buffer by a duration value
--demuxer-readahead-secs now controls how much the demuxer should readahead by an amount of seconds. This is based on the raw packet timestamps. It's not always very exact. For example, h264 in Matroska does not store any linear timestamps (only PTS values which are going to be reordered by the decoder), so this heuristic is usually off by several hundred milliseconds. The decision whether to readahead is basically OR-ed with the other --demuxer-readahead-packets options. Change the manpage descriptions to subtly convey these semantics.
Diffstat (limited to 'demux')
-rw-r--r--demux/demux.c20
1 files changed, 19 insertions, 1 deletions
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,
};