From a18aa9e6321058f96f2a4a26df19abd73567e360 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 27 Jan 2016 21:08:53 +0100 Subject: demux_mkv: allow negative timestamps FFmpeg can generate such files. It's unclear whether they're allowed by Matroska. mkvinfo shows packet timestamps in both forms (one of them must be a bug), and at last libavformat's demuxer treats timestamps as signed. --- demux/demux_mkv.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'demux/demux_mkv.c') diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 024f7e7e6e..9e8346e6ac 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -146,14 +146,14 @@ typedef struct mkv_track { typedef struct mkv_index { int tnum; - uint64_t timecode, duration; + int64_t timecode, duration; uint64_t filepos; // position of the cluster which contains the packet } mkv_index_t; struct block_info { uint64_t duration, discardpadding; bool simple, keyframe; - uint64_t timecode; + int64_t timecode; mkv_track_t *track; bstr data; void *alloc; @@ -170,7 +170,7 @@ typedef struct mkv_demuxer { struct ebml_tags *tags; - uint64_t tc_scale, cluster_tc; + int64_t tc_scale, cluster_tc; uint64_t cluster_start; uint64_t cluster_end; @@ -186,7 +186,7 @@ typedef struct mkv_demuxer { } *headers; int num_headers; - uint64_t skip_to_timecode; + int64_t skip_to_timecode; int v_skip_to_keyframe, a_skip_to_keyframe; int a_skip_preroll; int subtitle_preroll; @@ -706,7 +706,7 @@ static int demux_mkv_read_tracks(demuxer_t *demuxer) } static void cue_index_add(demuxer_t *demuxer, int track_id, uint64_t filepos, - uint64_t timecode, uint64_t duration) + int64_t timecode, int64_t duration) { mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; @@ -724,7 +724,7 @@ static void cue_index_add(demuxer_t *demuxer, int track_id, uint64_t filepos, static void add_block_position(demuxer_t *demuxer, struct mkv_track *track, uint64_t filepos, - uint64_t timecode, uint64_t duration) + int64_t timecode, int64_t duration) { mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; @@ -788,8 +788,8 @@ static int demux_mkv_read_cues(demuxer_t *demuxer) time, trackpos->cue_duration); mkv_d->index_has_durations |= trackpos->n_cue_duration > 0; MP_DBG(demuxer, "|+ found cue point for track %" PRIu64 - ": timecode %" PRIu64 ", filepos: %" PRIu64 - " offset %" PRIu64 ", duration %" PRIu64 "\n", + ": timecode %" PRId64 ", filepos: %" PRIu64 + " offset %" PRIu64 ", duration %" PRId64 "\n", trackpos->cue_track, time, pos, trackpos->cue_relative_position, trackpos->cue_duration); } @@ -1854,6 +1854,7 @@ static int demux_mkv_open(demuxer_t *demuxer, enum demux_check check) mkv_d->segment_start = stream_tell(s); mkv_d->segment_end = end_pos; mkv_d->a_skip_preroll = 1; + mkv_d->skip_to_timecode = INT64_MIN; if (demuxer->params && demuxer->params->matroska_was_valid) *demuxer->params->matroska_was_valid = true; @@ -2128,6 +2129,8 @@ static void mkv_seek_reset(demuxer_t *demuxer) } free_block(&mkv_d->tmp_block); + + mkv_d->skip_to_timecode = INT64_MIN; } // Copied from libavformat/matroskadec.c (FFmpeg 310f9dd / 2013-05-30) @@ -2379,7 +2382,7 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info) bstr data = block_info->data; bool keyframe = block_info->keyframe; uint64_t block_duration = block_info->duration; - uint64_t tc = block_info->timecode; + int64_t tc = block_info->timecode; mkv_track_t *track = block_info->track; struct sh_stream *stream = track->stream; uint32_t lace_size[MAX_NUM_LACES]; @@ -2466,7 +2469,7 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info) if (stream->type == STREAM_VIDEO) { mkv_d->v_skip_to_keyframe = 0; - mkv_d->skip_to_timecode = 0; + mkv_d->skip_to_timecode = INT64_MIN; mkv_d->subtitle_preroll = 0; } else if (stream->type == STREAM_AUDIO) { mkv_d->a_skip_to_keyframe = 0; @@ -2658,7 +2661,7 @@ static mkv_index_t *get_highest_index_entry(struct demuxer *demuxer) return index; } -static int create_index_until(struct demuxer *demuxer, uint64_t timecode) +static int create_index_until(struct demuxer *demuxer, int64_t timecode) { struct mkv_demuxer *mkv_d = demuxer->priv; struct stream *s = demuxer->stream; @@ -2672,7 +2675,7 @@ static int create_index_until(struct demuxer *demuxer, uint64_t timecode) if (!index || index->timecode * mkv_d->tc_scale < timecode) { stream_seek(s, index ? index->filepos : mkv_d->cluster_start); - MP_VERBOSE(demuxer, "creating index until TC %" PRIu64 "\n", timecode); + MP_VERBOSE(demuxer, "creating index until TC %" PRId64 "\n", timecode); for (;;) { int res; struct block_info block; @@ -2708,8 +2711,7 @@ static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id, for (size_t i = 0; i < mkv_d->num_indexes; i++) { if (seek_id < 0 || mkv_d->indexes[i].tnum == seek_id) { int64_t diff = - target_timecode - - (int64_t) (mkv_d->indexes[i].timecode * mkv_d->tc_scale); + target_timecode - mkv_d->indexes[i].timecode * mkv_d->tc_scale; if (flags & FLAG_BACKWARD) diff = -diff; if (min_diff != INT64_MIN) { @@ -2732,10 +2734,10 @@ static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id, double secs = opts->demux_mkv->subtitle_preroll_secs; if (mkv_d->index_has_durations) secs = MPMAX(secs, opts->demux_mkv->subtitle_preroll_secs_index); - uint64_t pre = MPMIN(INT64_MAX, secs * 1e9 / mkv_d->tc_scale); - uint64_t min_tc = pre < index->timecode ? index->timecode - pre : 0; + int64_t pre = MPMIN(INT64_MAX, secs * 1e9 / mkv_d->tc_scale); + int64_t min_tc = pre < index->timecode ? index->timecode - pre : 0; uint64_t prev_target = 0; - uint64_t prev_tc = 0; + int64_t prev_tc = 0; for (size_t i = 0; i < mkv_d->num_indexes; i++) { if (seek_id < 0 || mkv_d->indexes[i].tnum == seek_id) { struct mkv_index *cur = &mkv_d->indexes[i]; @@ -2826,7 +2828,7 @@ static void demux_mkv_seek(demuxer_t *demuxer, double rel_seek_secs, int flags) mkv_d->skip_to_timecode = target_timecode; } else { mkv_d->skip_to_timecode = index ? index->timecode * mkv_d->tc_scale - : 0; + : INT64_MIN; } } else { stream_t *s = demuxer->stream; -- cgit v1.2.3 From fa821de8b2b11c0c5e378342e0d56d16366cd96f Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 14 Feb 2016 12:42:24 +0100 Subject: demux_mkv: support channel layout in VfW muxed PCM Fixes #2820. --- demux/demux_mkv.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'demux/demux_mkv.c') diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 9e8346e6ac..4eb4df260f 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -1484,6 +1484,7 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track) unsigned char *extradata = track->private_data; unsigned int extradata_len = track->private_size; + uint64_t chmask = 0; if (!track->a_osfreq) track->a_osfreq = track->a_sfreq; @@ -1516,6 +1517,9 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track) extradata_len = track->private_size - 18; sh_a->bits_per_coded_sample = track->a_bps; mp_set_codec_from_tag(sh_a); + // WAVEFORMATEXTENSIBLE.dwChannelMask + if (sh_a->codec_tag == 0xfffe && extradata_len >= 6) + chmask = AV_RL32(extradata + 2); } else if (!strcmp(track->codec_id, "A_PCM/INT/LIT")) { bool sign = sh_a->bits_per_coded_sample > 8; mp_set_pcm_codec(sh_a, sign, false, sh_a->bits_per_coded_sample, false); @@ -1635,7 +1639,9 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track) if (!sh_a->codec) goto error; - mp_chmap_set_unknown(&sh_a->channels, track->a_channels); + mp_chmap_from_waveext(&sh_a->channels, chmask); + if (sh_a->channels.num != track->a_channels) + mp_chmap_set_unknown(&sh_a->channels, track->a_channels); const char *codec = sh_a->codec; if (!strcmp(codec, "mp3") || !strcmp(codec, "truehd")) { -- cgit v1.2.3 From 943f76e6ce979ce1e1e7e29e4e20f8ec56682df7 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 21 Feb 2016 16:25:02 +0100 Subject: demux_mkv: add hack to fix opus gapless behavior I think the conclusion is that AV_PKT_DATA_SKIP_SAMPLES is misdesigned (at least for some formats), and an alternative mechanism using durations would be better. (Combining it with a proper timebase would keep sample-accuracy.) --- demux/demux_mkv.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'demux/demux_mkv.c') diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 4eb4df260f..761985c204 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -1679,6 +1679,12 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track) AV_WL32(data + 10, track->a_osfreq); // Bogus: last frame won't be played. AV_WL32(data + 14, 0); + } else if (strcmp(codec, "opus")) { + // Hardcode the rate libavcodec's opus decoder outputs, so that + // AV_PKT_DATA_SKIP_SAMPLES actually works. The Matroska header only + // has an arbitrary "input" samplerate, while libavcodec is fixed to + // output 48000. + sh_a->samplerate = 48000; } // Some files have broken default DefaultDuration set, which will lead to -- cgit v1.2.3 From f3549ff76a082b480fbeef11a5d33d61fe75c4cd Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 22 Feb 2016 20:46:28 +0100 Subject: demux_mkv: fix opus gapless behavior (2) Commit 943f76e6, which already tried this, was very stupid: it didn't actually override the samplerate for Opus, but overrode it for all codecs other than Opus. And even then, it failed to use the overridden samplerate. (Sigh...) --- demux/demux_mkv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'demux/demux_mkv.c') diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 761985c204..e99d8a2c63 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -1679,7 +1679,7 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track) AV_WL32(data + 10, track->a_osfreq); // Bogus: last frame won't be played. AV_WL32(data + 14, 0); - } else if (strcmp(codec, "opus")) { + } else if (!strcmp(codec, "opus")) { // Hardcode the rate libavcodec's opus decoder outputs, so that // AV_PKT_DATA_SKIP_SAMPLES actually works. The Matroska header only // has an arbitrary "input" samplerate, while libavcodec is fixed to @@ -2467,7 +2467,7 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info) if (i == 0) dp->duration = block_duration / 1e9; if (stream->type == STREAM_AUDIO) { - unsigned int srate = track->a_sfreq; + unsigned int srate = stream->codec->samplerate; demux_packet_set_padding(dp, mkv_d->a_skip_preroll ? track->codec_delay * srate : 0, block_info->discardpadding / 1e9 * srate); -- cgit v1.2.3 From 503c6f7fd6c3c542667c93c75db260671c4ba982 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 24 Feb 2016 21:48:24 +0100 Subject: demux_mkv: don't trust DefaultDuration for audio It's used to interpolate timestamps for sub-packets ("block laces"). It's occasionally broken, and not really needed by us. --- demux/demux_mkv.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'demux/demux_mkv.c') diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index e99d8a2c63..7b5efd8219 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -1687,11 +1687,9 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track) sh_a->samplerate = 48000; } - // Some files have broken default DefaultDuration set, which will lead to - // audio packets with incorrect timestamps. This follows FFmpeg commit - // 6158a3b, sample see FFmpeg ticket 2508. - if (sh_a->samplerate == 8000 && strcmp(codec, "ac3") == 0) - track->default_duration = 0; + // This field tends to be broken, and our decoder can interpolate the + // missing timestamps anyway. + track->default_duration = 0; sh_a->extradata = extradata; sh_a->extradata_size = extradata_len; -- cgit v1.2.3 From 92ba63079617f6579c276dd3ec54197b56378913 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 28 Feb 2016 19:14:23 +0100 Subject: demux: remove relative seeking Ever since a change in mplayer2 or so, relative seeks were translated to absolute seeks before sending them to the demuxer in most cases. The only exception in current mpv is DVD seeking. Remove the SEEK_ABSOLUTE flag; it's not the implied default. SEEK_FACTOR is kept, because it's sometimes slightly useful for seeking in things like transport streams. (And maybe mkv files without duration set?) DVD seeking is terrible because DVD and libdvdnav are terrible, but mostly because libdvdnav is terrible. libdvdnav does not expose seeking with seek tables. (Although I know xbmc/kodi use an undocumented API that is not declared in the headers by dladdr()ing it - I think the function is dvdnav_jump_to_sector_by_time().) With the current mpv policy if not giving a shit about DVD, just revert our half-working seek hacks and always use dvdnav_time_search(). Relative seeking might get stuck sometimes; in this case --hr-seek=always is recommended. --- demux/demux_mkv.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'demux/demux_mkv.c') diff --git a/demux/demux_mkv.c b/demux/demux_mkv.c index 7b5efd8219..c932b45f39 100644 --- a/demux/demux_mkv.c +++ b/demux/demux_mkv.c @@ -163,7 +163,7 @@ struct block_info { typedef struct mkv_demuxer { int64_t segment_start, segment_end; - double duration, last_pts; + double duration; mkv_track_t **tracks; int num_tracks; @@ -2441,7 +2441,6 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info) if (use_this_block) { uint64_t filepos = block_info->filepos; - mkv_d->last_pts = current_pts; for (int i = 0; i < laces; i++) { bstr block = bstr_splice(data, 0, lace_size[i]); @@ -2459,7 +2458,7 @@ static int handle_block(demuxer_t *demuxer, struct block_info *block_info) * values being the same). Also, don't use it for extra * packets resulting from parsing. */ if (i == 0 || track->default_duration) - dp->pts = mkv_d->last_pts + i * track->default_duration; + dp->pts = current_pts + i * track->default_duration; if (stream->codec->avi_dts) MPSWAP(double, dp->pts, dp->dts); if (i == 0) @@ -2784,7 +2783,7 @@ static struct mkv_index *seek_with_cues(struct demuxer *demuxer, int seek_id, return index; } -static void demux_mkv_seek(demuxer_t *demuxer, double rel_seek_secs, int flags) +static void demux_mkv_seek(demuxer_t *demuxer, double seek_pts, int flags) { mkv_demuxer_t *mkv_d = demuxer->priv; int64_t old_pos = stream_tell(demuxer->stream); @@ -2814,15 +2813,13 @@ static void demux_mkv_seek(demuxer_t *demuxer, double rel_seek_secs, int flags) // Adjust the target a little bit to catch cases where the target position // specifies a keyframe with high, but not perfect, precision. - rel_seek_secs += flags & SEEK_FORWARD ? -0.005 : 0.005; + seek_pts += flags & SEEK_FORWARD ? -0.005 : 0.005; if (!(flags & SEEK_FACTOR)) { /* time in secs */ mkv_index_t *index = NULL; - if (!(flags & SEEK_ABSOLUTE)) /* relative seek */ - rel_seek_secs += mkv_d->last_pts; - rel_seek_secs = FFMAX(rel_seek_secs, 0); - int64_t target_timecode = rel_seek_secs * 1e9 + 0.5; + seek_pts = FFMAX(seek_pts, 0); + int64_t target_timecode = seek_pts * 1e9 + 0.5; if (create_index_until(demuxer, target_timecode) >= 0) { int seek_id = st_active[STREAM_VIDEO] ? v_tnum : a_tnum; @@ -2846,7 +2843,7 @@ static void demux_mkv_seek(demuxer_t *demuxer, double rel_seek_secs, int flags) read_deferred_cues(demuxer); int64_t size = stream_get_size(s); - int64_t target_filepos = size * MPCLAMP(rel_seek_secs, 0, 1); + int64_t target_filepos = size * MPCLAMP(seek_pts, 0, 1); mkv_index_t *index = NULL; if (mkv_d->index_complete) { -- cgit v1.2.3