From 29af78721760e426b920904d44566de482e30709 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 24 Dec 2017 01:56:09 +0100 Subject: player: update duration based on highest timestamp demuxed This will help with things like livestreams. As a minor detail, subtitles are excluded, because they sometimes have "unused" events after video and audio ends. To avoid this annoying corner case, just ignore them. --- demux/demux.c | 23 +++++++++++++++++++++++ demux/demux.h | 1 + player/command.c | 1 + player/command.h | 1 + player/loadfile.c | 2 ++ 5 files changed, 28 insertions(+) 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; } -- cgit v1.2.3