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.c45
1 files changed, 42 insertions, 3 deletions
diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c
index 14300b2d96..3d8efaf211 100644
--- a/demux/demux_mkv.c
+++ b/demux/demux_mkv.c
@@ -166,6 +166,7 @@ typedef struct mkv_demuxer {
mkv_index_t *indexes;
int num_indexes;
bool index_complete;
+ uint64_t deferred_cues;
int64_t *parsed_pos;
int num_parsed_pos;
@@ -721,6 +722,9 @@ static int demux_mkv_read_cues(demuxer_t *demuxer)
struct ebml_parse_ctx parse_ctx = {};
if (ebml_read_element(s, &parse_ctx, &cues, &ebml_cues_desc) < 0)
return -1;
+
+ mkv_d->num_indexes = 0;
+
for (int i = 0; i < cues.n_cue_point; i++) {
struct ebml_cue_point *cuepoint = &cues.cue_point[i];
if (cuepoint->n_cue_time != 1 || !cuepoint->n_cue_track_positions) {
@@ -748,6 +752,26 @@ static int demux_mkv_read_cues(demuxer_t *demuxer)
return 0;
}
+static void read_deferred_cues(demuxer_t *demuxer)
+{
+ mkv_demuxer_t *mkv_d = demuxer->priv;
+ stream_t *s = demuxer->stream;
+
+ if (mkv_d->deferred_cues) {
+ int64_t pos = mkv_d->deferred_cues;
+ mkv_d->deferred_cues = 0;
+ if (!stream_seek(s, pos)) {
+ mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] Failed to seek to cues\n");
+ return;
+ }
+ if (ebml_read_id(s, NULL) != MATROSKA_ID_CUES) {
+ mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] Expected element not found\n");
+ return;
+ }
+ demux_mkv_read_cues(demuxer);
+ }
+}
+
static int demux_mkv_read_chapters(struct demuxer *demuxer)
{
struct MPOpts *opts = demuxer->opts;
@@ -1019,9 +1043,13 @@ static int read_header_element(struct demuxer *demuxer, uint32_t id,
case MATROSKA_ID_CUES:
if (mkv_d->parsed_cues)
break;
- if (at_filepos && !seek_pos_id(s, at_filepos, id))
- return -1;
+ if (at_filepos) {
+ // Read cues when they are needed, to avoid seeking on opening.
+ mkv_d->deferred_cues = at_filepos;
+ return 1;
+ }
mkv_d->parsed_cues = true;
+ mkv_d->deferred_cues = 0;
return demux_mkv_read_cues(demuxer);
case MATROSKA_ID_TAGS:
@@ -2364,6 +2392,8 @@ static int create_index_until(struct demuxer *demuxer, uint64_t timecode)
struct mkv_demuxer *mkv_d = demuxer->priv;
struct stream *s = demuxer->stream;
+ read_deferred_cues(demuxer);
+
if (mkv_d->index_complete)
return 0;
@@ -2462,6 +2492,7 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs,
float audio_delay, int flags)
{
mkv_demuxer_t *mkv_d = demuxer->priv;
+ int64_t old_pos = stream_tell(demuxer->stream);
uint64_t v_tnum = -1;
uint64_t a_tnum = -1;
bool st_active[STREAM_TYPE_COUNT] = {0};
@@ -2501,6 +2532,9 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs,
index = seek_with_cues(demuxer, -1, target_timecode, flags);
}
+ if (!index)
+ stream_seek(demuxer->stream, old_pos);
+
if (st_active[STREAM_VIDEO])
mkv_d->v_skip_to_keyframe = 1;
if (flags & SEEK_FORWARD)
@@ -2519,8 +2553,11 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs,
mkv_index_t *index = NULL;
int i;
+ read_deferred_cues(demuxer);
+
if (!mkv_d->index_complete) { /* not implemented without index */
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] seek unsupported flags\n");
+ stream_seek(s, old_pos);
return;
}
@@ -2533,8 +2570,10 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs,
|| (mkv_d->indexes[i].filepos < index->filepos))))
index = &mkv_d->indexes[i];
- if (!index)
+ if (!index) {
+ stream_seek(s, old_pos);
return;
+ }
mkv_d->cluster_end = 0;
stream_seek(s, index->filepos);