diff options
Diffstat (limited to 'libmpdemux/demux_mkv.c')
-rw-r--r-- | libmpdemux/demux_mkv.c | 559 |
1 files changed, 296 insertions, 263 deletions
diff --git a/libmpdemux/demux_mkv.c b/libmpdemux/demux_mkv.c index 627ac7cd44..27e564578e 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" @@ -41,8 +44,7 @@ #include "subreader.h" #include "libvo/sub.h" -#include "libass/ass.h" -#include "libass/ass_mp.h" +#include "ass_mp.h" #include "libavutil/common.h" @@ -55,7 +57,7 @@ #endif #include "libavutil/lzo.h" -#include "libavutil/intreadwrite.h" +#include "ffmpeg_files/intreadwrite.h" #include "libavutil/avstring.h" static const unsigned char sipr_swaps[38][2]={ @@ -70,13 +72,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 { @@ -98,25 +99,25 @@ typedef struct mkv_track int type; uint32_t v_width, v_height, v_dwidth, v_dheight; - float v_frate; + double v_frate; uint32_t a_formattag; uint32_t a_channels, a_bps; float a_sfreq; - float default_duration; + double default_duration; int default_track; - void *private_data; + unsigned char *private_data; unsigned int private_size; /* stuff for realmedia */ int realmedia; int64_t rv_kf_base; int rv_kf_pts; - float rv_pts; /* previous video timestamp */ - float ra_pts; /* previous audio timestamp */ + double rv_pts; /* previous video timestamp */ + double ra_pts; /* previous audio timestamp */ /** realaudio descrambling */ int sub_packet_size; ///< sub packet size, per stream @@ -124,13 +125,13 @@ typedef struct mkv_track int coded_framesize; ///< coded frame size, per stream int audiopk_size; ///< audio packet size unsigned char *audio_buf; ///< place to store reordered audio data - float *audio_timestamp; ///< timestamp for each audio packet + double *audio_timestamp; ///< timestamp for each audio packet int sub_packet_cnt; ///< number of subpacket already received int audio_filepos; ///< file position of first audio packet in block /* stuff for quicktime */ int fix_i_bps; - float qt_last_a_pts; + double qt_last_a_pts; int subtitle_type; @@ -140,7 +141,7 @@ typedef struct mkv_track int reorder_timecodes; demux_packet_t **cached_dps; int num_cached_dps, num_allocated_dps; - float max_pts; + double max_pts; /* generic content encoding support */ mkv_content_encoding_t *encodings; @@ -160,14 +161,13 @@ typedef struct mkv_demuxer { off_t segment_start; - float duration, last_pts; + double duration, last_pts; uint64_t last_filepos; 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 +186,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 +195,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 +229,9 @@ add_cluster_position (mkv_demuxer_t *mkv_d, uint64_t position) if (mkv_d->cluster_positions[i] == position) return; - grow_array((void **)&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 +321,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 +338,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 +370,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 +388,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 +558,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 +1089,8 @@ demux_mkv_read_cues (demuxer_t *demuxer) if (time != EBML_UINT_INVALID && track != EBML_UINT_INVALID && pos != EBML_UINT_INVALID) { - grow_array((void **)&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 +1105,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 +1547,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 +1575,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 +1686,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; @@ -1662,7 +1709,7 @@ demux_mkv_open_video (demuxer_t *demuxer, mkv_track_t *track, int vid) sh_v->disp_w = track->v_width; sh_v->disp_h = track->v_height; if (track->v_dheight) - sh_v->aspect = (float)track->v_dwidth / (float)track->v_dheight; + sh_v->aspect = (double)track->v_dwidth / track->v_dheight; } else { @@ -1757,8 +1804,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'); @@ -1778,7 +1825,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; @@ -1882,7 +1929,7 @@ demux_mkv_open_audio (demuxer_t *demuxer, mkv_track_t *track, int aid) else { sh_a->codecdata_len = 2; - track->default_duration = 1024.0 / (float)sh_a->samplerate; + track->default_duration = 1024.0 / sh_a->samplerate; } } else if (track->a_formattag == mmioFOURCC('v', 'r', 'b', 's')) /* VORBIS */ @@ -1933,25 +1980,25 @@ demux_mkv_open_audio (demuxer_t *demuxer, mkv_track_t *track, int aid) sh_a->wf->nAvgBytesPerSec = atrc_fl2bps[flavor]; sh_a->wf->nBlockAlign = track->sub_packet_size; track->audio_buf = malloc(track->sub_packet_h * track->audiopk_size); - track->audio_timestamp = malloc(track->sub_packet_h * sizeof(float)); + track->audio_timestamp = malloc(track->sub_packet_h * sizeof(double)); break; case mmioFOURCC('c', 'o', 'o', 'k'): sh_a->wf->nAvgBytesPerSec = cook_fl2bps[flavor]; sh_a->wf->nBlockAlign = track->sub_packet_size; track->audio_buf = malloc(track->sub_packet_h * track->audiopk_size); - track->audio_timestamp = malloc(track->sub_packet_h * sizeof(float)); + track->audio_timestamp = malloc(track->sub_packet_h * sizeof(double)); break; case mmioFOURCC('s', 'i', 'p', 'r'): sh_a->wf->nAvgBytesPerSec = sipr_fl2bps[flavor]; sh_a->wf->nBlockAlign = track->coded_framesize; track->audio_buf = malloc(track->sub_packet_h * track->audiopk_size); - track->audio_timestamp = malloc(track->sub_packet_h * sizeof(float)); + track->audio_timestamp = malloc(track->sub_packet_h * sizeof(double)); break; case mmioFOURCC('2', '8', '_', '8'): sh_a->wf->nAvgBytesPerSec = 3600; sh_a->wf->nBlockAlign = track->coded_framesize; track->audio_buf = malloc(track->sub_packet_h * track->audiopk_size); - track->audio_timestamp = malloc(track->sub_packet_h * sizeof(float)); + track->audio_timestamp = malloc(track->sub_packet_h * sizeof(double)); break; } @@ -1967,13 +2014,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); } @@ -2036,7 +2083,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; } @@ -2044,8 +2091,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) { @@ -2135,8 +2180,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; @@ -2182,14 +2225,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; } @@ -2222,7 +2265,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; } @@ -2240,22 +2283,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 @@ -2265,6 +2292,8 @@ demux_mkv_open (demuxer_t *demuxer) demuxer->seekable = 1; } + demuxer->accurate_seek = true; + return DEMUXER_TYPE_MATROSKA; } @@ -2386,15 +2415,15 @@ 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; } sub_utf8 = 1; dp = new_demux_packet(size); memcpy(dp->buffer, block, size); - dp->pts = timecode / 1000.0f; - dp->endpts = (timecode + block_duration) / 1000.0f; + dp->pts = timecode / 1000.0; + dp->endpts = (timecode + block_duration) / 1000.0; ds_add_packet(demuxer->sub, dp); } @@ -2553,7 +2582,7 @@ flush_cached_dps (demuxer_t *demuxer, mkv_track_t *track) ok = 1; for (i = 1; i < track->num_cached_dps; i++) if (track->cached_dps[i - 1]->pts > track->cached_dps[i]->pts) { - float tmp_pts = track->cached_dps[i - 1]->pts; + double tmp_pts = track->cached_dps[i - 1]->pts; track->cached_dps[i - 1]->pts = track->cached_dps[i]->pts; track->cached_dps[i]->pts = tmp_pts; ok = 0; @@ -2627,7 +2656,7 @@ handle_block (demuxer_t *demuxer, uint8_t *block, uint64_t length, uint32_t *lace_size; uint8_t laces, flags; int i, num, tmp, use_this_block = 1; - float current_pts; + double current_pts; int16_t time; /* first byte(s): track num */ @@ -2643,13 +2672,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 + 0.5; 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++) @@ -2872,11 +2897,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; } @@ -2932,9 +2952,20 @@ 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.005 : 0.005; + free_cached_dps (demuxer); if (!(flags & SEEK_FACTOR)) /* time in secs */ { + mkv_index_t *index = NULL; mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; stream_t *s = demuxer->stream; int64_t target_timecode = 0, diff, min_diff=0xFFFFFFFFFFFFFFFLL; @@ -2986,12 +3017,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 |