From 90d7e51643273a14dfb9a4db622abb7da4e0aa5f Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 23 Apr 2015 19:35:15 +0200 Subject: demux_mkv: attempt to fix rounded timestamps There is some potential for breakage. If it happens, this might have to be disabled by default. --- DOCS/man/options.rst | 12 ++++++++++++ demux/demux_mkv.c | 19 ++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index ef914982a7..47f4c15152 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -2112,6 +2112,18 @@ Demuxer will be slower (especially when playing over http), or that behavior with broken files is much worse. So don't use this option. +``--demuxer-mkv-fix-timestamps=`` + Fix rounded Matroska timestamps (enabled by default). Matroska usually + stores timestamps rounded to milliseconds. This means timestamps jitter + by some amount around the intended timestamp. mpv can correct the timestamps + based on the framerate value stored in the file: if the timestamps does + not deviate more than 1 frame (as implied by the framerate), the timestamp + is rounded to the next frame, which should undo the rounding the muxer + did. + + This can break playback if the framerate value stored in the file is too + high. + ``--demuxer-rawaudio-channels=`` 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 4ae734cb5b..39b271e1b6 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -190,6 +191,7 @@ struct demux_mkv_opts { int subtitle_preroll; double subtitle_preroll_secs; int probe_duration; + int fix_timestamps; }; const struct m_sub_options demux_mkv_conf = { @@ -198,11 +200,13 @@ const struct m_sub_options demux_mkv_conf = { OPT_DOUBLE("subtitle-preroll-secs", subtitle_preroll_secs, M_OPT_MIN, .min = 0), OPT_FLAG("probe-video-duration", probe_duration, 0), + OPT_FLAG("fix-timestamps", fix_timestamps, 0), {0} }, .size = sizeof(struct demux_mkv_opts), .defaults = &(const struct demux_mkv_opts){ .subtitle_preroll_secs = 1.0, + .fix_timestamps = 1, }, }; @@ -2327,6 +2331,19 @@ exit: return res; } +static double fix_timestamp(demuxer_t *demuxer, mkv_track_t *track, double ts) +{ + mkv_demuxer_t *mkv_d = demuxer->priv; + if (demuxer->opts->demux_mkv->fix_timestamps && track->default_duration > 0) { + // Assume that timestamps have been rounded to the timecode scale. + double quant = mkv_d->tc_scale / 1e9; + double rts = rint(ts / track->default_duration) * track->default_duration; + if (fabs(rts - ts) < quant) + ts = rts; + } + return ts; +} + static int handle_block(demuxer_t *demuxer, struct block_info *block_info) { mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; @@ -2349,7 +2366,7 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info) return 0; } - current_pts = tc / 1e9 - track->codec_delay; + current_pts = fix_timestamp(demuxer, track, tc / 1e9) - track->codec_delay; if (track->type == MATROSKA_TRACK_AUDIO) { if (mkv_d->a_skip_to_keyframe) -- cgit v1.2.3