summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2019-05-22 22:27:07 +0200
committerwm4 <wm4@nowhere>2019-09-19 20:37:04 +0200
commit01423d8c037d32c52561f5068ff17f93f2e50414 (patch)
tree13819e412e992b3f78a87809853e21c408f3b8b2
parentb90723bccbe6a58bdfa7e8ba0e25922eada9e295 (diff)
downloadmpv-01423d8c037d32c52561f5068ff17f93f2e50414.tar.bz2
mpv-01423d8c037d32c52561f5068ff17f93f2e50414.tar.xz
demux, demux_mkv: fix seeking in cache with large codec delay
In this scenario, the demuxer will output timestamps offset by the codec delay (e.g. negative timestamps at the start; mkv simulates those), and the trimming in the decoder (often libavcodec, but ad_lavc.c in our case) will adjust the timestamps back (e.g. stream actually starts at 0). This offset needs to be taken into account when seeking. This worked in the uncached case. (demux_mkv.c is a bit tricky in that the index is already in the offset space, so it compensates even though the seek call does not reference codec_delay.) But in the cached case, seeks backwards did not seek enough, and forward they seeked too much. Fix this by adding the codec delay to the index search. We need to get "earlier" packets, so e.g. seeking to position 0 really gets the initial packets with negative timestamps. This also adjusts the seek range start. This is also pretty obvious: if the beginning of the file is cached, the seek range should start at 0, not a negative value. We compare 0-based timestamps to it later on. Not sure if this is the best approach. I also could have thought about/checked some corner cases harder. But fuck this shit. Not fixing duration (who cares) or end trimming, which would reduce the seek range and duration (who cares).
-rw-r--r--demux/demux.c7
-rw-r--r--demux/demux_mkv.c2
-rw-r--r--demux/stheader.h2
3 files changed, 10 insertions, 1 deletions
diff --git a/demux/demux.c b/demux/demux.c
index 019a8469c7..967b0b176f 100644
--- a/demux/demux.c
+++ b/demux/demux.c
@@ -1687,8 +1687,11 @@ static void adjust_seek_range_on_packet(struct demux_stream *ds,
if (queue->keyframe_latest) {
queue->keyframe_latest->kf_seek_pts = queue->keyframe_pts;
double old_end = queue->range->seek_end;
- if (queue->seek_start == MP_NOPTS_VALUE)
+ if (queue->seek_start == MP_NOPTS_VALUE) {
queue->seek_start = queue->keyframe_pts;
+ if (queue->seek_start != MP_NOPTS_VALUE)
+ queue->seek_start += ds->sh->seek_preroll;
+ }
if (queue->keyframe_end_pts != MP_NOPTS_VALUE)
queue->seek_end = queue->keyframe_end_pts;
queue->is_eof = !dp;
@@ -2982,6 +2985,8 @@ static void switch_current_range(struct demux_internal *in,
static struct demux_packet *find_seek_target(struct demux_queue *queue,
double pts, int flags)
{
+ pts -= queue->ds->sh->seek_preroll;
+
struct demux_packet *start = queue->head;
for (int n = 0; n < queue->num_index; n++) {
if (queue->index[n]->kf_seek_pts > pts)
diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c
index 67eb9c7af6..24279f7267 100644
--- a/demux/demux_mkv.c
+++ b/demux/demux_mkv.c
@@ -1836,6 +1836,8 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track)
sh_a->extradata = extradata;
sh_a->extradata_size = extradata_len;
+ sh->seek_preroll = track->codec_delay;
+
demux_add_sh_stream(demuxer, sh);
return 0;
diff --git a/demux/stheader.h b/demux/stheader.h
index beca0fabf7..198f16cd49 100644
--- a/demux/stheader.h
+++ b/demux/stheader.h
@@ -55,6 +55,8 @@ struct sh_stream {
bool missing_timestamps;
+ double seek_preroll;
+
// stream is a picture (such as album art)
struct demux_packet *attached_picture;