summaryrefslogtreecommitdiffstats
path: root/demux
diff options
context:
space:
mode:
authorMartin Herkt <lachs0r@srsfckn.biz>2016-02-28 23:31:51 +0100
committerMartin Herkt <lachs0r@srsfckn.biz>2016-02-28 23:31:51 +0100
commit21cd4ff05bb46b375a9ad38c9f0b7f8e71a5d979 (patch)
treeb9679cc1d2c7c3cab0f88c370015f34f6d0b27ca /demux
parentd1d6257731866934717353fce484f5f472f845d1 (diff)
parent1f436f65f2ee4df6419ca68bd6426b8283db6d22 (diff)
downloadmpv-21cd4ff05bb46b375a9ad38c9f0b7f8e71a5d979.tar.bz2
mpv-21cd4ff05bb46b375a9ad38c9f0b7f8e71a5d979.tar.xz
Merge branch 'master' into release/current
Diffstat (limited to 'demux')
-rw-r--r--demux/codec_tags.c14
-rw-r--r--demux/codec_tags.h14
-rw-r--r--demux/cue.c14
-rw-r--r--demux/cue.h14
-rw-r--r--demux/demux.c155
-rw-r--r--demux/demux.h9
-rw-r--r--demux/demux_cue.c14
-rw-r--r--demux/demux_disc.c38
-rw-r--r--demux/demux_edl.c14
-rw-r--r--demux/demux_lavf.c42
-rw-r--r--demux/demux_mf.c11
-rw-r--r--demux/demux_mkv.c79
-rw-r--r--demux/demux_mkv_timeline.c14
-rw-r--r--demux/demux_playlist.c32
-rw-r--r--demux/demux_rar.c14
-rw-r--r--demux/demux_raw.c8
-rw-r--r--demux/demux_timeline.c388
-rw-r--r--demux/packet.c5
-rw-r--r--demux/packet.h17
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,
+ &params2, 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/