summaryrefslogtreecommitdiffstats
path: root/demux/demux_mkv.c
diff options
context:
space:
mode:
Diffstat (limited to 'demux/demux_mkv.c')
-rw-r--r--demux/demux_mkv.c36
1 files changed, 30 insertions, 6 deletions
diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c
index 8fd4f42798..3e7958b827 100644
--- a/demux/demux_mkv.c
+++ b/demux/demux_mkv.c
@@ -194,6 +194,7 @@ typedef struct mkv_demuxer {
struct header_elem {
int32_t id;
int64_t pos;
+ bool needed;
bool parsed;
} *headers;
int num_headers;
@@ -1970,6 +1971,7 @@ static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check)
// Read headers that come after the first cluster (i.e. require seeking).
// Note: reading might increase ->num_headers.
// Likewise, ->headers might be reallocated.
+ int only_cue = -1;
for (int n = 0; n < mkv_d->num_headers; n++) {
struct header_elem *elem = &mkv_d->headers[n];
if (elem->parsed)
@@ -1984,14 +1986,36 @@ static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check)
}
continue;
}
- if (elem->id == MATROSKA_ID_CUES) {
- // Read cues when they are needed, to avoid seeking on opening.
- MP_VERBOSE(demuxer, "Deferring reading cues.\n");
- continue;
+ elem->needed = true;
+ only_cue = only_cue < 0 && elem->id == MATROSKA_ID_CUES;
+ }
+
+ // If there's only 1 needed element, and it's the cues, defer reading.
+ if (only_cue == 1) {
+ // Read cues when they are needed, to avoid seeking on opening.
+ MP_VERBOSE(demuxer, "Deferring reading cues.\n");
+ } else {
+ // Read them by ascending position to reduce unneeded seeks.
+ // O(n^2) because the number of elements is very low.
+ while (1) {
+ struct header_elem *lowest = NULL;
+ for (int n = 0; n < mkv_d->num_headers; n++) {
+ struct header_elem *elem = &mkv_d->headers[n];
+ if (!elem->needed)
+ continue;
+ if (!lowest || elem->pos < lowest->pos)
+ lowest = elem;
+ }
+
+ if (!lowest)
+ break;
+
+ lowest->needed = false;
+ if (read_deferred_element(demuxer, lowest) < 0)
+ return -1;
}
- if (read_deferred_element(demuxer, elem) < 0)
- return -1;
}
+
if (!stream_seek(s, start_pos)) {
MP_ERR(demuxer, "Couldn't seek back after reading headers?\n");
return -1;