mirror of https://github.com/mpv-player/mpv
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).
This commit is contained in:
parent
b90723bccb
commit
01423d8c03
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue