diff options
author | Uoti Urpala <uau@glyph.nonexistent.invalid> | 2010-01-28 00:56:26 +0200 |
---|---|---|
committer | Uoti Urpala <uau@glyph.nonexistent.invalid> | 2010-01-28 00:56:26 +0200 |
commit | c710c5ee504530eeb7ef7c73f6665fdb291dd206 (patch) | |
tree | 7150c1cee52a18db270877ae384290274a129cd2 /libmpdemux | |
parent | d84685ce13c7b31689b257e44b780373c91f8d32 (diff) | |
parent | 55c50b3f9931095f7420ce6932329eceaf81d347 (diff) | |
download | mpv-c710c5ee504530eeb7ef7c73f6665fdb291dd206.tar.bz2 mpv-c710c5ee504530eeb7ef7c73f6665fdb291dd206.tar.xz |
Merge branch 'matroska'
Diffstat (limited to 'libmpdemux')
-rw-r--r-- | libmpdemux/demux_lavf.c | 6 | ||||
-rw-r--r-- | libmpdemux/demux_mkv.c | 1636 | ||||
-rw-r--r-- | libmpdemux/demuxer.c | 57 | ||||
-rw-r--r-- | libmpdemux/demuxer.h | 9 | ||||
-rw-r--r-- | libmpdemux/ebml.c | 440 | ||||
-rw-r--r-- | libmpdemux/ebml.h | 195 | ||||
-rw-r--r-- | libmpdemux/ebml_defs.c | 382 | ||||
-rw-r--r-- | libmpdemux/ebml_types.h | 433 |
8 files changed, 1886 insertions, 1272 deletions
diff --git a/libmpdemux/demux_lavf.c b/libmpdemux/demux_lavf.c index 622b87d45a..ad958889ed 100644 --- a/libmpdemux/demux_lavf.c +++ b/libmpdemux/demux_lavf.c @@ -408,8 +408,8 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i) { } case CODEC_TYPE_ATTACHMENT:{ if (st->codec->codec_id == CODEC_ID_TTF) - demuxer_add_attachment(demuxer, st->filename, - "application/x-truetype-font", + demuxer_add_attachment(demuxer, st->filename, INT_MAX, + "application/x-truetype-font", INT_MAX, codec->extradata, codec->extradata_size); break; } @@ -489,7 +489,7 @@ static demuxer_t* demux_open_lavf(demuxer_t *demuxer){ uint64_t start = av_rescale_q(c->start, c->time_base, (AVRational){1,1000}); uint64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,1000}); t = av_metadata_get(c->metadata, "title", NULL, 0); - demuxer_add_chapter(demuxer, t ? t->value : NULL, start, end); + demuxer_add_chapter(demuxer, t ? t->value : NULL, INT_MAX, start, end); } for(i=0; i<avfc->nb_streams; i++) diff --git a/libmpdemux/demux_mkv.c b/libmpdemux/demux_mkv.c index b4a17d036f..69bef825b4 100644 --- a/libmpdemux/demux_mkv.c +++ b/libmpdemux/demux_mkv.c @@ -82,9 +82,9 @@ static const int cook_fl2bps[COOK_FLAVORS] = { 12016, 16408, 22911, 33506 }; -typedef struct { - uint32_t order, type, scope; - uint32_t comp_algo; +typedef struct mkv_content_encoding { + uint64_t order, type, scope; + uint64_t comp_algo; uint8_t *comp_settings; int comp_settings_len; } mkv_content_encoding_t; @@ -175,10 +175,13 @@ typedef struct mkv_demuxer { mkv_index_t *indexes; int num_indexes; - off_t *parsed_cues; - int parsed_cues_num; - off_t *parsed_seekhead; - int parsed_seekhead_num; + off_t *parsed_pos; + int num_parsed_pos; + bool parsed_info; + bool parsed_tracks; + bool parsed_tags; + bool parsed_chapters; + bool parsed_attachments; struct cluster_pos { uint64_t filepos; @@ -211,6 +214,29 @@ static void *grow_array(void *array, int nelem, size_t elsize) return array; } +static bool is_parsed_header(struct mkv_demuxer *mkv_d, off_t pos) +{ + int low = 0; + int high = mkv_d->num_parsed_pos; + while (high > low + 1) { + int mid = high + low >> 1; + if (mkv_d->parsed_pos[mid] > pos) + high = mid; + else + low = mid; + } + if (mkv_d->num_parsed_pos && mkv_d->parsed_pos[low] == pos) + return true; + if (!(mkv_d->num_parsed_pos & 31)) + mkv_d->parsed_pos = talloc_realloc(mkv_d, mkv_d->parsed_pos, off_t, + mkv_d->num_parsed_pos + 32); + mkv_d->num_parsed_pos++; + for (int i = mkv_d->num_parsed_pos - 1; i > low; i--) + mkv_d->parsed_pos[i] = mkv_d->parsed_pos[i - 1]; + mkv_d->parsed_pos[low] = pos; + return false; +} + static mkv_track_t *demux_mkv_find_track_by_num(mkv_demuxer_t *d, int n, int type) { @@ -283,23 +309,29 @@ static void free_cached_dps(demuxer_t *demuxer) } } -static int demux_mkv_decode(mkv_track_t *track, uint8_t *src, - uint8_t **dest, uint32_t *size, uint32_t type) +static void demux_mkv_decode(mkv_track_t *track, uint8_t *src, + uint8_t **dest, uint32_t *size, uint32_t type) { - int i, result; - int modified = 0; + uint8_t *orig_src = src; *dest = src; - if (track->num_encodings <= 0) - return 0; - for (i = 0; i < track->num_encodings; i++) { - if (!(track->encodings[i].scope & type)) + for (int i = 0; i < track->num_encodings; i++) { + struct mkv_content_encoding *enc = track->encodings + i; + if (!(enc->scope & type)) continue; + if (src != *dest && src != orig_src) + free(src); + src = *dest; // output from last iteration is new source + + if (enc->comp_algo == 0) { #if CONFIG_ZLIB - if (track->encodings[i].comp_algo == 0) { /* zlib encoded track */ + + if (*size == 0) + continue; + z_stream zstream; zstream.zalloc = (alloc_func) 0; @@ -308,14 +340,14 @@ static int demux_mkv_decode(mkv_track_t *track, uint8_t *src, if (inflateInit(&zstream) != Z_OK) { mp_tmsg(MSGT_DEMUX, MSGL_WARN, "[mkv] zlib initialization failed.\n"); - return modified; + goto error; } zstream.next_in = (Bytef *) src; zstream.avail_in = *size; - modified = 1; *dest = NULL; zstream.avail_out = *size; + int result; do { *size += 4000; *dest = realloc(*dest, *size); @@ -327,7 +359,7 @@ static int demux_mkv_decode(mkv_track_t *track, uint8_t *src, free(*dest); *dest = NULL; inflateEnd(&zstream); - return modified; + goto error; } zstream.avail_out += 4000; } while (zstream.avail_out == 4000 && zstream.avail_in != 0 @@ -335,9 +367,8 @@ static int demux_mkv_decode(mkv_track_t *track, uint8_t *src, *size = zstream.total_out; inflateEnd(&zstream); - } #endif - if (track->encodings[i].comp_algo == 2) { + } else if (enc->comp_algo == 2) { /* lzo encoded track */ int dstlen = *size * 3; @@ -347,7 +378,7 @@ static int demux_mkv_decode(mkv_track_t *track, uint8_t *src, if (dstlen > SIZE_MAX - AV_LZO_OUTPUT_PADDING) goto lzo_fail; *dest = realloc(*dest, dstlen + AV_LZO_OUTPUT_PADDING); - result = av_lzo1x_decode(*dest, &dstlen, src, &srclen); + int result = av_lzo1x_decode(*dest, &dstlen, src, &srclen); if (result == 0) break; if (!(result & AV_LZO_OUTPUT_FULL)) { @@ -356,17 +387,24 @@ static int demux_mkv_decode(mkv_track_t *track, uint8_t *src, "[mkv] lzo decompression failed.\n"); free(*dest); *dest = NULL; - return modified; + goto error; } mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] lzo decompression buffer too small.\n"); dstlen *= 2; } *size = dstlen; + } else if (enc->comp_algo == 3) { + *dest = malloc(*size + enc->comp_settings_len); + memcpy(*dest, enc->comp_settings, enc->comp_settings_len); + memcpy(*dest + enc->comp_settings_len, src, *size); + *size += enc->comp_settings_len; } } - return modified; + error: + if (src != *dest && src != orig_src) + free(src); } @@ -374,341 +412,164 @@ static int demux_mkv_read_info(demuxer_t *demuxer) { 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: - 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: - 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; + mkv_d->tc_scale = 1000000; + mkv_d->duration = 0; - default: - ebml_read_skip(s, &l); - length -= l; - break; - } + struct ebml_info info = {}; + struct ebml_parse_ctx parse_ctx = {}; + if (ebml_read_element(s, &parse_ctx, &info, &ebml_info_desc) < 0) + return 1; + if (info.n_timecode_scale) { + mkv_d->tc_scale = info.timecode_scale; + mp_msg(MSGT_DEMUX, MSGL_V, + "[mkv] | + timecode scale: %" PRIu64 "\n", mkv_d->tc_scale); } - mkv_d->tc_scale = tc_scale; - mkv_d->duration = duration * tc_scale / 1000000000.0; - if (duration) + if (info.n_duration) { + mkv_d->duration = info.duration * mkv_d->tc_scale / 1e9; mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + duration: %.3fs\n", mkv_d->duration); - + } + if (info.n_segment_uid) { + int len = info.segment_uid.len; + if (len != sizeof(demuxer->matroska_data.segment_uid)) { + mp_msg(MSGT_DEMUX, MSGL_INFO, + "[mkv] segment uid invalid length %d\n", len); + } else { + memcpy(demuxer->matroska_data.segment_uid, info.segment_uid.start, + len); + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + segment uid"); + for (int i = 0; i < len; i++) + mp_msg(MSGT_DEMUX, MSGL_V, " %02x", + demuxer->matroska_data.segment_uid[i]); + mp_msg(MSGT_DEMUX, MSGL_V, "\n"); + } + } + talloc_free(parse_ctx.talloc_ctx); return 0; } -/** - * \brief free array of kv_content_encoding_t - * \param encodings pointer to array - * \param numencodings number of encodings in array - */ -static void demux_mkv_free_encodings(mkv_content_encoding_t *encodings, - int numencodings) -{ - while (numencodings-- > 0) - free(encodings[numencodings].comp_settings); - free(encodings); -} - -static int demux_mkv_read_trackencodings(demuxer_t *demuxer, - mkv_track_t *track) +static void parse_trackencodings(struct demuxer *demuxer, + struct mkv_track *track, + struct ebml_content_encodings *encodings) { - stream_t *s = demuxer->stream; - mkv_content_encoding_t *ce, e; - uint64_t len1, len2, length, l; - int i, il, n; - - ce = malloc(sizeof(*ce)); - n = 0; - - len1 = length = ebml_read_length(s, &il); - len1 += il; - while (length > 0) { - switch (ebml_read_id(s, &il)) { - case MATROSKA_ID_CONTENTENCODING: - memset(&e, 0, sizeof(e)); + // initial allocation to be a non-NULL context before realloc + mkv_content_encoding_t *ce = talloc_size(track, 1); + + for (int n_enc = 0; n_enc < encodings->n_content_encoding; n_enc++) { + struct ebml_content_encoding *enc = encodings->content_encoding + n_enc; + struct mkv_content_encoding e = {}; + e.order = enc->content_encoding_order; + if (enc->n_content_encoding_scope) + e.scope = enc->content_encoding_scope; + else e.scope = 1; - - len2 = ebml_read_length(s, &i); - l = len2 + i; - - while (len2 > 0) { - uint64_t num, l; - int il; - - switch (ebml_read_id(s, &il)) { - case MATROSKA_ID_CONTENTENCODINGORDER: - num = ebml_read_uint(s, &l); - if (num == EBML_UINT_INVALID) - goto err_out; - e.order = num; - break; - - case MATROSKA_ID_CONTENTENCODINGSCOPE: - num = ebml_read_uint(s, &l); - if (num == EBML_UINT_INVALID) - goto err_out; - e.scope = num; - break; - - case MATROSKA_ID_CONTENTENCODINGTYPE: - num = ebml_read_uint(s, &l); - if (num == EBML_UINT_INVALID) - goto err_out; - e.type = num; - break; - - case MATROSKA_ID_CONTENTCOMPRESSION:; - uint64_t le; - - le = ebml_read_length(s, &i); - l = le + i; - - while (le > 0) { - uint64_t l; - int il; - - switch (ebml_read_id(s, &il)) { - case MATROSKA_ID_CONTENTCOMPALGO: - num = ebml_read_uint(s, &l); - if (num == EBML_UINT_INVALID) - goto err_out; - e.comp_algo = num; - break; - - case MATROSKA_ID_CONTENTCOMPSETTINGS: - l = ebml_read_length(s, &i); - e.comp_settings = malloc(l); - stream_read(s, e.comp_settings, l); - e.comp_settings_len = l; - l += i; - break; - - default: - ebml_read_skip(s, &l); - break; - } - le -= l + il; - } - - if (e.type == 1) { - 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_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_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_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 - - break; - - default: - ebml_read_skip(s, &l); - break; - } - len2 -= l + il; + e.type = enc->content_encoding_type; + + if (enc->n_content_compression) { + struct ebml_content_compression *z = &enc->content_compression; + e.comp_algo = z->content_comp_algo; + if (z->n_content_comp_settings) { + int sz = z->content_comp_settings.len; + e.comp_settings = talloc_size(ce, sz); + memcpy(e.comp_settings, z->content_comp_settings.start, sz); + e.comp_settings_len = sz; } - for (i = 0; i < n; i++) - if (e.order <= ce[i].order) - break; - ce = realloc(ce, (n + 1) * sizeof(*ce)); - memmove(ce + i + 1, ce + i, (n - i) * sizeof(*ce)); - memcpy(ce + i, &e, sizeof(e)); - n++; - break; - - default: - ebml_read_skip(s, &l); - break; } - length -= l + il; + if (e.type == 1) { + 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_tmsg(MSGT_DEMUX, MSGL_WARN, + "[mkv] Unknown content encoding type for " + "track %u. Skipping track.\n", + track->tnum); + } else if (e.comp_algo != 0 && e.comp_algo != 2) { + mp_tmsg(MSGT_DEMUX, MSGL_WARN, + "[mkv] Track %u has been compressed with " + "an unknown/unsupported compression\n" + "[mkv] algorithm (%" PRIu64 "). Skipping track.\n", + track->tnum, e.comp_algo); + } +#if !CONFIG_ZLIB + else if (e.comp_algo == 0) { + 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 + int i; + for (i = 0; i < n_enc; i++) + if (e.order >= ce[i].order) + break; + ce = talloc_realloc_size(track, ce, (n_enc + 1) * sizeof(*ce)); + memmove(ce + i + 1, ce + i, (n_enc - i) * sizeof(*ce)); + memcpy(ce + i, &e, sizeof(e)); } track->encodings = ce; - track->num_encodings = n; - return len1; - - err_out: - demux_mkv_free_encodings(ce, n); - return 0; + track->num_encodings = encodings->n_content_encoding; } -static int demux_mkv_read_trackaudio(demuxer_t *demuxer, mkv_track_t *track) +static void parse_trackaudio(struct demuxer *demuxer, struct mkv_track *track, + struct ebml_audio *audio) { - stream_t *s = demuxer->stream; - uint64_t len, length, l; - uint64_t num; - long double fnum; - int il; - - track->a_sfreq = 8000.0; - track->a_channels = 1; - - len = length = ebml_read_length(s, &il); - len += il; - while (length > 0) { - switch (ebml_read_id(s, &il)) { - case MATROSKA_ID_AUDIOSAMPLINGFREQ: - fnum = ebml_read_float(s, &l); - if (fnum == EBML_FLOAT_INVALID) - return 0; - track->a_sfreq = fnum; - mp_msg(MSGT_DEMUX, MSGL_V, - "[mkv] | + Sampling frequency: %f\n", track->a_sfreq); - break; - - case MATROSKA_ID_AUDIOBITDEPTH: - num = ebml_read_uint(s, &l); - if (num == EBML_UINT_INVALID) - return 0; - track->a_bps = num; - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Bit depth: %u\n", - track->a_bps); - break; - - case MATROSKA_ID_AUDIOCHANNELS: - num = ebml_read_uint(s, &l); - if (num == EBML_UINT_INVALID) - return 0; - track->a_channels = num; - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Channels: %u\n", - track->a_channels); - break; - - default: - ebml_read_skip(s, &l); - break; - } - length -= l + il; + if (audio->n_sampling_frequency) { + track->a_sfreq = audio->sampling_frequency; + mp_msg(MSGT_DEMUX, MSGL_V, + "[mkv] | + Sampling frequency: %f\n", track->a_sfreq); + } else + track->a_sfreq = 8000; + if (audio->n_bit_depth) { + track->a_bps = audio->bit_depth; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Bit depth: %u\n", + track->a_bps); } - return len; + if (audio->n_channels) { + track->a_channels = audio->channels; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Channels: %u\n", + track->a_channels); + } else + track->a_channels = 1; } -static int demux_mkv_read_trackvideo(demuxer_t *demuxer, mkv_track_t *track) +static void parse_trackvideo(struct demuxer *demuxer, struct mkv_track *track, + struct ebml_video *video) { - stream_t *s = demuxer->stream; - uint64_t len, length, l; - uint64_t num; - long double fnum; - int il; - - len = length = ebml_read_length(s, &il); - len += il; - while (length > 0) { - switch (ebml_read_id(s, &il)) { - case MATROSKA_ID_VIDEOFRAMERATE: - fnum = ebml_read_float(s, &l); - if (fnum == EBML_FLOAT_INVALID) - return 0; - track->v_frate = fnum; - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Frame rate: %f\n", - track->v_frate); - if (track->v_frate > 0) - track->default_duration = 1 / track->v_frate; - break; - - case MATROSKA_ID_VIDEODISPLAYWIDTH: - num = ebml_read_uint(s, &l); - if (num == EBML_UINT_INVALID) - return 0; - track->v_dwidth = num; - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Display width: %u\n", - track->v_dwidth); - break; - - case MATROSKA_ID_VIDEODISPLAYHEIGHT: - num = ebml_read_uint(s, &l); - if (num == EBML_UINT_INVALID) - return 0; - track->v_dheight = num; - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Display height: %u\n", - track->v_dheight); - break; - - case MATROSKA_ID_VIDEOPIXELWIDTH: - num = ebml_read_uint(s, &l); - if (num == EBML_UINT_INVALID) - return 0; - track->v_width = num; - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Pixel width: %u\n", - track->v_width); - break; - - case MATROSKA_ID_VIDEOPIXELHEIGHT: - num = ebml_read_uint(s, &l); - if (num == EBML_UINT_INVALID) - return 0; - track->v_height = num; - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Pixel height: %u\n", - track->v_height); - break; - - default: - ebml_read_skip(s, &l); - break; - } - length -= l + il; + if (video->n_frame_rate) { + track->v_frate = video->frame_rate; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Frame rate: %f\n", + track->v_frate); + if (track->v_frate > 0) + track->default_duration = 1 / track->v_frate; + } + if (video->n_display_width) { + track->v_dwidth = video->display_width; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Display width: %u\n", + track->v_dwidth); + } + if (video->n_display_height) { + track->v_dheight = video->display_height; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Display height: %u\n", + track->v_dheight); + } + if (video->n_pixel_width) { + track->v_width = video->pixel_width; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Pixel width: %u\n", + track->v_width); + } + if (video->n_pixel_height) { + track->v_height = video->pixel_height; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Pixel height: %u\n", + track->v_height); } - return len; } /** @@ -717,211 +578,141 @@ static int demux_mkv_read_trackvideo(demuxer_t *demuxer, mkv_track_t *track) */ static void demux_mkv_free_trackentry(mkv_track_t *track) { - free(track->name); - free(track->codec_id); - free(track->language); - free(track->private_data); free(track->audio_buf); free(track->audio_timestamp); - demux_mkv_free_encodings(track->encodings, track->num_encodings); - free(track); + talloc_free(track); } -static int demux_mkv_read_trackentry(demuxer_t *demuxer) +static void parse_trackentry(struct demuxer *demuxer, + struct ebml_track_entry *entry) { mkv_demuxer_t *mkv_d = (mkv_demuxer_t *) demuxer->priv; - stream_t *s = demuxer->stream; - mkv_track_t *track; - uint64_t len, length, l; - uint64_t num; - int il; - - track = calloc(1, sizeof(*track)); - /* set default values */ - track->default_track = 1; - track->name = 0; - track->language = strdup("eng"); - - len = length = ebml_read_length(s, &il); - len += il; - while (length > 0) { - switch (ebml_read_id(s, &il)) { - case MATROSKA_ID_TRACKNUMBER: - num = ebml_read_uint(s, &l); - if (num == EBML_UINT_INVALID) - goto err_out; - track->tnum = num; - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Track number: %u\n", - track->tnum); - break; - - case MATROSKA_ID_TRACKNAME: - track->name = ebml_read_utf8(s, &l); - if (track->name == NULL) - goto err_out; - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Name: %s\n", - track->name); - break; - - case MATROSKA_ID_TRACKTYPE: - num = ebml_read_uint(s, &l); - if (num == EBML_UINT_INVALID) - return 0; - track->type = num; - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Track type: "); - switch (track->type) { - case MATROSKA_TRACK_AUDIO: - mp_msg(MSGT_DEMUX, MSGL_V, "Audio\n"); - break; - case MATROSKA_TRACK_VIDEO: - mp_msg(MSGT_DEMUX, MSGL_V, "Video\n"); - break; - case MATROSKA_TRACK_SUBTITLE: - mp_msg(MSGT_DEMUX, MSGL_V, "Subtitle\n"); - break; - default: - mp_msg(MSGT_DEMUX, MSGL_V, "unknown\n"); - break; - } - break; - - case MATROSKA_ID_TRACKAUDIO: - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Audio track\n"); - l = demux_mkv_read_trackaudio(demuxer, track); - if (l == 0) - goto err_out; - break; - - case MATROSKA_ID_TRACKVIDEO: - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Video track\n"); - l = demux_mkv_read_trackvideo(demuxer, track); - if (l == 0) - goto err_out; - break; + struct mkv_track *track = talloc_zero_size(NULL, sizeof(*track)); + + track->tnum = entry->track_number; + if (track->tnum) + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Track number: %u\n", + track->tnum); + else + mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] Missing track number!\n"); + + if (entry->n_name) { + track->name = talloc_strndup(track, entry->name.start, + entry->name.len); + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Name: %s\n", + track->name); + } - case MATROSKA_ID_CODECID: - track->codec_id = ebml_read_ascii(s, &l); - if (track->codec_id == NULL) - goto err_out; - if (!strcmp(track->codec_id, MKV_V_MSCOMP) - || !strcmp(track->codec_id, MKV_A_ACM)) - track->ms_compat = 1; - else if (!strcmp(track->codec_id, MKV_S_VOBSUB)) - track->subtitle_type = MATROSKA_SUBTYPE_VOBSUB; - else if (!strcmp(track->codec_id, MKV_S_TEXTSSA) - || !strcmp(track->codec_id, MKV_S_TEXTASS) - || !strcmp(track->codec_id, MKV_S_SSA) - || !strcmp(track->codec_id, MKV_S_ASS)) { - track->subtitle_type = MATROSKA_SUBTYPE_SSA; - } else if (!strcmp(track->codec_id, MKV_S_TEXTASCII)) - track->subtitle_type = MATROSKA_SUBTYPE_TEXT; - if (!strcmp(track->codec_id, MKV_S_TEXTUTF8)) { - track->subtitle_type = MATROSKA_SUBTYPE_TEXT; - } - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Codec ID: %s\n", - track->codec_id); - break; + track->type = entry->track_type; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Track type: "); + switch (track->type) { + case MATROSKA_TRACK_AUDIO: + mp_msg(MSGT_DEMUX, MSGL_V, "Audio\n"); + break; + case MATROSKA_TRACK_VIDEO: + mp_msg(MSGT_DEMUX, MSGL_V, "Video\n"); + break; + case MATROSKA_TRACK_SUBTITLE: + mp_msg(MSGT_DEMUX, MSGL_V, "Subtitle\n"); + break; + default: + mp_msg(MSGT_DEMUX, MSGL_V, "unknown\n"); + break; + } - case MATROSKA_ID_CODECPRIVATE:; - int x; - num = ebml_read_length(s, &x); - // audit: cheap guard against overflows later.. - if (num > SIZE_MAX - 1000) - return 0; - l = x + num; - track->private_data = malloc(num + AV_LZO_INPUT_PADDING); - if (stream_read(s, track->private_data, num) != (int) num) - goto err_out; - track->private_size = num; - mp_msg(MSGT_DEMUX, MSGL_V, - "[mkv] | + CodecPrivate, length " "%u\n", - track->private_size); - break; + if (entry->n_audio) { + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Audio track\n"); + parse_trackaudio(demuxer, track, &entry->audio); + } - case MATROSKA_ID_TRACKLANGUAGE: - free(track->language); - track->language = ebml_read_utf8(s, &l); - if (track->language == NULL) - goto err_out; - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Language: %s\n", - track->language); - break; + if (entry->n_video) { + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Video track\n"); + parse_trackvideo(demuxer, track, &entry->video); + } - case MATROSKA_ID_TRACKFLAGDEFAULT: - num = ebml_read_uint(s, &l); - if (num == EBML_UINT_INVALID) - goto err_out; - track->default_track = num; - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Default flag: %u\n", - track->default_track); - break; + if (entry->n_codec_id) { + track->codec_id = talloc_strndup(track, entry->codec_id.start, + entry->codec_id.len); + if (!strcmp(track->codec_id, MKV_V_MSCOMP) + || !strcmp(track->codec_id, MKV_A_ACM)) + track->ms_compat = 1; + else if (!strcmp(track->codec_id, MKV_S_VOBSUB)) + track->subtitle_type = MATROSKA_SUBTYPE_VOBSUB; + else if (!strcmp(track->codec_id, MKV_S_TEXTSSA) + || !strcmp(track->codec_id, MKV_S_TEXTASS) + || !strcmp(track->codec_id, MKV_S_SSA) + || !strcmp(track->codec_id, MKV_S_ASS)) { + track->subtitle_type = MATROSKA_SUBTYPE_SSA; + } else if (!strcmp(track->codec_id, MKV_S_TEXTASCII)) + track->subtitle_type = MATROSKA_SUBTYPE_TEXT; + if (!strcmp(track->codec_id, MKV_S_TEXTUTF8)) { + track->subtitle_type = MATROSKA_SUBTYPE_TEXT; + } + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Codec ID: %s\n", + track->codec_id); + } else + mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] Missing codec ID!\n"); + + if (entry->n_codec_private) { + int len = entry->codec_private.len; + track->private_data = talloc_size(track, len + AV_LZO_INPUT_PADDING); + memcpy(track->private_data, entry->codec_private.star |