summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/input.rst1
-rw-r--r--DOCS/man/options.rst7
-rw-r--r--demux/demux_mkv.c65
-rw-r--r--options/options.c1
-rw-r--r--options/options.h1
5 files changed, 75 insertions, 0 deletions
diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst
index 68d48ae880..ea408d00ed 100644
--- a/DOCS/man/input.rst
+++ b/DOCS/man/input.rst
@@ -792,6 +792,7 @@ Property list
``ab-loop-a``, ``ab-loop-b`` (TW)
Set/get A-B loop points. See corresponding options and ``ab_loop`` command.
+ The special value ``no`` on either of these properties disables looping.
``angle`` (RW)
Current DVD angle.
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index b2ddd1c12a..aeb0cc63fe 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -2070,6 +2070,13 @@ Demuxer
``--demuxer-mkv-subtitle-preroll-secs=<value>``
See ``--demuxer-mkv-subtitle-preroll``.
+``--demuxer-mkv-probe-video-duration``
+ When opening the file, seek to the end of it, and check what timestamp the
+ last video packet has, and report that as file duration. This is strictly
+ for compatibility with Haali only. In this mode, it's possible that opening
+ will slower (especially when playing over http), or that behavior with
+ broken files is much worse. So don't use this option.
+
``--demuxer-rawaudio-channels=<value>``
Number of channels (or channel layout) if ``--demuxer=rawaudio`` is used
(default: stereo).
diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c
index 36ca0277ba..85287e5a80 100644
--- a/demux/demux_mkv.c
+++ b/demux/demux_mkv.c
@@ -199,6 +199,8 @@ typedef struct mkv_demuxer {
// (Subtitle packets added before first A/V keyframe packet is found with seek.)
#define NUM_SUB_PREROLL_PACKETS 500
+static void probe_last_timestamp(struct demuxer *demuxer);
+
#define AAC_SYNC_EXTENSION_TYPE 0x02b7
static int aac_get_sample_rate_index(uint32_t sample_rate)
{
@@ -1845,6 +1847,9 @@ static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check)
process_tags(demuxer);
display_create_tracks(demuxer);
+ if (demuxer->opts->mkv_probe_duration)
+ probe_last_timestamp(demuxer);
+
return 0;
}
@@ -2859,6 +2864,66 @@ static void demux_mkv_seek(demuxer_t *demuxer, double rel_seek_secs, int flags)
demux_mkv_fill_buffer(demuxer);
}
+static void probe_last_timestamp(struct demuxer *demuxer)
+{
+ mkv_demuxer_t *mkv_d = demuxer->priv;
+ int64_t old_pos = stream_tell(demuxer->stream);
+
+ if (!demuxer->seekable)
+ return;
+
+ // Pick some arbitrary video track
+ int v_tnum = -1;
+ for (int n = 0; n < mkv_d->num_tracks; n++) {
+ if (mkv_d->tracks[n]->type == MATROSKA_TRACK_VIDEO) {
+ v_tnum = mkv_d->tracks[n]->tnum;
+ break;
+ }
+ }
+ if (v_tnum < 0)
+ return;
+
+ read_deferred_cues(demuxer);
+
+ if (!mkv_d->index_complete)
+ return;
+
+ // Find last cluster that still has video packets
+ int64_t target = 0;
+ for (size_t i = 0; i < mkv_d->num_indexes; i++) {
+ struct mkv_index *cur = &mkv_d->indexes[i];
+ if (cur->tnum == v_tnum)
+ target = MPMAX(target, cur->filepos);
+ }
+ if (!target)
+ return;
+
+ if (!stream_seek(demuxer->stream, target))
+ return;
+
+ int64_t last_ts[STREAM_TYPE_COUNT] = {0};
+ while (1) {
+ struct block_info block;
+ int res = read_next_block(demuxer, &block);
+ if (res < 0)
+ break;
+ if (res > 0) {
+ if (block.track && block.track->stream) {
+ enum stream_type type = block.track->stream->type;
+ if (last_ts[type] < block.timecode)
+ last_ts[type] = block.timecode;
+ }
+ free_block(&block);
+ }
+ }
+
+ if (last_ts[STREAM_VIDEO])
+ mkv_d->duration = last_ts[STREAM_VIDEO] / 1e9;
+
+ stream_seek(demuxer->stream, old_pos);
+ mkv_d->cluster_start = mkv_d->cluster_end = 0;
+}
+
static int demux_mkv_control(demuxer_t *demuxer, int cmd, void *arg)
{
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv;
diff --git a/options/options.c b/options/options.c
index 93b660b0fd..1f6e0ae377 100644
--- a/options/options.c
+++ b/options/options.c
@@ -306,6 +306,7 @@ const m_option_t mp_opts[] = {
OPT_FLAG("mkv-subtitle-preroll", mkv_subtitle_preroll, 0), // old alias
OPT_DOUBLE("demuxer-mkv-subtitle-preroll-secs", mkv_subtitle_preroll_secs,
M_OPT_MIN, .min = 0),
+ OPT_FLAG("demuxer-mkv-probe-video-duration", mkv_probe_duration, 0),
// ------------------------- subtitles options --------------------
diff --git a/options/options.h b/options/options.h
index 63f77b2b3a..94d78ac6a0 100644
--- a/options/options.h
+++ b/options/options.h
@@ -196,6 +196,7 @@ typedef struct MPOpts {
char *sub_demuxer_name;
int mkv_subtitle_preroll;
double mkv_subtitle_preroll_secs;
+ int mkv_probe_duration;
double demuxer_min_secs_cache;
int cache_pausing;