summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demux/demux.c23
-rw-r--r--demux/demux.h1
-rw-r--r--player/command.c1
-rw-r--r--player/command.h1
-rw-r--r--player/loadfile.c2
5 files changed, 28 insertions, 0 deletions
diff --git a/demux/demux.c b/demux/demux.c
index 4ea8cce595..8c8600d63b 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -190,6 +190,8 @@ struct demux_internal {
// This is never NULL. This is always ranges[num_ranges - 1].
struct demux_cached_range *current_range;
+ double highest_av_pts; // highest non-subtitle PTS seen - for duration
+
// Cached state.
bool force_cache_update;
struct mp_tags *stream_metadata;
@@ -1198,6 +1200,23 @@ void demux_add_packet(struct sh_stream *stream, demux_packet_t *dp)
adjust_seek_range_on_packet(ds, dp);
+ // Possible update duration based on highest TS demuxed (but ignore subs).
+ if (stream->type != STREAM_SUB) {
+ if (dp->segmented)
+ ts = MP_PTS_MIN(ts, dp->end);
+ if (ts > in->highest_av_pts) {
+ in->highest_av_pts = ts;
+ double duration = in->highest_av_pts - in->d_thread->start_time;
+ if (duration > in->d_thread->duration) {
+ in->d_thread->duration = duration;
+ // (Don't wakeup like like demux_changed(), would be too noisy.)
+ in->d_thread->events |= DEMUX_EVENT_DURATION;
+ in->d_buffer->duration = duration;
+ in->d_buffer->events |= DEMUX_EVENT_DURATION;
+ }
+ }
+ }
+
// Wake up if this was the first packet after start/possible underrun.
if (ds->in->wakeup_cb && ds->reader_head && !ds->reader_head->next)
ds->in->wakeup_cb(ds->in->wakeup_cb_ctx);
@@ -1798,6 +1817,9 @@ static void demux_copy(struct demuxer *dst, struct demuxer *src)
}
}
+ if (src->events & DEMUX_EVENT_DURATION)
+ dst->duration = src->duration;
+
dst->events |= src->events;
src->events = 0;
}
@@ -1968,6 +1990,7 @@ static struct demuxer *open_given_type(struct mpv_global *global,
.max_bytes = opts->max_bytes,
.max_bytes_bw = opts->max_bytes_bw,
.initial_state = true,
+ .highest_av_pts = MP_NOPTS_VALUE,
};
pthread_mutex_init(&in->lock, NULL);
pthread_cond_init(&in->wakeup, NULL);
diff --git a/demux/demux.h b/demux/demux.h
index ab8edb7aa0..85bd5fd626 100644
--- a/demux/demux.h
+++ b/demux/demux.h
@@ -91,6 +91,7 @@ enum demux_event {
DEMUX_EVENT_INIT = 1 << 0, // complete (re-)initialization
DEMUX_EVENT_STREAMS = 1 << 1, // a stream was added
DEMUX_EVENT_METADATA = 1 << 2, // metadata or stream_metadata changed
+ DEMUX_EVENT_DURATION = 1 << 3, // duration updated
DEMUX_EVENT_ALL = 0xFFFF,
};
diff --git a/player/command.c b/player/command.c
index 974c61769e..6288106bee 100644
--- a/player/command.c
+++ b/player/command.c
@@ -4117,6 +4117,7 @@ static const char *const *const mp_event_property_change[] = {
"estimated-display-fps", "vsync-jitter", "sub-text", "audio-bitrate",
"video-bitrate", "sub-bitrate", "decoder-frame-drop-count",
"frame-drop-count", "video-frame-info"),
+ E(MP_EVENT_DURATION_UPDATE, "duration"),
E(MPV_EVENT_VIDEO_RECONFIG, "video-out-params", "video-params",
"video-format", "video-codec", "video-bitrate", "dwidth", "dheight",
"width", "height", "fps", "aspect", "vo-configured", "current-vo",
diff --git a/player/command.h b/player/command.h
index 0ab746b1d2..478bc8c737 100644
--- a/player/command.h
+++ b/player/command.h
@@ -57,6 +57,7 @@ enum {
MP_EVENT_WIN_STATE,
MP_EVENT_CHANGE_PLAYLIST,
MP_EVENT_CORE_IDLE,
+ MP_EVENT_DURATION_UPDATE,
};
bool mp_hook_test_completion(struct MPContext *mpctx, char *type);
diff --git a/player/loadfile.c b/player/loadfile.c
index 8139c06f3f..d2e26c1ba4 100644
--- a/player/loadfile.c
+++ b/player/loadfile.c
@@ -212,6 +212,8 @@ void update_demuxer_properties(struct MPContext *mpctx)
mpctx->filtered_tags = info;
mp_notify(mpctx, MPV_EVENT_METADATA_UPDATE, NULL);
}
+ if (events & DEMUX_EVENT_DURATION)
+ mp_notify(mpctx, MP_EVENT_DURATION_UPDATE, NULL);
demuxer->events = 0;
}