diff options
Diffstat (limited to 'demux/demux_mkv.c')
-rw-r--r-- | demux/demux_mkv.c | 45 |
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); |