summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/interface-changes.rst6
-rw-r--r--DOCS/man/input.rst13
-rw-r--r--DOCS/man/options.rst11
-rw-r--r--demux/demux.c21
-rw-r--r--demux/demux.h1
-rw-r--r--options/options.c3
-rw-r--r--options/options.h1
-rw-r--r--player/command.c10
-rw-r--r--player/core.h1
-rw-r--r--player/loadfile.c12
-rw-r--r--player/misc.c19
-rw-r--r--player/osd.c3
-rw-r--r--player/playloop.c22
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--;
}