summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--demux/demux.c28
-rw-r--r--demux/demux.h4
-rw-r--r--demux/demux_disc.c24
-rw-r--r--demux/demux_lavf.c34
-rw-r--r--demux/demux_mf.c9
-rw-r--r--demux/demux_mkv.c17
-rw-r--r--demux/demux_raw.c8
-rw-r--r--demux/demux_timeline.c18
-rw-r--r--player/loadfile.c2
-rw-r--r--player/playloop.c15
-rw-r--r--player/sub.c2
-rw-r--r--stream/stream_dvdnav.c37
12 files changed, 49 insertions, 149 deletions
diff --git a/demux/demux.c b/demux/demux.c
index fe72d3ef4c..05a8551608 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -580,8 +580,7 @@ static void start_refreshing(struct demux_internal *in)
pthread_mutex_unlock(&in->lock);
// Seek back to player's current position, with a small offset added.
- in->d_thread->desc->seek(in->d_thread, start_ts - 1.0,
- SEEK_ABSOLUTE | SEEK_BACKWARD | SEEK_HR);
+ in->d_thread->desc->seek(in->d_thread, start_ts - 1.0, SEEK_BACKWARD | SEEK_HR);
pthread_mutex_lock(&in->lock);
}
@@ -947,7 +946,6 @@ static void demux_copy(struct demuxer *dst, struct demuxer *src)
dst->partially_seekable = src->partially_seekable;
dst->filetype = src->filetype;
dst->ts_resets_possible = src->ts_resets_possible;
- dst->rel_seeks = src->rel_seeks;
dst->allow_refresh_seeks = src->allow_refresh_seeks;
dst->fully_read = src->fully_read;
dst->start_time = src->start_time;
@@ -1240,7 +1238,7 @@ void demux_flush(demuxer_t *demuxer)
pthread_mutex_unlock(&demuxer->in->lock);
}
-int demux_seek(demuxer_t *demuxer, double rel_seek_secs, int flags)
+int demux_seek(demuxer_t *demuxer, double seek_pts, int flags)
{
struct demux_internal *in = demuxer->in;
assert(demuxer == in->d_user);
@@ -1250,32 +1248,22 @@ int demux_seek(demuxer_t *demuxer, double rel_seek_secs, int flags)
return 0;
}
- if ((flags & SEEK_FACTOR) && !(flags & SEEK_ABSOLUTE)) {
- MP_WARN(demuxer, "Invalid seek flags.\n");
- return 0;
- }
-
- if (rel_seek_secs == MP_NOPTS_VALUE && (flags & SEEK_ABSOLUTE))
+ if (seek_pts == MP_NOPTS_VALUE)
return 0;
- if (!(flags & (SEEK_BACKWARD | SEEK_FORWARD))) {
- if (flags & SEEK_ABSOLUTE || rel_seek_secs < 0) {
- flags |= SEEK_BACKWARD;
- } else {
- flags |= SEEK_FORWARD;
- }
- }
+ if (!(flags & SEEK_FORWARD))
+ flags |= SEEK_BACKWARD;
pthread_mutex_lock(&in->lock);
- MP_VERBOSE(in, "queuing seek to %f%s\n", rel_seek_secs,
+ MP_VERBOSE(in, "queuing seek to %f%s\n", seek_pts,
in->seeking ? " (cascade)" : "");
flush_locked(demuxer);
in->seeking = true;
in->seek_flags = flags;
- in->seek_pts = rel_seek_secs;
- if ((flags & SEEK_ABSOLUTE) && !(flags & SEEK_FACTOR))
+ in->seek_pts = seek_pts;
+ if (!(flags & SEEK_FACTOR))
in->seek_pts = MP_ADD_PTS(in->seek_pts, -in->ts_offset);
if (!in->threading)
diff --git a/demux/demux.h b/demux/demux.h
index 05e645f728..e882e90da8 100644
--- a/demux/demux.h
+++ b/demux/demux.h
@@ -57,7 +57,6 @@ struct demux_ctrl_stream_ctrl {
int res;
};
-#define SEEK_ABSOLUTE (1 << 0) // argument is a timestamp
#define SEEK_FACTOR (1 << 1) // argument is in range [0,1]
#define SEEK_FORWARD (1 << 2) // prefer later time if not exact
#define SEEK_BACKWARD (1 << 3) // prefer earlier time if not exact
@@ -179,9 +178,6 @@ typedef struct demuxer {
double start_time;
// File format allows PTS resets (even if the current file is without)
bool ts_resets_possible;
- // Send relative seek requests, instead of SEEK_ABSOLUTE or SEEK_FACTOR.
- // This is only done if the user explicitly uses a relative seek.
- bool rel_seeks;
// Enable fast track switching hacks. This requires from the demuxer:
// - seeking is somewhat reliable; packet contents must not change
// - packet position (demux_packet.pos) is set, not negative, unique, and
diff --git a/demux/demux_disc.c b/demux/demux_disc.c
index 7feec6ca72..91b87a4631 100644
--- a/demux/demux_disc.c
+++ b/demux/demux_disc.c
@@ -42,7 +42,6 @@ struct priv {
double base_time; // playback display start time of current segment
double base_dts; // packet DTS that maps to base_time
double last_dts; // DTS of previously demuxed packet
- double seek_pts;
bool seek_reinit; // needs reinit after seek
};
@@ -159,35 +158,27 @@ static void add_streams(demuxer_t *demuxer)
reselect_streams(demuxer);
}
-static void d_seek(demuxer_t *demuxer, double rel_seek_secs, int flags)
+static void d_seek(demuxer_t *demuxer, double seek_pts, int flags)
{
struct priv *p = demuxer->priv;
if (demuxer->stream->uncached_type == STREAMTYPE_CDDA) {
- demux_seek(p->slave, rel_seek_secs, flags);
+ demux_seek(p->slave, seek_pts, flags);
return;
}
- double pts = p->seek_pts;
- if (flags & SEEK_ABSOLUTE)
- pts = 0.0f;
- double base_pts = pts; // to what pts is relative
-
if (flags & SEEK_FACTOR) {
double tmp = 0;
stream_control(demuxer->stream, STREAM_CTRL_GET_TIME_LENGTH, &tmp);
- pts += tmp * rel_seek_secs;
- } else {
- pts += rel_seek_secs;
+ seek_pts *= tmp;
}
- MP_VERBOSE(demuxer, "seek to: %f\n", pts);
+ MP_VERBOSE(demuxer, "seek to: %f\n", seek_pts);
- double seek_arg[] = {pts, base_pts, flags};
+ double seek_arg[] = {seek_pts, flags};
stream_control(demuxer->stream, STREAM_CTRL_SEEK_TO_TIME, seek_arg);
demux_control(p->slave, DEMUXER_CTRL_RESYNC, NULL);
- p->seek_pts = pts;
p->seek_reinit = true;
}
@@ -268,9 +259,6 @@ static int d_fill_buffer(demuxer_t *demuxer)
MP_TRACE(demuxer, "opts: %d %f %f\n", sh->type, pkt->pts, pkt->dts);
- if (pkt->pts != MP_NOPTS_VALUE)
- p->seek_pts = pkt->pts;
-
demux_add_packet(sh, pkt);
return 1;
}
@@ -328,8 +316,6 @@ static int d_open(demuxer_t *demuxer, enum demux_check check)
// Can be seekable even if the stream isn't.
demuxer->seekable = true;
-
- demuxer->rel_seeks = true;
}
add_dvd_streams(demuxer);
diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c
index 518dd0f8dd..8a92a2886f 100644
--- a/demux/demux_lavf.c
+++ b/demux/demux_lavf.c
@@ -164,7 +164,6 @@ typedef struct lavf_priv {
int avif_flags;
AVFormatContext *avfc;
AVIOContext *pb;
- int64_t last_pts;
struct sh_stream **streams; // NULL for unknown streams
int num_streams;
int cur_program;
@@ -920,11 +919,6 @@ static int demux_lavf_fill_buffer(demuxer_t *demux)
#endif
dp->pos = pkt->pos;
dp->keyframe = pkt->flags & AV_PKT_FLAG_KEY;
- if (dp->pts != MP_NOPTS_VALUE) {
- priv->last_pts = dp->pts * AV_TIME_BASE;
- } else if (dp->dts != MP_NOPTS_VALUE) {
- priv->last_pts = dp->dts * AV_TIME_BASE;
- }
av_packet_unref(pkt);
if (priv->format_hack.clear_filepos)
@@ -934,19 +928,13 @@ static int demux_lavf_fill_buffer(demuxer_t *demux)
return 1;
}
-static void demux_seek_lavf(demuxer_t *demuxer, double rel_seek_secs, int flags)
+static void demux_seek_lavf(demuxer_t *demuxer, double seek_pts, int flags)
{
lavf_priv_t *priv = demuxer->priv;
int avsflags = 0;
+ int64_t seek_pts_av = 0;
- if (flags & SEEK_ABSOLUTE)
- priv->last_pts = 0;
- else if (rel_seek_secs < 0)
- avsflags = AVSEEK_FLAG_BACKWARD;
-
- if (flags & SEEK_FORWARD)
- avsflags = 0;
- else if (flags & SEEK_BACKWARD)
+ if (flags & SEEK_BACKWARD)
avsflags = AVSEEK_FLAG_BACKWARD;
if (flags & SEEK_FACTOR) {
@@ -956,28 +944,28 @@ static void demux_seek_lavf(demuxer_t *demuxer, double rel_seek_secs, int flags)
!(priv->avif_flags & AVFMT_NO_BYTE_SEEK))
{
avsflags |= AVSEEK_FLAG_BYTE;
- priv->last_pts = end * rel_seek_secs;
+ seek_pts_av = end * seek_pts;
} else if (priv->avfc->duration != 0 &&
priv->avfc->duration != AV_NOPTS_VALUE)
{
- priv->last_pts = rel_seek_secs * priv->avfc->duration;
+ seek_pts_av = seek_pts * priv->avfc->duration;
}
} else {
if (flags & SEEK_BACKWARD)
- rel_seek_secs -= priv->seek_delay;
- priv->last_pts += rel_seek_secs * AV_TIME_BASE;
+ seek_pts -= priv->seek_delay;
+ seek_pts_av = seek_pts * AV_TIME_BASE;
}
int r;
if (!priv->avfc->iformat->read_seek2) {
// Normal seeking.
- r = av_seek_frame(priv->avfc, -1, priv->last_pts, avsflags);
+ r = av_seek_frame(priv->avfc, -1, seek_pts_av, avsflags);
if (r < 0 && (avsflags & AVSEEK_FLAG_BACKWARD)) {
// When seeking before the beginning of the file, and seeking fails,
// try again without the backwards flag to make it seek to the
// beginning.
avsflags &= ~AVSEEK_FLAG_BACKWARD;
- r = av_seek_frame(priv->avfc, -1, priv->last_pts, avsflags);
+ r = av_seek_frame(priv->avfc, -1, seek_pts_av, avsflags);
}
} else {
// av_seek_frame() won't work. Use "new" seeking API. We don't use this
@@ -985,11 +973,11 @@ static void demux_seek_lavf(demuxer_t *demuxer, double rel_seek_secs, int flags)
// Set max_ts==ts, so that demuxing starts from an earlier position in
// the worst case.
r = avformat_seek_file(priv->avfc, -1, INT64_MIN,
- priv->last_pts, priv->last_pts, avsflags);
+ seek_pts_av, seek_pts_av, avsflags);
// Similar issue as in the normal seeking codepath.
if (r < 0) {
r = avformat_seek_file(priv->avfc, -1, INT64_MIN,
- priv->last_pts, INT64_MAX, avsflags);
+ seek_pts_av, INT64_MAX, avsflags);
}
}
if (r < 0) {
diff --git a/demux/demux_mf.c b/demux/demux_mf.c
index c60f5c6307..c0b159e4ea 100644
--- a/demux/demux_mf.c
+++ b/demux/demux_mf.c
@@ -159,15 +159,12 @@ static mf_t *open_mf_single(void *talloc_ctx, struct mp_log *log, char *filename
return mf;
}
-static void demux_seek_mf(demuxer_t *demuxer, double rel_seek_secs, int flags)
+static void demux_seek_mf(demuxer_t *demuxer, double seek_pts, int flags)
{
mf_t *mf = demuxer->priv;
- int newpos = (flags & SEEK_ABSOLUTE) ? 0 : mf->curr_frame - 1;
-
+ int newpos = seek_pts * mf->sh->codec->fps;
if (flags & SEEK_FACTOR)
- newpos += rel_seek_secs * (mf->nr_of_files - 1);
- else
- newpos += rel_seek_secs * mf->sh->codec->fps;
+ newpos = seek_pts * (mf->nr_of_files - 1);
if (newpos < 0)
newpos = 0;
if (newpos >= mf->nr_of_files)
diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c
index 7b5efd8219..c932b45f39 100644
--- a/demux/demux_mkv.c
+++ b/demux/demux_mkv.c
@@ -163,7 +163,7 @@ struct block_info {
typedef struct mkv_demuxer {
int64_t segment_start, segment_end;
- double duration, last_pts;
+ double duration;
mkv_track_t **tracks;
int num_tracks;
@@ -2441,7 +2441,6 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info)
if (use_this_block) {
uint64_t filepos = block_info->filepos;
- mkv_d->last_pts = current_pts;
for (int i = 0; i < laces; i++) {
bstr block = bstr_splice(data, 0, lace_size[i]);
@@ -2459,7 +2458,7 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info)
* values being the same). Also, don't use it for extra
* packets resulting from parsing. */
if (i == 0 || track->default_duration)
- dp->pts = mkv_d->last_pts + i * track->default_duration;
+ dp->pts = current_pts + i * track->default_duration;
if (stream->codec->avi_dts)
MPSWAP(double, dp->pts, dp->dts);
if (i == 0)
@@ -2784,7 +2783,7 @@ static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id,
return index;
}
-static void demux_mkv_seek(demuxer_t *demuxer, double rel_seek_secs, int flags)
+static void demux_mkv_seek(demuxer_t *demuxer, double seek_pts, int flags)
{
mkv_demuxer_t *mkv_d = demuxer->priv;
int64_t old_pos = stream_tell(demuxer->stream);
@@ -2814,15 +2813,13 @@ static void demux_mkv_seek(demuxer_t *demuxer, double rel_seek_secs, int flags)
// Adjust the target a little bit to catch cases where the target position
// specifies a keyframe with high, but not perfect, precision.
- rel_seek_secs += flags & SEEK_FORWARD ? -0.005 : 0.005;
+ seek_pts += flags & SEEK_FORWARD ? -0.005 : 0.005;
if (!(flags & SEEK_FACTOR)) { /* time in secs */
mkv_index_t *index = NULL;
- if (!(flags & SEEK_ABSOLUTE)) /* relative seek */
- rel_seek_secs += mkv_d->last_pts;
- rel_seek_secs = FFMAX(rel_seek_secs, 0);
- int64_t target_timecode = rel_seek_secs * 1e9 + 0.5;
+ seek_pts = FFMAX(seek_pts, 0);
+ int64_t target_timecode = seek_pts * 1e9 + 0.5;
if (create_index_until(demuxer, target_timecode) >= 0) {
int seek_id = st_active[STREAM_VIDEO] ? v_tnum : a_tnum;
@@ -2846,7 +2843,7 @@ static void demux_mkv_seek(demuxer_t *demuxer, double rel_seek_secs, int flags)
read_deferred_cues(demuxer);
int64_t size = stream_get_size(s);
- int64_t target_filepos = size * MPCLAMP(rel_seek_secs, 0, 1);
+ int64_t target_filepos = size * MPCLAMP(seek_pts, 0, 1);
mkv_index_t *index = NULL;
if (mkv_d->index_complete) {
diff --git a/demux/demux_raw.c b/demux/demux_raw.c
index 7fd9fdefa2..0d7517c3f0 100644
--- a/demux/demux_raw.c
+++ b/demux/demux_raw.c
@@ -263,17 +263,15 @@ static int raw_fill_buffer(demuxer_t *demuxer)
return 1;
}
-static void raw_seek(demuxer_t *demuxer, double rel_seek_secs, int flags)
+static void raw_seek(demuxer_t *demuxer, double seek_pts, int flags)
{
struct priv *p = demuxer->priv;
stream_t *s = demuxer->stream;
int64_t end = 0;
stream_control(s, STREAM_CTRL_GET_SIZE, &end);
- int64_t pos = (flags & SEEK_ABSOLUTE) ? 0 : stream_tell(s);
+ int64_t pos = seek_pts * p->frame_rate * p->frame_size;
if (flags & SEEK_FACTOR)
- pos += end * rel_seek_secs;
- else
- pos += rel_seek_secs * p->frame_rate * p->frame_size;
+ pos = end * seek_pts;
if (pos < 0)
pos = 0;
if (end && pos > end)
diff --git a/demux/demux_timeline.c b/demux/demux_timeline.c
index 9fba3d5abb..0c6c3986cc 100644
--- a/demux/demux_timeline.c
+++ b/demux/demux_timeline.c
@@ -63,8 +63,6 @@ struct priv {
// Total number of packets received past end of segment. Used
// to be clever about determining when to switch segments.
int eos_packets;
-
- double seek_pts;
};
static void reselect_streams(struct demuxer *demuxer)
@@ -107,7 +105,7 @@ static void switch_segment(struct demuxer *demuxer, struct segment *new,
p->current = new;
reselect_streams(demuxer);
demux_set_ts_offset(new->d, new->start - new->d_start);
- demux_seek(new->d, start_pts, flags | SEEK_ABSOLUTE);
+ demux_seek(new->d, start_pts, flags);
for (int n = 0; n < p->num_streams; n++) {
struct virtual_stream *vs = &p->streams[n];
@@ -118,19 +116,11 @@ static void switch_segment(struct demuxer *demuxer, struct segment *new,
p->eos_packets = 0;
}
-static void d_seek(struct demuxer *demuxer, double rel_seek_secs, int flags)
+static void d_seek(struct demuxer *demuxer, double seek_pts, int flags)
{
struct priv *p = demuxer->priv;
- double pts = p->seek_pts;
- if (flags & SEEK_ABSOLUTE)
- pts = 0.0f;
-
- if (flags & SEEK_FACTOR) {
- pts += p->duration * rel_seek_secs;
- } else {
- pts += rel_seek_secs;
- }
+ double pts = seek_pts * ((flags & SEEK_FACTOR) ? p->duration : 1);
flags &= SEEK_FORWARD | SEEK_BACKWARD | SEEK_HR;
@@ -144,8 +134,6 @@ static void d_seek(struct demuxer *demuxer, double rel_seek_secs, int flags)
p->current = NULL; // force seek
switch_segment(demuxer, new, pts, flags);
-
- p->seek_pts = pts;
}
static int d_fill_buffer(struct demuxer *demuxer)
diff --git a/player/loadfile.c b/player/loadfile.c
index 9ab930dfa7..b1e9cd2057 100644
--- a/player/loadfile.c
+++ b/player/loadfile.c
@@ -209,7 +209,7 @@ void reselect_demux_stream(struct MPContext *mpctx, struct track *track)
double pts = get_current_time(mpctx);
if (pts == MP_NOPTS_VALUE)
pts = 0;
- demux_seek(track->demuxer, pts, SEEK_ABSOLUTE);
+ demux_seek(track->demuxer, pts, 0);
}
}
}
diff --git a/player/playloop.c b/player/playloop.c
index 3e68ee9027..07a21e462c 100644
--- a/player/playloop.c
+++ b/player/playloop.c
@@ -242,8 +242,7 @@ static int mp_seek(MPContext *mpctx, struct seek_params seek)
// Prefer doing absolute seeks, unless not possible.
if ((seek.type == MPSEEK_FACTOR && !mpctx->demuxer->ts_resets_possible &&
- target_time != MP_NOPTS_VALUE) ||
- (seek.type == MPSEEK_RELATIVE && (!mpctx->demuxer->rel_seeks || hr_seek)))
+ target_time != MP_NOPTS_VALUE) || seek.type == MPSEEK_RELATIVE)
{
seek.type = MPSEEK_ABSOLUTE;
seek.amount = target_time;
@@ -253,15 +252,7 @@ static int mp_seek(MPContext *mpctx, struct seek_params seek)
double demuxer_amount = seek.amount;
- int demuxer_style = 0;
- switch (seek.type) {
- case MPSEEK_FACTOR:
- demuxer_style |= SEEK_ABSOLUTE | SEEK_FACTOR;
- break;
- case MPSEEK_ABSOLUTE:
- demuxer_style |= SEEK_ABSOLUTE;
- break;
- }
+ int demuxer_style = seek.type == MPSEEK_FACTOR ? SEEK_FACTOR : 0;
if (hr_seek || direction < 0) {
demuxer_style |= SEEK_BACKWARD;
} else if (direction > 0) {
@@ -281,7 +272,7 @@ static int mp_seek(MPContext *mpctx, struct seek_params seek)
double main_new_pos = demuxer_amount;
if (seek.type != MPSEEK_ABSOLUTE)
main_new_pos = target_time;
- demux_seek(track->demuxer, main_new_pos, SEEK_ABSOLUTE | SEEK_BACKWARD);
+ demux_seek(track->demuxer, main_new_pos, 0);
}
}
diff --git a/player/sub.c b/player/sub.c
index 6b2a3664dc..6892ac935b 100644
--- a/player/sub.c
+++ b/player/sub.c
@@ -103,7 +103,7 @@ static bool update_subtitle(struct MPContext *mpctx, double video_pts,
{
// Assume fully_read implies no interleaved audio/video streams.
// (Reading packets will change the demuxer position.)
- demux_seek(track->demuxer, 0, SEEK_ABSOLUTE);
+ demux_seek(track->demuxer, 0, 0);
track->preloaded = sub_read_all_packets(track->d_sub);
}
diff --git a/stream/stream_dvdnav.c b/stream/stream_dvdnav.c
index e2562dbcbc..d61ca5c937 100644
--- a/stream/stream_dvdnav.c
+++ b/stream/stream_dvdnav.c
@@ -332,8 +332,7 @@ static int control(stream_t *stream, int cmd, void *arg)
case STREAM_CTRL_SEEK_TO_TIME: {
double *args = arg;
double d = args[0]; // absolute target timestamp
- double r = args[1]; // if not SEEK_ABSOLUTE, the base time for d
- int flags = args[2]; // from SEEK_* flags (demux.h)
+ int flags = args[1]; // from SEEK_* flags (demux.h)
if (flags & SEEK_HR)
d -= 10; // fudge offset; it's a hack, because fuck libdvd*
int64_t tm = (int64_t)(d * 90000);
@@ -344,37 +343,9 @@ static int control(stream_t *stream, int cmd, void *arg)
uint32_t pos, len;
if (dvdnav_get_position(dvdnav, &pos, &len) != DVDNAV_STATUS_OK)
break;
- // The following is convoluted, because we have to translate between
- // dvdnav's block/CBR-based seeking bullshit, and the player's
- // timestamp-based high-level machinery.
- if (!(flags & SEEK_ABSOLUTE) && !(flags & SEEK_HR) && priv->duration > 0)
- {
- int dir = (flags & SEEK_BACKWARD) ? -1 : 1;
- // The user is making a relative seek (translated to absolute),
- // and we try not to get the user stuck on "boundaries". So try
- // to do block based seeks, which should workaround libdvdnav's
- // terrible CBR-based seeking.
- d -= r; // relative seek amount in seconds
- d = d / (priv->duration / 1000.0) * len; // d is now in blocks
- d += pos; // absolute target in blocks
- if (dir > 0)
- d = MPMAX(d, pos + 1.0);
- if (dir < 0)
- d = MPMIN(d, pos - 1.0);
- d += 0.5; // round
- uint32_t target = MPCLAMP(d, 0, len);
- MP_VERBOSE(stream, "seek from block %lu to %lu, dir=%d\n",
- (unsigned long)pos, (unsigned long)target, dir);
- if (dvdnav_sector_search(dvdnav, target, SEEK_SET) != DVDNAV_STATUS_OK)
- break;
- } else {
- // "old" method, should be good enough for large seeks. Used for
- // hr-seeks (with fudge offset), because I fear that block-based
- // seeking might be off too far for large jumps.
- MP_VERBOSE(stream, "seek to PTS %f (%"PRId64")\n", d, tm);
- if (dvdnav_time_search(dvdnav, tm) != DVDNAV_STATUS_OK)
- break;
- }
+ MP_VERBOSE(stream, "seek to PTS %f (%"PRId64")\n", d, tm);
+ if (dvdnav_time_search(dvdnav, tm) != DVDNAV_STATUS_OK)
+ break;
stream_drop_buffers(stream);
d = dvdnav_get_current_time(dvdnav) / 90000.0f;
MP_VERBOSE(stream, "landed at: %f\n", d);