diff options
Diffstat (limited to 'libmpdemux/demux_mkv.c')
-rw-r--r-- | libmpdemux/demux_mkv.c | 513 |
1 files changed, 273 insertions, 240 deletions
diff --git a/libmpdemux/demux_mkv.c b/libmpdemux/demux_mkv.c index cb4d971755..4f44646b56 100644 --- a/libmpdemux/demux_mkv.c +++ b/libmpdemux/demux_mkv.c @@ -27,7 +27,10 @@ #include <stdio.h> #include <ctype.h> #include <inttypes.h> +#include <stdbool.h> +#include "talloc.h" +#include "options.h" #include "stream/stream.h" #include "demuxer.h" #include "stheader.h" @@ -70,13 +73,12 @@ static const unsigned char sipr_swaps[38][2]={ #define ATRC_FLAVORS 8 #define COOK_FLAVORS 34 static const int sipr_fl2bps[SIPR_FLAVORS] = {813, 1062, 625, 2000}; -static const int atrc_fl2bps[ATRC_FLAVORS] = - {8269, 11714, 13092, 16538, 18260, 22050, 33075, 44100}; -static const int cook_fl2bps[COOK_FLAVORS] = - { 1000, 1378, 2024, 2584, 4005, 5513, 8010, 4005, 750, 2498, - 4048, 5513, 8010, 11973, 8010, 2584, 4005, 2067, 2584, 2584, - 4005, 4005, 5513, 5513, 8010, 12059, 1550, 8010, 12059, 5513, - 12016, 16408, 22911, 33506}; +static const int atrc_fl2bps[ATRC_FLAVORS] = {8269, 11714, 13092, 16538, 18260, 22050, 33075, 44100}; +static const int cook_fl2bps[COOK_FLAVORS] = { + 1000, 1378, 2024, 2584, 4005, 5513, 8010, 4005, 750, 2498, + 4048, 5513, 8010, 11973, 8010, 2584, 4005, 2067, 2584, 2584, + 4005, 4005, 5513, 5513, 8010, 12059, 1550, 8010, 12059, 5513, + 12016, 16408, 22911, 33506}; typedef struct { @@ -108,7 +110,7 @@ typedef struct mkv_track int default_track; - void *private_data; + unsigned char *private_data; unsigned int private_size; /* stuff for realmedia */ @@ -166,8 +168,7 @@ typedef struct mkv_demuxer mkv_track_t **tracks; int num_tracks; - uint64_t tc_scale, cluster_tc, first_tc; - int has_first_tc; + uint64_t tc_scale, cluster_tc; uint64_t cluster_size; uint64_t blockgroup_size; @@ -186,8 +187,6 @@ typedef struct mkv_demuxer int64_t skip_to_timecode; int v_skip_to_keyframe, a_skip_to_keyframe; - int64_t stop_timecode; - int last_aid; int audio_tracks[MAX_A_STREAMS]; } mkv_demuxer_t; @@ -197,20 +196,16 @@ typedef struct mkv_demuxer #define RAPROPERTIES4_SIZE 56 #define RAPROPERTIES5_SIZE 70 -/* for e.g. "-slang ger" */ -extern char *dvdsub_lang; -extern char *audio_lang; -extern int dvdsub_id; - /** * \brief ensures there is space for at least one additional element * \param array array to grow * \param nelem current number of elements in array * \param elsize size of one array element */ -static void grow_array(void **array, int nelem, size_t elsize) { +static void *grow_array(void *array, int nelem, size_t elsize) { if (!(nelem & 31)) - *array = realloc(*array, (nelem + 32) * elsize); + array = realloc(array, (nelem + 32) * elsize); + return array; } static mkv_track_t * @@ -235,8 +230,9 @@ add_cluster_position (mkv_demuxer_t *mkv_d, uint64_t position) if (mkv_d->cluster_positions[i] == position) return; - grow_array(&mkv_d->cluster_positions, mkv_d->num_cluster_pos, - sizeof(uint64_t)); + mkv_d->cluster_positions = grow_array(mkv_d->cluster_positions, + mkv_d->num_cluster_pos, + sizeof(uint64_t)); mkv_d->cluster_positions[mkv_d->num_cluster_pos++] = position; } @@ -326,8 +322,8 @@ demux_mkv_decode (mkv_track_t *track, uint8_t *src, uint8_t **dest, zstream.opaque = (voidpf) 0; if (inflateInit (&zstream) != Z_OK) { - mp_msg (MSGT_DEMUX, MSGL_WARN, - MSGTR_MPDEMUX_MKV_ZlibInitializationFailed); + mp_tmsg (MSGT_DEMUX, MSGL_WARN, + "[mkv] zlib initialization failed.\n"); return modified; } zstream.next_in = (Bytef *) src; @@ -343,8 +339,8 @@ demux_mkv_decode (mkv_track_t *track, uint8_t *src, uint8_t **dest, result = inflate (&zstream, Z_NO_FLUSH); if (result != Z_OK && result != Z_STREAM_END) { - mp_msg (MSGT_DEMUX, MSGL_WARN, - MSGTR_MPDEMUX_MKV_ZlibDecompressionFailed); + mp_tmsg (MSGT_DEMUX, MSGL_WARN, + "[mkv] zlib decompression failed.\n"); free(*dest); *dest = NULL; inflateEnd (&zstream); @@ -375,8 +371,8 @@ demux_mkv_decode (mkv_track_t *track, uint8_t *src, uint8_t **dest, if (!(result & AV_LZO_OUTPUT_FULL)) { lzo_fail: - mp_msg (MSGT_DEMUX, MSGL_WARN, - MSGTR_MPDEMUX_MKV_LzoDecompressionFailed); + mp_tmsg (MSGT_DEMUX, MSGL_WARN, + "[mkv] lzo decompression failed.\n"); free(*dest); *dest = NULL; return modified; @@ -393,52 +389,67 @@ lzo_fail: } -static int -demux_mkv_read_info (demuxer_t *demuxer) +static int demux_mkv_read_info(demuxer_t *demuxer) { - mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; - stream_t *s = demuxer->stream; - uint64_t length, l; - int il; - uint64_t tc_scale = 1000000; - long double duration = 0.; - - length = ebml_read_length (s, NULL); - while (length > 0) - { - switch (ebml_read_id (s, &il)) - { + mkv_demuxer_t *mkv_d = demuxer->priv; + stream_t *s = demuxer->stream; + uint64_t length, l; + int i; + uint64_t tc_scale = 1000000; + long double duration = 0.; + + length = ebml_read_length(s, NULL); + while (length > 0) { + uint32_t id = ebml_read_id(s, &i); + length -= i; + switch (id) { case MATROSKA_ID_TIMECODESCALE: - { - uint64_t num = ebml_read_uint (s, &l); - if (num == EBML_UINT_INVALID) - return 1; - tc_scale = num; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + timecode scale: %"PRIu64"\n", + tc_scale = ebml_read_uint(s, &l); + length -= l; + if (tc_scale == EBML_UINT_INVALID) + return 1; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + timecode scale: %"PRIu64"\n", tc_scale); break; - } case MATROSKA_ID_DURATION: - { - long double num = ebml_read_float (s, &l); - if (num == EBML_FLOAT_INVALID) - return 1; - duration = num; - mp_msg (MSGT_DEMUX, MSGL_V, "[mkv] | + duration: %.3Lfs\n", - duration * tc_scale / 1000000000.0); + duration = ebml_read_float(s, &l); + length -= l; + if (duration == EBML_FLOAT_INVALID) + return 1; + break; + + case MATROSKA_ID_SEGMENTUID:; + l = ebml_read_length(s, &i); + length -= i; + if (l != sizeof(demuxer->matroska_data.segment_uid)) { + mp_msg(MSGT_DEMUX, MSGL_INFO, + "[mkv] segment uid invalid length %"PRIu64"\n", l); + stream_skip(s, l); + } else { + stream_read(s, demuxer->matroska_data.segment_uid, l); + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + segment uid"); + for (int i = 0; i < l; i++) + mp_msg(MSGT_DEMUX, MSGL_V, " %02x", + demuxer->matroska_data.segment_uid[i]); + mp_msg(MSGT_DEMUX, MSGL_V, "\n"); + } + length -= l; break; - } default: - ebml_read_skip (s, &l); - break; + ebml_read_skip(s, &l); + length -= l; + break; } - length -= l + il; } - mkv_d->tc_scale = tc_scale; - mkv_d->duration = duration * tc_scale / 1000000000.0; - return 0; + mkv_d->tc_scale = tc_scale; + mkv_d->duration = duration * tc_scale / 1000000000.0; + if (duration) + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + duration: %.3fs\n", + mkv_d->duration); + + return 0; } /** @@ -548,26 +559,26 @@ demux_mkv_read_trackencodings (demuxer_t *demuxer, mkv_track_t *track) if (e.type == 1) { - mp_msg(MSGT_DEMUX, MSGL_WARN, - MSGTR_MPDEMUX_MKV_TrackEncrypted, track->tnum); + mp_tmsg(MSGT_DEMUX, MSGL_WARN, + "[mkv] Track number %u has been encrypted and decryption has not yet been\n[mkv] implemented. Skipping track.\n", track->tnum); } else if (e.type != 0) { - mp_msg(MSGT_DEMUX, MSGL_WARN, - MSGTR_MPDEMUX_MKV_UnknownContentEncoding, track->tnum); + mp_tmsg(MSGT_DEMUX, MSGL_WARN, + "[mkv] Unknown content encoding type for track %u. Skipping track.\n", track->tnum); } if (e.comp_algo != 0 && e.comp_algo != 2) { - mp_msg (MSGT_DEMUX, MSGL_WARN, - MSGTR_MPDEMUX_MKV_UnknownCompression, + mp_tmsg (MSGT_DEMUX, MSGL_WARN, + "[mkv] Track %u has been compressed with an unknown/unsupported compression\n[mkv] algorithm (%u). Skipping track.\n", track->tnum, e.comp_algo); } #if !CONFIG_ZLIB else if (e.comp_algo == 0) { - mp_msg (MSGT_DEMUX, MSGL_WARN, - MSGTR_MPDEMUX_MKV_ZlibCompressionUnsupported, + mp_tmsg (MSGT_DEMUX, MSGL_WARN, + "[mkv] Track %u was compressed with zlib but mplayer has not been compiled\n[mkv] with support for zlib compression. Skipping track.\n", track->tnum); } #endif @@ -1079,7 +1090,8 @@ demux_mkv_read_cues (demuxer_t *demuxer) if (time != EBML_UINT_INVALID && track != EBML_UINT_INVALID && pos != EBML_UINT_INVALID) { - grow_array(&mkv_d->indexes, mkv_d->num_indexes, sizeof(mkv_index_t)); + mkv_d->indexes = grow_array(mkv_d->indexes, mkv_d->num_indexes, + sizeof(mkv_index_t)); mkv_d->indexes[mkv_d->num_indexes].tnum = track; mkv_d->indexes[mkv_d->num_indexes].timecode = time; mkv_d->indexes[mkv_d->num_indexes].filepos =mkv_d->segment_start+pos; @@ -1094,140 +1106,175 @@ demux_mkv_read_cues (demuxer_t *demuxer) return 0; } -static int -demux_mkv_read_chapters (demuxer_t *demuxer) +static uint64_t read_one_chapter(struct demuxer *demuxer, stream_t *s) { - stream_t *s = demuxer->stream; - uint64_t length, l; - int il; - - if (demuxer->chapters) - { - ebml_read_skip (s, NULL); - return 0; - } - - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] /---- [ parsing chapters ] ---------\n"); - length = ebml_read_length (s, NULL); - - while (length > 0) - { - switch (ebml_read_id (s, &il)) - { - case MATROSKA_ID_EDITIONENTRY: - { - uint64_t len; - int i; - - len = ebml_read_length (s, &i); - l = len + i; + uint64_t len, l; + uint64_t start = 0, end = 0; + struct matroska_chapter chapter = {}; + char *name = 0; + int i; + uint32_t id; + + len = ebml_read_length(s, &i); + uint64_t bytes_read = len + i; + + while (len > 0) { + id = ebml_read_id(s, &i); + len -= i; + switch (id) { + case MATROSKA_ID_CHAPTERTIMESTART: + start = ebml_read_uint(s, &l) / 1000000; + len -= l; + break; - while (len > 0) - { - uint64_t l; - int il; + case MATROSKA_ID_CHAPTERTIMEEND: + end = ebml_read_uint(s, &l) / 1000000; + len -= l; + break; - switch (ebml_read_id (s, &il)) - { - case MATROSKA_ID_CHAPTERATOM: - { - uint64_t len, start=0, end=0; - char* name = 0; - int i; - int cid; + case MATROSKA_ID_CHAPTERDISPLAY:; + uint64_t displaylen = ebml_read_length(s, &i); + len -= displaylen + i; + while (displaylen > 0) { + id = ebml_read_id(s, &i); + displaylen -= i; + switch (id) { + case MATROSKA_ID_CHAPSTRING: + name = ebml_read_utf8(s, &l); + break; + default: + ebml_read_skip(s, &l); + break; + } + displaylen -= l; + } + break; - len = ebml_read_length (s, &i); - l = len + i; + case MATROSKA_ID_CHAPTERSEGMENTUID: + l = ebml_read_length(s, &i); + len -= l + i; + if (l != sizeof(chapter.segment_uid)) { + mp_msg(MSGT_DEMUX, MSGL_INFO, + "[mkv] chapter segment uid invalid length %"PRIu64"\n", + l); + stream_skip(s, l); + } else { + stream_read(s, chapter.segment_uid, l); + chapter.has_segment_uid = true; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Chapter segment uid "); + for (int i = 0; i < l; i++) + mp_msg(MSGT_DEMUX, MSGL_V, "%02x ", chapter.segment_uid[i]); + mp_msg(MSGT_DEMUX, MSGL_V, "\n"); + } + break; - while (len > 0) - { - uint64_t l; - int il; + default: + ebml_read_skip(s, &l); + len -= l; + break; + } + } - switch (ebml_read_id (s, &il)) - { - case MATROSKA_ID_CHAPTERTIMESTART: - start = ebml_read_uint (s, &l) / 1000000; - break; + if (!name) + name = strdup("(unnamed)"); + + int cid = demuxer_add_chapter(demuxer, name, start, end); + struct matroska_data *m = &demuxer->matroska_data; + m->ordered_chapters = talloc_realloc(demuxer, m->ordered_chapters, + struct matroska_chapter, + m->num_ordered_chapters + 1); + chapter.start = start; + chapter.end = end; + chapter.name = talloc_strdup(m->ordered_chapters, name); + // Will be undone later if this is a normal chapter rather than ordered + m->ordered_chapters[m->num_ordered_chapters] = chapter; + m->num_ordered_chapters++; + + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Chapter %u from %02d:%02d:%02d." + "%03d to %02d:%02d:%02d.%03d, %s\n", + cid, + (int) (start / 60 / 60 / 1000), + (int) ((start / 60 / 1000) % 60), + (int) ((start / 1000) % 60), + (int) (start % 1000), + (int) (end / 60 / 60 / 1000), + (int) ((end / 60 / 1000) % 60), + (int) ((end / 1000) % 60), + (int) (end % 1000), name); + + free(name); + return bytes_read; +} - case MATROSKA_ID_CHAPTERTIMEEND: - end = ebml_read_uint (s, &l) / 1000000; - break; +static int demux_mkv_read_chapters(struct demuxer *demuxer) +{ + stream_t *s = demuxer->stream; + uint64_t length, l; + int i; + uint32_t id; - case MATROSKA_ID_CHAPTERDISPLAY: - { - uint64_t len; - int i; - - len = ebml_read_length (s, &i); - l = len + i; - while (len > 0) - { - uint64_t l; - int il; - - switch (ebml_read_id (s, &il)) - { - case MATROSKA_ID_CHAPSTRING: - name = ebml_read_utf8 (s, &l); - break; - default: - ebml_read_skip (s, &l); - break; - } - len -= l + il; - } - } - break; + if (demuxer->chapters) { + ebml_read_skip(s, NULL); + return 0; + } - default: - ebml_read_skip (s, &l); - break; - } - len -= l + il; - } + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] /---- [ parsing chapters ] ---------\n"); + length = ebml_read_length(s, NULL); - if (!name) - name = strdup("(unnamed)"); - - cid = demuxer_add_chapter(demuxer, name, start, end); - - mp_msg(MSGT_DEMUX, MSGL_V, - "[mkv] Chapter %u from %02d:%02d:%02d." - "%03d to %02d:%02d:%02d.%03d, %s\n", - cid, - (int) (start / 60 / 60 / 1000), - (int) ((start / 60 / 1000) % 60), - (int) ((start / 1000) % 60), - (int) (start % 1000), - (int) (end / 60 / 60 / 1000), - (int) ((end / 60 / 1000) % 60), - (int) ((end / 1000) % 60), - (int) (end % 1000), name); - - free(name); - break; - } + bool have_edition = false; + while (length > 0) { + id = ebml_read_id(s, &i); + length -= i; + switch (id) { + case MATROSKA_ID_EDITIONENTRY: + if (have_edition) { + mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] Multiple edition entries" + " - ignoring all but first!\n"); + ebml_read_skip(s, &l); + length -= l; + break; + } + have_edition = true; + uint64_t editionlen = ebml_read_length(s, &i); + length -= editionlen + i; + bool ordered = false; + while (editionlen > 0) { + id = ebml_read_id(s, &i); + editionlen -= i; + switch (id) { + case MATROSKA_ID_CHAPTERATOM: + l = read_one_chapter(demuxer, s); + break; + case MATROSKA_ID_EDITIONFLAGORDERED: + ordered = ebml_read_uint(s, &l); + mp_msg(MSGT_DEMUX, MSGL_V, + "[mkv] Ordered chapter flag: %d\n", ordered); + break; - default: - ebml_read_skip (s, &l); + default: + ebml_read_skip(s, &l); break; - } - len -= l + il; - } + } + editionlen -= l; + } + if (!ordered) { + // The chapters should be interpreted as normal ones, + // so undo the addition of this information. + talloc_free(demuxer->matroska_data.ordered_chapters); + demuxer->matroska_data.ordered_chapters = NULL; + demuxer->matroska_data.num_ordered_chapters = 0; + } break; - } default: - ebml_read_skip (s, &l); - break; + ebml_read_skip(s, &l); + length -= l; + break; } - - length -= l + il; } - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] \\---- [ parsing chapters ] ---------\n"); - return 0; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] \\---- [ parsing chapters ] ---------\n"); + return 0; } static int @@ -1501,10 +1548,10 @@ display_create_tracks (demuxer_t *demuxer) break; } if (mkv_d->tracks[i]->name) - mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_MPDEMUX_MKV_TrackIDName, + mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[mkv] Track ID %u: %s (%s) \"%s\", %s\n", mkv_d->tracks[i]->tnum, type, mkv_d->tracks[i]->codec_id, mkv_d->tracks[i]->name, str); else - mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_MPDEMUX_MKV_TrackID, + mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[mkv] Track ID %u: %s (%s), %s\n", mkv_d->tracks[i]->tnum, type, mkv_d->tracks[i]->codec_id, str); } } @@ -1529,6 +1576,7 @@ static const videocodec_info_t vinfo[] = { static int demux_mkv_open_video (demuxer_t *demuxer, mkv_track_t *track, int vid) { + struct MPOpts *opts = demuxer->opts; BITMAPINFOHEADER *bih; void *ImageDesc = NULL; sh_video_t *sh_v; @@ -1639,9 +1687,9 @@ demux_mkv_open_video (demuxer_t *demuxer, mkv_track_t *track, int vid) bih = realloc (bih, bih->biSize); memcpy (bih + 1, track->private_data, track->private_size); } - track->reorder_timecodes = user_correct_pts == 0; + track->reorder_timecodes = opts->user_correct_pts == 0; if (!vi->id) { - mp_msg (MSGT_DEMUX,MSGL_WARN, MSGTR_MPDEMUX_MKV_UnknownCodecID, + mp_tmsg (MSGT_DEMUX,MSGL_WARN, "[mkv] Unknown/unsupported CodecID (%s) or missing/bad CodecPrivate\n[mkv] data (track %u).\n", track->codec_id, track->tnum); free(bih); return 1; @@ -1755,8 +1803,8 @@ demux_mkv_open_audio (demuxer_t *demuxer, mkv_track_t *track, int aid) { if (track->private_data == NULL || track->private_size == 0) { - mp_msg (MSGT_DEMUX, MSGL_WARN, - MSGTR_MPDEMUX_MKV_FlacTrackDoesNotContainValidHeaders); + mp_tmsg (MSGT_DEMUX, MSGL_WARN, + "[mkv] FLAC track does not contain valid headers.\n"); return 1; } track->a_formattag = mmioFOURCC ('f', 'L', 'a', 'C'); @@ -1776,7 +1824,7 @@ demux_mkv_open_audio (demuxer_t *demuxer, mkv_track_t *track, int aid) } else { - mp_msg (MSGT_DEMUX, MSGL_WARN, MSGTR_MPDEMUX_MKV_UnknownAudioCodec, + mp_tmsg (MSGT_DEMUX, MSGL_WARN, "[mkv] Unknown/unsupported audio codec ID '%s' for track %u or missing/faulty\n[mkv] private codec data.\n", track->codec_id, track->tnum); free_sh_audio(demuxer, track->tnum); return 1; @@ -1965,13 +2013,13 @@ demux_mkv_open_audio (demuxer_t *demuxer, mkv_track_t *track, int aid) if (track->a_formattag == mmioFOURCC('f', 'L', 'a', 'C')) { - ptr = (unsigned char *)track->private_data; + ptr = track->private_data; size = track->private_size; } else { sh_a->format = mmioFOURCC('f', 'L', 'a', 'C'); - ptr = (unsigned char *) track->private_data + ptr = track->private_data + sizeof (WAVEFORMATEX); size = track->private_size - sizeof (WAVEFORMATEX); } @@ -2033,7 +2081,7 @@ demux_mkv_open_sub (demuxer_t *demuxer, mkv_track_t *track, int sid) } else { - mp_msg (MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_MKV_SubtitleTypeNotSupported, + mp_tmsg (MSGT_DEMUX, MSGL_ERR, "[mkv] Subtitle type '%s' is not supported.\n", track->codec_id); return 1; } @@ -2041,8 +2089,6 @@ demux_mkv_open_sub (demuxer_t *demuxer, mkv_track_t *track, int sid) return 0; } -static void demux_mkv_seek (demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags); - static int demux_mkv_open (demuxer_t *demuxer) { @@ -2132,8 +2178,6 @@ demux_mkv_open (demuxer_t *demuxer) uint64_t num = ebml_read_uint (s, NULL); if (num == EBML_UINT_INVALID) return 0; - mkv_d->first_tc = num * mkv_d->tc_scale / 1000000.0; - mkv_d->has_first_tc = 1; } stream_seek (s, p - 4); cont = 1; @@ -2179,14 +2223,14 @@ demux_mkv_open (demuxer_t *demuxer) if (track && demuxer->v_streams[track->tnum]) { - mp_msg (MSGT_DEMUX, MSGL_INFO, - MSGTR_MPDEMUX_MKV_WillPlayVideoTrack, track->tnum); + mp_tmsg (MSGT_DEMUX, MSGL_INFO, + "[mkv] Will play video track %u.\n", track->tnum); demuxer->video->id = track->tnum; demuxer->video->sh = demuxer->v_streams[track->tnum]; } else { - mp_msg (MSGT_DEMUX, MSGL_INFO, MSGTR_MPDEMUX_MKV_NoVideoTrackFound); + mp_tmsg (MSGT_DEMUX, MSGL_INFO, "[mkv] No video track found/wanted.\n"); demuxer->video->id = -2; } @@ -2219,7 +2263,7 @@ demux_mkv_open (demuxer_t *demuxer) } else { - mp_msg (MSGT_DEMUX, MSGL_INFO, MSGTR_MPDEMUX_MKV_NoAudioTrackFound); + mp_tmsg (MSGT_DEMUX, MSGL_INFO, "[mkv] No audio track found/wanted.\n"); demuxer->audio->id = -2; } @@ -2237,22 +2281,6 @@ demux_mkv_open (demuxer_t *demuxer) } } - if (demuxer->chapters) - { - for (i=0; i < (int)demuxer->num_chapters; i++) - { - demuxer->chapters[i].start -= mkv_d->first_tc; - demuxer->chapters[i].end -= mkv_d->first_tc; - } - if (dvd_last_chapter > 0 && dvd_last_chapter <= demuxer->num_chapters) - { - if (demuxer->chapters[dvd_last_chapter-1].end != 0) - mkv_d->stop_timecode = demuxer->chapters[dvd_last_chapter-1].end; - else if (dvd_last_chapter + 1 <= demuxer->num_chapters) - mkv_d->stop_timecode = demuxer->chapters[dvd_last_chapter].start; - } - } - if (s->end_pos == 0 || (mkv_d->indexes == NULL && index_mode < 0)) demuxer->seekable = 0; else @@ -2262,6 +2290,8 @@ demux_mkv_open (demuxer_t *demuxer) demuxer->seekable = 1; } + demuxer->accurate_seek = true; + return DEMUXER_TYPE_MATROSKA; } @@ -2383,7 +2413,7 @@ handle_subtitles(demuxer_t *demuxer, mkv_track_t *track, char *block, if (block_duration == 0) { mp_msg (MSGT_DEMUX, MSGL_WARN, - MSGTR_MPDEMUX_MKV_NoBlockDurationForSubtitleTrackFound); + "[mkv] Warning: No BlockDuration for subtitle track found.\n"); return; } @@ -2640,13 +2670,9 @@ handle_block (demuxer_t *demuxer, uint8_t *block, uint64_t length, return 0; block += old_length - length; - tc = ((time*mkv_d->tc_scale+mkv_d->cluster_tc) /1000000.0 - mkv_d->first_tc); + tc = ((time*mkv_d->tc_scale+mkv_d->cluster_tc) /1000000.0); if (tc < 0) tc = 0; - if (mkv_d->stop_timecode > 0 && tc > mkv_d->stop_timecode) { - free(lace_size); - return -1; - } current_pts = tc / 1000.0; for (i=0; i<mkv_d->num_tracks; i++) @@ -2869,11 +2895,6 @@ demux_mkv_fill_buffer (demuxer_t *demuxer, demux_stream_t *ds) uint64_t num = ebml_read_uint (s, &l); if (num == EBML_UINT_INVALID) return 0; - if (!mkv_d->has_first_tc) - { - mkv_d->first_tc = num * mkv_d->tc_scale / 1000000.0; - mkv_d->has_first_tc = 1; - } mkv_d->cluster_tc = num * mkv_d->tc_scale; break; } @@ -2929,6 +2950,16 @@ demux_mkv_fill_buffer (demuxer_t *demuxer, demux_stream_t *ds) static void demux_mkv_seek (demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int flags) { + if (!(flags & (SEEK_BACKWARD | SEEK_FORWARD))) { + if (flags & SEEK_ABSOLUTE || rel_seek_secs < 0) + flags |= SEEK_BACKWARD; + else + flags |= SEEK_FORWARD; + } + // 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.001 : 0.001; + free_cached_dps (demuxer); if (!(flags & SEEK_FACTOR)) /* time in secs */ { @@ -2983,12 +3014,12 @@ demux_mkv_seek (demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int for (i=0; i < mkv_d->num_cluster_pos; i++) { diff = mkv_d->cluster_positions[i] - target_filepos; - if (rel_seek_secs < 0 && diff < 0 && -diff < min_diff) + if (flags & SEEK_BACKWARD && diff < 0 && -diff < min_diff) { cluster_pos = mkv_d->cluster_positions[i]; min_diff = -diff; } - else if (rel_seek_secs > 0 + else if (flags & SEEK_FORWARD && (diff < 0 ? -1 * diff : diff) < min_diff) { cluster_pos = mkv_d->cluster_positions[i]; @@ -3009,17 +3040,17 @@ demux_mkv_seek (demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int for (i=0; i < mkv_d->num_indexes; i++) if (mkv_d->indexes[i].tnum == seek_id) { - diff = target_timecode + mkv_d->first_tc - + diff = target_timecode - (int64_t) mkv_d->indexes[i].timecode * mkv_d->tc_scale / 1000000.0; - if ((flags & SEEK_ABSOLUTE || target_timecode <= mkv_d->last_pts*1000)) { - // Absolute seek or seek backward: find the last index - // position before target time + if (flags & SEEK_BACKWARD) { + // Seek backward: find the last index position + // before target time if (diff < 0 || diff >= min_diff) continue; } else { - // Relative seek forward: find the first index position + // Seek forward: find the first index position // after target time. If no such index exists, find last // position between current position and target time. if (diff <= 0) { @@ -3043,8 +3074,10 @@ demux_mkv_seek (demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int if (demuxer->video->id >= 0) mkv_d->v_skip_to_keyframe = 1; - if (rel_seek_secs > 0.0) + if (flags & SEEK_FORWARD) mkv_d->skip_to_timecode = target_timecode; + else + mkv_d->skip_to_timecode = 0; mkv_d->a_skip_to_keyframe = 1; demux_mkv_fill_buffer(demuxer, NULL); |