summaryrefslogtreecommitdiffstats
path: root/demux/demux.c
diff options
context:
space:
mode:
Diffstat (limited to 'demux/demux.c')
-rw-r--r--demux/demux.c87
1 files changed, 63 insertions, 24 deletions
diff --git a/demux/demux.c b/demux/demux.c
index 386b088148..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"
@@ -663,7 +662,7 @@ static void update_seek_ranges(struct demux_cached_range *range)
}
}
- if (range->seek_start >= range->seek_end)
+ if (range->seek_start >= range->seek_end && !(range->is_bof && range->is_eof))
goto broken;
prune_metadata(range);
@@ -3173,19 +3172,26 @@ void demux_update(demuxer_t *demuxer, double pts)
static void demux_init_cuesheet(struct demuxer *demuxer)
{
+ if (demuxer->num_chapters)
+ return;
+
+ struct sh_stream *sh = demuxer->in->metadata_stream;
char *cue = mp_tags_get_str(demuxer->metadata, "cuesheet");
- if (cue && !demuxer->num_chapters) {
- struct cue_file *f = mp_parse_cue(bstr0(cue));
- if (f) {
- if (mp_check_embedded_cue(f) < 0) {
- MP_WARN(demuxer, "Embedded cue sheet references more than one file. "
- "Ignoring it.\n");
- } else {
- for (int n = 0; n < f->num_tracks; n++) {
- struct cue_track *t = &f->tracks[n];
- int idx = demuxer_add_chapter(demuxer, "", t->start, -1);
- mp_tags_merge(demuxer->chapters[idx].metadata, t->tags);
- }
+ if (!cue && sh)
+ cue = mp_tags_get_str(sh->tags, "cuesheet");
+ if (!cue)
+ return;
+
+ struct cue_file *f = mp_parse_cue(bstr0(cue));
+ if (f) {
+ if (mp_check_embedded_cue(f) < 0) {
+ MP_WARN(demuxer, "Embedded cue sheet references more than one file. "
+ "Ignoring it.\n");
+ } else {
+ for (int n = 0; n < f->num_tracks; n++) {
+ struct cue_track *t = &f->tracks[n];
+ int idx = demuxer_add_chapter(demuxer, "", t->start, -1);
+ mp_tags_merge(demuxer->chapters[idx].metadata, t->tags);
}
}
talloc_free(f);
@@ -4480,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,
@@ -4492,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) {