mirror of
https://github.com/mpv-player/mpv
synced 2025-04-01 00:07:33 +00:00
demux_mkv: seek: with no track-specific index entries use any
The Cue entries in typical Matroska files have information for the video track only. This caused seeks to fail when playing with -novideo, as demux_mkv tried to use audio track index entries then. Add a fallback case that uses any index entries without caring what track they're for if there are no entries specific to the track we're interested in.
This commit is contained in:
parent
0619b75cb1
commit
fc66c94360
@ -2496,6 +2496,49 @@ static int seek_creating_index(struct demuxer *demuxer, float rel_seek_secs,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id,
|
||||||
|
int64_t target_timecode, int flags)
|
||||||
|
{
|
||||||
|
struct mkv_demuxer *mkv_d = demuxer->priv;
|
||||||
|
int64_t min_diff = 0xFFFFFFFFFFFFFFF;
|
||||||
|
struct mkv_index *index = NULL;
|
||||||
|
|
||||||
|
/* let's find the entry in the indexes with the smallest */
|
||||||
|
/* difference to the wanted timecode. */
|
||||||
|
for (int i = 0; i < mkv_d->num_indexes; i++)
|
||||||
|
if (seek_id < 0 || mkv_d->indexes[i].tnum == seek_id) {
|
||||||
|
uint64_t diff =
|
||||||
|
target_timecode -
|
||||||
|
(int64_t) (mkv_d->indexes[i].timecode *
|
||||||
|
mkv_d->tc_scale / 1000000.0 + 0.5);
|
||||||
|
|
||||||
|
if (flags & SEEK_BACKWARD) {
|
||||||
|
// Seek backward: find the last index position
|
||||||
|
// before target time
|
||||||
|
if (diff < 0 || diff >= min_diff)
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
// Seek forward: find the first index position
|
||||||
|
// after target time. If no such index exists, find last
|
||||||
|
// position between current position and target time.
|
||||||
|
if (diff <= 0) {
|
||||||
|
if (min_diff <= 0 && diff <= min_diff)
|
||||||
|
continue;
|
||||||
|
} else if (diff >=
|
||||||
|
FFMIN(target_timecode - mkv_d->last_pts, min_diff))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
min_diff = diff;
|
||||||
|
index = mkv_d->indexes + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index) { /* We've found an entry. */
|
||||||
|
mkv_d->cluster_size = mkv_d->blockgroup_size = 0;
|
||||||
|
stream_seek(demuxer->stream, index->filepos);
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs,
|
static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs,
|
||||||
float audio_delay, int flags)
|
float audio_delay, int flags)
|
||||||
{
|
{
|
||||||
@ -2521,9 +2564,6 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs,
|
|||||||
free_cached_dps(demuxer);
|
free_cached_dps(demuxer);
|
||||||
if (!(flags & SEEK_FACTOR)) { /* time in secs */
|
if (!(flags & SEEK_FACTOR)) { /* time in secs */
|
||||||
mkv_index_t *index = NULL;
|
mkv_index_t *index = NULL;
|
||||||
stream_t *s = demuxer->stream;
|
|
||||||
int64_t diff, min_diff = 0xFFFFFFFFFFFFFFF;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!(flags & SEEK_ABSOLUTE)) /* relative seek */
|
if (!(flags & SEEK_ABSOLUTE)) /* relative seek */
|
||||||
rel_seek_secs += mkv_d->last_pts;
|
rel_seek_secs += mkv_d->last_pts;
|
||||||
@ -2537,41 +2577,9 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs,
|
|||||||
} else {
|
} else {
|
||||||
int seek_id = (demuxer->video->id < 0) ?
|
int seek_id = (demuxer->video->id < 0) ?
|
||||||
a_tnum : v_tnum;
|
a_tnum : v_tnum;
|
||||||
|
index = seek_with_cues(demuxer, seek_id, target_timecode, flags);
|
||||||
/* let's find the entry in the indexes with the smallest */
|
if (!index)
|
||||||
/* difference to the wanted timecode. */
|
index = seek_with_cues(demuxer, -1, target_timecode, flags);
|
||||||
for (i = 0; i < mkv_d->num_indexes; i++)
|
|
||||||
if (mkv_d->indexes[i].tnum == seek_id) {
|
|
||||||
diff =
|
|
||||||
target_timecode -
|
|
||||||
(int64_t) (mkv_d->indexes[i].timecode *
|
|
||||||
mkv_d->tc_scale / 1000000.0 + 0.5);
|
|
||||||
|
|
||||||
if (flags & SEEK_BACKWARD) {
|
|
||||||
// Seek backward: find the last index position
|
|
||||||
// before target time
|
|
||||||
if (diff < 0 || diff >= min_diff)
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
// Seek forward: find the first index position
|
|
||||||
// after target time. If no such index exists, find last
|
|
||||||
// position between current position and target time.
|
|
||||||
if (diff <= 0) {
|
|
||||||
if (min_diff <= 0 && diff <= min_diff)
|
|
||||||
continue;
|
|
||||||
} else if (diff >=
|
|
||||||
FFMIN(target_timecode - mkv_d->last_pts,
|
|
||||||
min_diff))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
min_diff = diff;
|
|
||||||
index = mkv_d->indexes + i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index) { /* We've found an entry. */
|
|
||||||
mkv_d->cluster_size = mkv_d->blockgroup_size = 0;
|
|
||||||
stream_seek(s, index->filepos);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (demuxer->video->id >= 0)
|
if (demuxer->video->id >= 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user