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);