diff options
-rw-r--r-- | DOCS/interface-changes.rst | 6 | ||||
-rw-r--r-- | DOCS/man/input.rst | 13 | ||||
-rw-r--r-- | DOCS/man/options.rst | 11 | ||||
-rw-r--r-- | demux/demux.c | 21 | ||||
-rw-r--r-- | demux/demux.h | 1 | ||||
-rw-r--r-- | options/options.c | 3 | ||||
-rw-r--r-- | options/options.h | 1 | ||||
-rw-r--r-- | player/command.c | 10 | ||||
-rw-r--r-- | player/core.h | 1 | ||||
-rw-r--r-- | player/loadfile.c | 12 | ||||
-rw-r--r-- | player/misc.c | 19 | ||||
-rw-r--r-- | player/osd.c | 3 | ||||
-rw-r--r-- | player/playloop.c | 22 |
13 files changed, 79 insertions, 44 deletions
diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst index dd42895203..2dd2e052ac 100644 --- a/DOCS/interface-changes.rst +++ b/DOCS/interface-changes.rst @@ -21,6 +21,12 @@ Interface changes --- mpv 0.14.0 --- - add "vsync-ratio" property + - add --rebase-start-time option + This is a breaking change to start time handling. Instead of making start + time handling an aspect of different options and properties (like + "time-pos" vs. "playback-time"), make it dependent on the new option. For + compatibility, the "time-start" property now always returns 0, so code + which attempted to handle rebasing manually will not break. --- mpv 0.13.0 --- - remove VO opengl-cb frame queue suboptions (no replacement) --- mpv 0.12.0 --- diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst index 0233dbf057..b581c5a8ad 100644 --- a/DOCS/man/input.rst +++ b/DOCS/man/input.rst @@ -943,8 +943,9 @@ Property list Position in current file in seconds. ``time-start`` - Return the start time of the file. (Usually 0, but some kind of files, - especially transport streams, can have a different start time.) + Deprecated. Always returns 0. Before mpv 0.14, this used to return the start + time of the file (could affect e.g. transport streams). See + ``--rebase-start-time`` option. ``time-remaining`` Remaining length of the file in seconds. Note that the file duration is not @@ -954,9 +955,11 @@ Property list ``time-remaining`` scaled by the current ``speed``. ``playback-time`` (RW) - The playback time, which is the time relative to playback start. (This can - be different from the ``time-pos`` property if the file does not start at - position ``0``, in which case ``time-pos`` is the source timestamp.) + Position in current file in seconds. Unlike ``time-pos``, the time is + clamped to the range of the file. (Inaccurate file durations etc. could + make it go out of range. Also helpful when the user attempts to seek + outside of the file, as the seek target time is considered the current + position during seeking.) ``chapter`` (RW) Current chapter number. The number of the first chapter is 0. diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 76a4e5a33b..fe76296d5f 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -69,7 +69,8 @@ Playback Control The general format for absolute times is ``[[hh:]mm:]ss[.ms]``. If the time is given with a prefix of ``+`` or ``-``, the seek is relative from the start - or end of the file. + or end of the file. (Since mpv 0.14, the start of the file is always + considered 0.) ``pp%`` seeks to percent position pp (0-100). @@ -101,6 +102,14 @@ Playback Control Stop after a given time relative to the start time. See ``--start`` for valid option values and examples. +``--rebase-start-time=<yes|no>`` + Whether to move the file start time to ``00:00:00`` (default: yes). This + is less awkward for files which start at a random timestamp, such as + transport streams. On the other hand, if there are timestamp resets, the + resulting behavior can be rather weird. For this reason, and in case you + are actually interested in the real timestamps, this behavior can be + disabled with ``no``. + ``--speed=<0.01-100>`` Slow down or speed up playback by the factor given as parameter. diff --git a/demux/demux.c b/demux/demux.c index a00a3617cc..a3d1ecf7c2 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -124,6 +124,8 @@ struct demux_internal { bool refresh_seeks_enabled; bool start_refresh_seek; + double ts_offset; // timestamp offset to apply everything + // Cached state. bool force_cache_update; double time_length; @@ -164,6 +166,8 @@ struct demux_stream { #define MP_PTS_MIN(a, b) MPMIN(PTS_OR_DEF(a, b), PTS_OR_DEF(b, a)) #define MP_PTS_MAX(a, b) MPMAX(PTS_OR_DEF(a, b), PTS_OR_DEF(b, a)) +#define MP_ADD_PTS(a, b) ((a) == MP_NOPTS_VALUE ? (a) : ((a) + (b))) + static void demuxer_sort_chapters(demuxer_t *demuxer); static void *demux_thread(void *pctx); static void update_cache(struct demux_internal *in); @@ -189,6 +193,14 @@ static void ds_flush(struct demux_stream *ds) ds->last_pos = -1; } +void demux_set_ts_offset(struct demuxer *demuxer, double offset) +{ + struct demux_internal *in = demuxer->in; + pthread_mutex_lock(&in->lock); + in->ts_offset = offset; + pthread_mutex_unlock(&in->lock); +} + struct sh_stream *new_sh_stream(demuxer_t *demuxer, enum stream_type type) { assert(demuxer == demuxer->in->d_thread); @@ -603,6 +615,9 @@ static struct demux_packet *dequeue_packet(struct demux_stream *ds) if (pkt->pos >= ds->in->d_user->filepos) ds->in->d_user->filepos = pkt->pos; + pkt->pts = MP_ADD_PTS(pkt->pts, ds->in->ts_offset); + pkt->dts = MP_ADD_PTS(pkt->dts, ds->in->ts_offset); + return pkt; } @@ -664,7 +679,7 @@ double demux_get_next_pts(struct sh_stream *sh) pthread_mutex_lock(&sh->ds->in->lock); ds_get_packets(sh->ds); if (sh->ds->head) - res = sh->ds->head->pts; + res = MP_ADD_PTS(sh->ds->head->pts, sh->ds->in->ts_offset); pthread_mutex_unlock(&sh->ds->in->lock); } return res; @@ -1148,6 +1163,8 @@ int demux_seek(demuxer_t *demuxer, double rel_seek_secs, int flags) in->seeking = true; in->seek_flags = flags; in->seek_pts = rel_seek_secs; + if (flags & SEEK_ABSOLUTE) + in->seek_pts = MP_ADD_PTS(in->seek_pts, -in->ts_offset); if (!in->threading) execute_seek(in); @@ -1419,6 +1436,8 @@ static int cached_demux_control(struct demux_internal *in, int cmd, void *arg) r->ts_duration = MPMAX(0, r->ts_range[1] - r->ts_range[0]); if (!num_packets || in->seeking) r->ts_duration = 0; + r->ts_range[0] = MP_ADD_PTS(r->ts_range[0], in->ts_offset); + r->ts_range[1] = MP_ADD_PTS(r->ts_range[1], in->ts_offset); return DEMUXER_CTRL_OK; } } diff --git a/demux/demux.h b/demux/demux.h index 7823d50233..96717d5eeb 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -271,6 +271,7 @@ bool demux_cancel_test(struct demuxer *demuxer); void demux_flush(struct demuxer *demuxer); int demux_seek(struct demuxer *demuxer, double rel_seek_secs, int flags); void demux_set_enable_refresh_seeks(struct demuxer *demuxer, bool enabled); +void demux_set_ts_offset(struct demuxer *demuxer, double offset); int demux_control(struct demuxer *demuxer, int cmd, void *arg); diff --git a/options/options.c b/options/options.c index 5cb5e2b522..a42d818c83 100644 --- a/options/options.c +++ b/options/options.c @@ -198,6 +198,8 @@ const m_option_t mp_opts[] = { OPT_REL_TIME("end", play_end, 0), OPT_REL_TIME("length", play_length, 0), + OPT_FLAG("rebase-start-time", rebase_start_time, 0), + OPT_TIME("ab-loop-a", ab_loop[0], 0, .min = MP_NOPTS_VALUE), OPT_TIME("ab-loop-b", ab_loop[1], 0, .min = MP_NOPTS_VALUE), @@ -763,6 +765,7 @@ const struct MPOpts mp_default_opts = { .consolecontrols = 1, .playlist_pos = -1, .play_frames = -1, + .rebase_start_time = 1, .keep_open = 0, .stream_id = { { [STREAM_AUDIO] = -1, [STREAM_VIDEO] = -1, diff --git a/options/options.h b/options/options.h index 31006c11bd..49387f388b 100644 --- a/options/options.h +++ b/options/options.h @@ -173,6 +173,7 @@ typedef struct MPOpts { struct m_rel_time play_start; struct m_rel_time play_end; struct m_rel_time play_length; + int rebase_start_time; int play_frames; double ab_loop[2]; double step_sec; diff --git a/player/command.c b/player/command.c index eadcc27296..2e29f994de 100644 --- a/player/command.c +++ b/player/command.c @@ -658,11 +658,8 @@ static int mp_property_percent_pos(void *ctx, struct m_property *prop, static int mp_property_time_start(void *ctx, struct m_property *prop, int action, void *arg) { - MPContext *mpctx = ctx; - double start = get_start_time(mpctx); - if (start < 0) - return M_PROPERTY_UNAVAILABLE; - return property_time(action, arg, start); + // minor backwards-compat. + return property_time(action, arg, 0); } /// Current position in seconds (RW) @@ -723,8 +720,7 @@ static int mp_property_playback_time(void *ctx, struct m_property *prop, return M_PROPERTY_UNAVAILABLE; if (action == M_PROPERTY_SET) { - double target = get_start_time(mpctx) + *(double *)arg; - queue_seek(mpctx, MPSEEK_ABSOLUTE, target, MPSEEK_DEFAULT, true); + queue_seek(mpctx, MPSEEK_ABSOLUTE, *(double *)arg, MPSEEK_DEFAULT, true); return M_PROPERTY_OK; } return property_time(action, arg, get_playback_time(mpctx)); diff --git a/player/core.h b/player/core.h index abe1316b41..9f47e2ad4e 100644 --- a/player/core.h +++ b/player/core.h @@ -454,7 +454,6 @@ void mp_print_version(struct mp_log *log, int always); void wakeup_playloop(void *ctx); // misc.c -double get_start_time(struct MPContext *mpctx); double get_main_demux_pts(struct MPContext *mpctx); double get_track_video_offset(struct MPContext *mpctx, struct track *track); double rel_time_to_abs(struct MPContext *mpctx, struct m_rel_time t); diff --git a/player/loadfile.c b/player/loadfile.c index 3007ef4f8e..be54b4c9c0 100644 --- a/player/loadfile.c +++ b/player/loadfile.c @@ -714,6 +714,9 @@ struct track *mp_add_external_file(struct MPContext *mpctx, char *filename, if (!demuxer) goto err_out; + if (filter != STREAM_SUB && opts->rebase_start_time) + demux_set_ts_offset(demuxer, -demuxer->start_time); + struct track *first = NULL; for (int n = 0; n < demuxer->num_streams; n++) { struct sh_stream *sh = demuxer->streams[n]; @@ -910,6 +913,10 @@ static void load_chapters(struct MPContext *mpctx) talloc_free(mpctx->chapters); mpctx->num_chapters = src->num_chapters; mpctx->chapters = demux_copy_chapter_data(src->chapters, src->num_chapters); + if (mpctx->opts->rebase_start_time) { + for (int n = 0; n < mpctx->num_chapters; n++) + mpctx->chapters[n].pts -= src->start_time; + } } if (free_src) free_demuxer_and_stream(src); @@ -954,8 +961,11 @@ static void open_demux_thread(void *pctx) args->err = MPV_ERROR_LOADING_FAILED; } } - if (args->demux) + if (args->demux) { args->tl = timeline_load(global, args->log, args->demux); + if (global->opts->rebase_start_time) + demux_set_ts_offset(args->demux, -args->demux->start_time); + } } static void open_demux_reentrant(struct MPContext *mpctx) diff --git a/player/misc.c b/player/misc.c index 1e67adbe32..0a3479590d 100644 --- a/player/misc.c +++ b/player/misc.c @@ -56,21 +56,20 @@ double get_relative_time(struct MPContext *mpctx) double rel_time_to_abs(struct MPContext *mpctx, struct m_rel_time t) { double length = get_time_length(mpctx); - double start = get_start_time(mpctx); switch (t.type) { case REL_TIME_ABSOLUTE: return t.pos; case REL_TIME_RELATIVE: if (t.pos >= 0) { - return start + t.pos; + return t.pos; } else { if (length >= 0) - return MPMAX(start + length + t.pos, 0.0); + return MPMAX(length + t.pos, 0.0); } break; case REL_TIME_PERCENT: if (length >= 0) - return start + length * (t.pos / 100.0); + return length * (t.pos / 100.0); break; case REL_TIME_CHAPTER: if (chapter_start_time(mpctx, t.pos) != MP_NOPTS_VALUE) @@ -87,12 +86,11 @@ double get_play_end_pts(struct MPContext *mpctx) if (opts->play_end.type) { end = rel_time_to_abs(mpctx, opts->play_end); } else if (opts->play_length.type) { - double startpts = get_start_time(mpctx); double start = rel_time_to_abs(mpctx, opts->play_start); if (start == MP_NOPTS_VALUE) - start = startpts; + start = 0; double length = rel_time_to_abs(mpctx, opts->play_length); - if (start != MP_NOPTS_VALUE && length != MP_NOPTS_VALUE) + if (length != MP_NOPTS_VALUE) end = start + length; } if (opts->chapterrange[1] > 0) { @@ -117,18 +115,11 @@ double get_main_demux_pts(struct MPContext *mpctx) return main_new_pos; } -double get_start_time(struct MPContext *mpctx) -{ - return mpctx->demuxer ? mpctx->demuxer->start_time : 0; -} - // Get the offset from the given track to the video. double get_track_video_offset(struct MPContext *mpctx, struct track *track) { if (track && track->under_timeline) return mpctx->video_offset; - if (track && track->is_external) - return get_start_time(mpctx); return 0; } diff --git a/player/osd.c b/player/osd.c index cb49131cc1..ce3ba103cd 100644 --- a/player/osd.c +++ b/player/osd.c @@ -363,8 +363,7 @@ void set_osd_bar_chapters(struct MPContext *mpctx, int type) } else { int num = get_chapter_count(mpctx); for (int n = 0; n < num; n++) { - double time = chapter_start_time(mpctx, n) - - get_start_time(mpctx); + double time = chapter_start_time(mpctx, n); if (time >= 0) { float pos = time / len; MP_TARRAY_APPEND(mpctx, mpctx->osd_progbar.stops, diff --git a/player/playloop.c b/player/playloop.c index 643f290c48..6fa7b62292 100644 --- a/player/playloop.c +++ b/player/playloop.c @@ -205,7 +205,7 @@ static int mp_seek(MPContext *mpctx, struct seek_params seek, case MPSEEK_FACTOR: ; double len = get_time_length(mpctx); if (len >= 0) - target_time = seek.amount * len + get_start_time(mpctx); + target_time = seek.amount * len; break; } @@ -405,15 +405,14 @@ double get_playback_time(struct MPContext *mpctx) double cur = get_current_time(mpctx); if (cur == MP_NOPTS_VALUE) return cur; - double start = get_start_time(mpctx); // During seeking, the time corresponds to the last seek time - apply some // cosmetics to it. if (mpctx->playback_pts == MP_NOPTS_VALUE) { double length = get_time_length(mpctx); if (length >= 0) - cur = MPCLAMP(cur, start, start + length); + cur = MPCLAMP(cur, 0, length); } - return cur >= start ? cur - start : cur; + return cur; } // Return playback position in 0.0-1.0 ratio, or -1 if unknown. @@ -423,15 +422,15 @@ double get_current_pos_ratio(struct MPContext *mpctx, bool use_range) if (!demuxer) return -1; double ans = -1; - double start = get_start_time(mpctx); + double start = 0; double len = get_time_length(mpctx); if (use_range) { double startpos = rel_time_to_abs(mpctx, mpctx->opts->play_start); double endpos = get_play_end_pts(mpctx); - if (endpos == MP_NOPTS_VALUE || endpos > start + MPMAX(0, len)) - endpos = start + MPMAX(0, len); - if (startpos == MP_NOPTS_VALUE || startpos < start) - startpos = start; + if (endpos == MP_NOPTS_VALUE || endpos > MPMAX(0, len)) + endpos = MPMAX(0, len); + if (startpos == MP_NOPTS_VALUE || startpos < 0) + startpos = 0; if (endpos < startpos) endpos = startpos; start = startpos; @@ -506,7 +505,7 @@ char *chapter_name(struct MPContext *mpctx, int chapter) double chapter_start_time(struct MPContext *mpctx, int chapter) { if (chapter == -1) - return get_start_time(mpctx); + return 0; if (chapter >= 0 && chapter < mpctx->num_chapters) return mpctx->chapters[chapter].pts; return MP_NOPTS_VALUE; @@ -785,8 +784,7 @@ static void handle_loop_file(struct MPContext *mpctx) if (opts->loop_file && mpctx->stop_play == AT_END_OF_FILE) { mpctx->stop_play = KEEP_PLAYING; set_osd_function(mpctx, OSD_FFW); - queue_seek(mpctx, MPSEEK_ABSOLUTE, get_start_time(mpctx), - MPSEEK_DEFAULT, true); + queue_seek(mpctx, MPSEEK_ABSOLUTE, 0, MPSEEK_DEFAULT, true); if (opts->loop_file > 0) opts->loop_file--; } |