diff options
author | Martin Herkt <lachs0r@srsfckn.biz> | 2016-02-28 23:31:51 +0100 |
---|---|---|
committer | Martin Herkt <lachs0r@srsfckn.biz> | 2016-02-28 23:31:51 +0100 |
commit | 21cd4ff05bb46b375a9ad38c9f0b7f8e71a5d979 (patch) | |
tree | b9679cc1d2c7c3cab0f88c370015f34f6d0b27ca /demux | |
parent | d1d6257731866934717353fce484f5f472f845d1 (diff) | |
parent | 1f436f65f2ee4df6419ca68bd6426b8283db6d22 (diff) | |
download | mpv-21cd4ff05bb46b375a9ad38c9f0b7f8e71a5d979.tar.bz2 mpv-21cd4ff05bb46b375a9ad38c9f0b7f8e71a5d979.tar.xz |
Merge branch 'master' into release/current
Diffstat (limited to 'demux')
-rw-r--r-- | demux/codec_tags.c | 14 | ||||
-rw-r--r-- | demux/codec_tags.h | 14 | ||||
-rw-r--r-- | demux/cue.c | 14 | ||||
-rw-r--r-- | demux/cue.h | 14 | ||||
-rw-r--r-- | demux/demux.c | 155 | ||||
-rw-r--r-- | demux/demux.h | 9 | ||||
-rw-r--r-- | demux/demux_cue.c | 14 | ||||
-rw-r--r-- | demux/demux_disc.c | 38 | ||||
-rw-r--r-- | demux/demux_edl.c | 14 | ||||
-rw-r--r-- | demux/demux_lavf.c | 42 | ||||
-rw-r--r-- | demux/demux_mf.c | 11 | ||||
-rw-r--r-- | demux/demux_mkv.c | 79 | ||||
-rw-r--r-- | demux/demux_mkv_timeline.c | 14 | ||||
-rw-r--r-- | demux/demux_playlist.c | 32 | ||||
-rw-r--r-- | demux/demux_rar.c | 14 | ||||
-rw-r--r-- | demux/demux_raw.c | 8 | ||||
-rw-r--r-- | demux/demux_timeline.c | 388 | ||||
-rw-r--r-- | demux/packet.c | 5 | ||||
-rw-r--r-- | demux/packet.h | 17 |
19 files changed, 647 insertions, 249 deletions
diff --git a/demux/codec_tags.c b/demux/codec_tags.c index 7e91291e9e..5f4f569435 100644 --- a/demux/codec_tags.c +++ b/demux/codec_tags.c @@ -1,18 +1,18 @@ /* * This file is part of mpv. * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. * * mpv is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see <http://www.gnu.org/licenses/>. + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see <http://www.gnu.org/licenses/>. */ #include <libavformat/avformat.h> diff --git a/demux/codec_tags.h b/demux/codec_tags.h index 294759a299..147760b0fe 100644 --- a/demux/codec_tags.h +++ b/demux/codec_tags.h @@ -1,18 +1,18 @@ /* * This file is part of mpv. * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. * * mpv is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see <http://www.gnu.org/licenses/>. + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see <http://www.gnu.org/licenses/>. */ #ifndef MP_CODEC_TAGS_H diff --git a/demux/cue.c b/demux/cue.c index 4a84107db7..69f30f4871 100644 --- a/demux/cue.c +++ b/demux/cue.c @@ -1,18 +1,18 @@ /* * This file is part of mpv. * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. * * mpv is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see <http://www.gnu.org/licenses/>. + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see <http://www.gnu.org/licenses/>. */ #include <stdlib.h> diff --git a/demux/cue.h b/demux/cue.h index 1ae5f0a203..61f18e6fa5 100644 --- a/demux/cue.h +++ b/demux/cue.h @@ -1,18 +1,18 @@ /* * This file is part of mpv. * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. * * mpv is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see <http://www.gnu.org/licenses/>. + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see <http://www.gnu.org/licenses/>. */ #ifndef MP_CUE_H_ diff --git a/demux/demux.c b/demux/demux.c index 19ad6970b0..05a8551608 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -36,6 +36,7 @@ #include "stream/stream.h" #include "demux.h" +#include "timeline.h" #include "stheader.h" #include "cue.h" @@ -52,6 +53,7 @@ extern const demuxer_desc_t demuxer_desc_playlist; extern const demuxer_desc_t demuxer_desc_disc; extern const demuxer_desc_t demuxer_desc_rar; extern const demuxer_desc_t demuxer_desc_libarchive; +extern const demuxer_desc_t demuxer_desc_timeline; /* Please do not add any new demuxers here. If you want to implement a new * demuxer, add it to libavformat, except for wrappers around external @@ -160,6 +162,10 @@ struct demux_stream { int64_t last_pos; struct demux_packet *head; struct demux_packet *tail; + + // for closed captions (demuxer_feed_caption) + struct sh_stream *cc; + }; // Return "a", or if that is NOPTS, return "def". @@ -361,6 +367,27 @@ const char *stream_type_name(enum stream_type type) } } +void demuxer_feed_caption(struct sh_stream *stream, demux_packet_t *dp) +{ + struct demuxer *demuxer = stream->ds->in->d_thread; + struct sh_stream *sh = stream->ds->cc; + + if (!sh) { + sh = demux_alloc_sh_stream(STREAM_SUB); + if (!sh) { + talloc_free(dp); + return; + } + sh->codec->codec = "eia_608"; + stream->ds->cc = sh; + demux_add_sh_stream(demuxer, sh); + } + + dp->pts = MP_ADD_PTS(dp->pts, -stream->ds->in->ts_offset); + dp->dts = MP_ADD_PTS(dp->dts, -stream->ds->in->ts_offset); + demux_add_packet(sh, dp); +} + void demux_add_packet(struct sh_stream *stream, demux_packet_t *dp) { struct demux_stream *ds = stream ? stream->ds : NULL; @@ -463,7 +490,12 @@ static bool read_packet(struct demux_internal *in) } for (int n = 0; n < in->num_streams; n++) { struct demux_stream *ds = in->streams[n]->ds; - ds->eof |= !ds->head; + bool eof = !ds->head; + if (eof && !ds->eof) { + if (in->wakeup_cb) + in->wakeup_cb(in->wakeup_cb_ctx); + } + ds->eof |= eof; } pthread_cond_signal(&in->wakeup); return false; @@ -548,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); } @@ -558,11 +589,18 @@ static void execute_trackswitch(struct demux_internal *in) { in->tracks_switched = false; + bool any_selected = false; + for (int n = 0; n < in->num_streams; n++) + any_selected |= in->streams[n]->ds->selected; + pthread_mutex_unlock(&in->lock); if (in->d_thread->desc->control) in->d_thread->desc->control(in->d_thread, DEMUXER_CTRL_SWITCHED_TRACKS, 0); + stream_control(in->d_thread->stream, STREAM_CTRL_SET_READAHEAD, + &(int){any_selected}); + pthread_mutex_lock(&in->lock); if (in->start_refresh_seek) @@ -664,23 +702,9 @@ static struct demux_packet *dequeue_packet(struct demux_stream *ds) pkt->pts = MP_ADD_PTS(pkt->pts, ds->in->ts_offset); pkt->dts = MP_ADD_PTS(pkt->dts, ds->in->ts_offset); - return pkt; -} + pkt->start = MP_ADD_PTS(pkt->start, ds->in->ts_offset); + pkt->end = MP_ADD_PTS(pkt->end, ds->in->ts_offset); -// Read a packet from the given stream. The returned packet belongs to the -// caller, who has to free it with talloc_free(). Might block. Returns NULL -// on EOF. -struct demux_packet *demux_read_packet(struct sh_stream *sh) -{ - struct demux_stream *ds = sh ? sh->ds : NULL; - struct demux_packet *pkt = NULL; - if (ds) { - pthread_mutex_lock(&ds->in->lock); - ds_get_packets(ds); - pkt = dequeue_packet(ds); - pthread_cond_signal(&ds->in->wakeup); // possibly read more - pthread_mutex_unlock(&ds->in->lock); - } return pkt; } @@ -699,6 +723,24 @@ static bool use_lazy_subtitle_reading(struct demux_stream *ds) return false; } +// Read a packet from the given stream. The returned packet belongs to the +// caller, who has to free it with talloc_free(). Might block. Returns NULL +// on EOF. +struct demux_packet *demux_read_packet(struct sh_stream *sh) +{ + struct demux_stream *ds = sh ? sh->ds : NULL; + struct demux_packet *pkt = NULL; + if (ds) { + pthread_mutex_lock(&ds->in->lock); + if (!use_lazy_subtitle_reading(ds)) + ds_get_packets(ds); + pkt = dequeue_packet(ds); + pthread_cond_signal(&ds->in->wakeup); // possibly read more + pthread_mutex_unlock(&ds->in->lock); + } + return pkt; +} + // Poll the demuxer queue, and if there's a packet, return it. Otherwise, just // make the demuxer thread read packets for this stream, and if there's at // least one packet, call the wakeup callback. @@ -749,7 +791,7 @@ bool demux_has_packet(struct sh_stream *sh) return has_packet; } -// Read and return any packet we find. +// Read and return any packet we find. NULL means EOF. struct demux_packet *demux_read_any_packet(struct demuxer *demuxer) { struct demux_internal *in = demuxer->in; @@ -904,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; @@ -1046,10 +1087,11 @@ static struct demuxer *open_given_type(struct mpv_global *global, in->d_user->metadata = talloc_zero(in->d_user, struct mp_tags); in->d_buffer->metadata = talloc_zero(in->d_buffer, struct mp_tags); - mp_verbose(log, "Trying demuxer: %s (force-level: %s)\n", - desc->name, d_level(check)); + mp_dbg(log, "Trying demuxer: %s (force-level: %s)\n", + desc->name, d_level(check)); - if (stream->seekable) // not for DVD/BD/DVB in particular + // not for DVD/BD/DVB in particular + if (stream->seekable && (!params || !params->timeline)) stream_seek(stream, 0); // Peek this much data to avoid that stream_read() run by some demuxers @@ -1076,6 +1118,17 @@ static struct demuxer *open_given_type(struct mpv_global *global, demux_init_cache(demuxer); demux_changed(in->d_thread, DEMUX_EVENT_ALL); demux_update(demuxer); + stream_control(demuxer->stream, STREAM_CTRL_SET_READAHEAD, &(int){false}); + struct timeline *tl = timeline_load(global, log, demuxer); + if (tl) { + struct demuxer_params params2 = {0}; + params2.timeline = tl; + struct demuxer *sub = open_given_type(global, log, + &demuxer_desc_timeline, stream, + ¶ms2, DEMUX_CHECK_FORCE); + if (sub) + return sub; + } return demuxer; } @@ -1119,6 +1172,7 @@ struct demuxer *demux_open(struct stream *stream, struct demuxer_params *params, // Test demuxers from first to last, one pass for each check_levels[] entry for (int pass = 0; check_levels[pass] != -1; pass++) { enum demux_check level = check_levels[pass]; + mp_verbose(log, "Trying demuxers for level=%s.\n", d_level(level)); for (int n = 0; demuxer_list[n]; n++) { const struct demuxer_desc *desc = demuxer_list[n]; if (!check_desc || desc == check_desc) { @@ -1184,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); @@ -1194,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) @@ -1255,37 +1299,26 @@ struct sh_stream *demuxer_stream_by_demuxer_id(struct demuxer *d, return NULL; } -void demuxer_switch_track(struct demuxer *demuxer, enum stream_type type, - struct sh_stream *stream) -{ - assert(!stream || stream->type == type); - - int num = demux_get_num_stream(demuxer); - for (int n = 0; n < num; n++) { - struct sh_stream *cur = demux_get_stream(demuxer, n); - if (cur->type == type) - demuxer_select_track(demuxer, cur, cur == stream); - } -} - void demuxer_select_track(struct demuxer *demuxer, struct sh_stream *stream, bool selected) { struct demux_internal *in = demuxer->in; pthread_mutex_lock(&in->lock); - bool update = false; // don't flush buffers if stream is already selected / unselected if (stream->ds->selected != selected) { stream->ds->selected = selected; stream->ds->active = false; ds_flush(stream->ds); - if (selected && in->refresh_seeks_enabled && in->threading) + in->tracks_switched = true; + if (selected && in->refresh_seeks_enabled) in->start_refresh_seek = true; - update = true; + if (in->threading) { + pthread_cond_signal(&in->wakeup); + } else { + execute_trackswitch(in); + } } pthread_mutex_unlock(&in->lock); - if (update) - demux_control(demuxer, DEMUXER_CTRL_SWITCHED_TRACKS, NULL); } void demux_set_stream_autoselect(struct demuxer *demuxer, bool autoselect) @@ -1456,10 +1489,6 @@ static int cached_demux_control(struct demux_internal *in, int cmd, void *arg) c->res = r; return DEMUXER_CTRL_OK; } - case DEMUXER_CTRL_SWITCHED_TRACKS: - in->tracks_switched = true; - pthread_cond_signal(&in->wakeup); - return DEMUXER_CTRL_OK; case DEMUXER_CTRL_GET_BITRATE_STATS: { double *rates = arg; for (int n = 0; n < STREAM_TYPE_COUNT; n++) diff --git a/demux/demux.h b/demux/demux.h index d274be5ae7..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 @@ -160,7 +159,7 @@ struct demuxer_params { struct matroska_segment_uid *matroska_wanted_uids; int matroska_wanted_segment; bool *matroska_was_valid; - bool expect_subtitle; + struct timeline *timeline; // -- demux_open_url() only int stream_flags; bool allow_capture; @@ -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 @@ -238,6 +234,7 @@ void free_demuxer(struct demuxer *demuxer); void free_demuxer_and_stream(struct demuxer *demuxer); void demux_add_packet(struct sh_stream *stream, demux_packet_t *dp); +void demuxer_feed_caption(struct sh_stream *stream, demux_packet_t *dp); struct demux_packet *demux_read_packet(struct sh_stream *sh); int demux_read_packet_async(struct sh_stream *sh, struct demux_packet **out_pkt); @@ -273,8 +270,6 @@ void demux_set_ts_offset(struct demuxer *demuxer, double offset); int demux_control(struct demuxer *demuxer, int cmd, void *arg); -void demuxer_switch_track(struct demuxer *demuxer, enum stream_type type, - struct sh_stream *stream); void demuxer_select_track(struct demuxer *demuxer, struct sh_stream *stream, bool selected); void demux_set_stream_autoselect(struct demuxer *demuxer, bool autoselect); diff --git a/demux/demux_cue.c b/demux/demux_cue.c index bef1516057..673e8b9f27 100644 --- a/demux/demux_cue.c +++ b/demux/demux_cue.c @@ -3,18 +3,18 @@ * * This file is part of mpv. * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. * * mpv is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see <http://www.gnu.org/licenses/>. + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see <http://www.gnu.org/licenses/>. */ #include <stdlib.h> diff --git a/demux/demux_disc.c b/demux/demux_disc.c index dcc3e7c79f..91b87a4631 100644 --- a/demux/demux_disc.c +++ b/demux/demux_disc.c @@ -1,18 +1,18 @@ /* * This file is part of mpv. * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. * * mpv is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see <http://www.gnu.org/licenses/>. + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see <http://www.gnu.org/licenses/>. */ #include <string.h> @@ -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_edl.c b/demux/demux_edl.c index 74ce7aef66..aeccab406f 100644 --- a/demux/demux_edl.c +++ b/demux/demux_edl.c @@ -3,18 +3,18 @@ * * This file is part of mpv. * - * mpv is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. * * mpv is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License along - * with mpv. If not, see <http://www.gnu.org/licenses/>. + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see <http://www.gnu.org/licenses/>. */ #include <stdlib.h> diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index 1b3105170d..8a92a2886f 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -164,12 +164,12 @@ 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; char *mime_type; bool merge_track_metadata; + double seek_delay; } lavf_priv_t; // At least mp4 has name="mov,mp4,m4a,3gp,3g2,mj2", so we split the name @@ -282,6 +282,8 @@ static void convert_charset(struct demuxer *demuxer) // libavformat transparently converts UTF-16 to UTF-8 if (!mp_charset_is_utf16(cp) && !mp_charset_is_utf8(cp)) { bstr conv = mp_iconv_to_utf8(demuxer->log, data, cp, MP_ICONV_VERBOSE); + if (conv.start && conv.start != data.start) + talloc_steal(alloc, conv.start); if (conv.start) data = conv; } @@ -562,6 +564,11 @@ static void handle_new_stream(demuxer_t *demuxer, int i) sh->codec->samplerate = codec->sample_rate; sh->codec->bitrate = codec->bit_rate; + double delay = 0; + if (codec->sample_rate > 0) + delay = codec->delay / (double)codec->sample_rate; + priv->seek_delay = MPMAX(priv->seek_delay, delay); + export_replaygain(demuxer, sh->codec, st); break; @@ -912,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) @@ -926,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) { @@ -948,26 +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 { - priv->last_pts += rel_seek_secs * AV_TIME_BASE; + if (flags & SEEK_BACKWARD) + 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 @@ -975,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 a91d13dff2..c0b159e4ea 100644 --- a/demux/demux_mf.c +++ b/ |