diff options
Diffstat (limited to 'demux/demux.c')
-rw-r--r-- | demux/demux.c | 54 |
1 files changed, 43 insertions, 11 deletions
diff --git a/demux/demux.c b/demux/demux.c index 5997a96ed6..6feb97e998 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -26,7 +26,6 @@ #include <string.h> #include <sys/stat.h> #include <sys/types.h> -#include <unistd.h> #include "cache.h" #include "config.h" @@ -4487,9 +4486,11 @@ void demux_get_reader_state(struct demuxer *demuxer, struct demux_reader_state * *r = (struct demux_reader_state){ .eof = in->eof, - .ts_reader = MP_NOPTS_VALUE, - .ts_end = MP_NOPTS_VALUE, - .ts_duration = -1, + .ts_info = { + .reader = MP_NOPTS_VALUE, + .end = MP_NOPTS_VALUE, + .duration = -1, + }, .total_bytes = in->total_bytes, .seeking = in->seeking_in_progress, .low_level_seeks = in->low_level_seeks, @@ -4499,24 +4500,55 @@ void demux_get_reader_state(struct demuxer *demuxer, struct demux_reader_state * .file_cache_bytes = in->cache ? demux_cache_get_size(in->cache) : -1, }; bool any_packets = false; + for (int n = 0; n < STREAM_TYPE_COUNT; n++) { + r->ts_per_stream[n] = r->ts_info; + } for (int n = 0; n < in->num_streams; n++) { struct demux_stream *ds = in->streams[n]->ds; if (ds->eager && !(!ds->queue->head && ds->eof) && !ds->ignore_eof) { r->underrun |= !ds->reader_head && !ds->eof && !ds->still_image; - r->ts_reader = MP_PTS_MAX(r->ts_reader, ds->base_ts); - r->ts_end = MP_PTS_MAX(r->ts_end, ds->queue->last_ts); any_packets |= !!ds->reader_head; + + double ts_reader = ds->base_ts; + double ts_end = ds->queue->last_ts; + double ts_duration = -1; + if (ts_reader != MP_NOPTS_VALUE && ts_reader <= ts_end) + ts_duration = ts_end - ts_reader; + + struct demux_ctrl_ts_info *i = &r->ts_per_stream[ds->type]; + i->reader = MP_PTS_MIN(i->reader, ts_reader); + i->end = MP_PTS_MIN(i->end, ts_end); + i->duration = ts_duration; } r->fw_bytes += get_forward_buffered_bytes(ds); } + struct demux_ctrl_ts_info *ots = &r->ts_info; + // find stream type with lowest duration and use its state + for (int n = 0; n < STREAM_TYPE_COUNT; n++) { + struct demux_ctrl_ts_info *ts = &r->ts_per_stream[n]; + if (r->ts_info.duration != -1) { + // skip if timestamps unknown + if (ts->duration == -1) + continue; + // skip if we already know of a smaller cached stream + if (ts->duration > ots->duration) + continue; + // skip empty subtitle streams when other streams exist + if (n == STREAM_SUB && ts->duration == 0.0) + continue; + } + ots->duration = ts->duration; + ots->reader = ts->reader; + ots->end = ts->end; + } r->idle = (!in->reading && !r->underrun) || r->eof; r->underrun &= !r->idle && in->threading; - r->ts_reader = MP_ADD_PTS(r->ts_reader, in->ts_offset); - r->ts_end = MP_ADD_PTS(r->ts_end, in->ts_offset); - if (r->ts_reader != MP_NOPTS_VALUE && r->ts_reader <= r->ts_end) - r->ts_duration = r->ts_end - r->ts_reader; + ots->reader = MP_ADD_PTS(ots->reader, in->ts_offset); + ots->end = MP_ADD_PTS(ots->end, in->ts_offset); + if (ots->reader != MP_NOPTS_VALUE && ots->reader <= ots->end) + ots->duration = ots->end - ots->reader; if (in->seeking || !any_packets) - r->ts_duration = 0; + ots->duration = 0; for (int n = 0; n < MPMIN(in->num_ranges, MAX_SEEK_RANGES); n++) { struct demux_cached_range *range = in->ranges[n]; if (range->seek_start != MP_NOPTS_VALUE) { |