summaryrefslogtreecommitdiffstats
path: root/libmpdemux
diff options
context:
space:
mode:
authorUoti Urpala <uau@glyph.nonexistent.invalid>2010-01-28 00:56:26 +0200
committerUoti Urpala <uau@glyph.nonexistent.invalid>2010-01-28 00:56:26 +0200
commitc710c5ee504530eeb7ef7c73f6665fdb291dd206 (patch)
tree7150c1cee52a18db270877ae384290274a129cd2 /libmpdemux
parentd84685ce13c7b31689b257e44b780373c91f8d32 (diff)
parent55c50b3f9931095f7420ce6932329eceaf81d347 (diff)
downloadmpv-c710c5ee504530eeb7ef7c73f6665fdb291dd206.tar.bz2
mpv-c710c5ee504530eeb7ef7c73f6665fdb291dd206.tar.xz
Merge branch 'matroska'
Diffstat (limited to 'libmpdemux')
-rw-r--r--libmpdemux/demux_lavf.c6
-rw-r--r--libmpdemux/demux_mkv.c1636
-rw-r--r--libmpdemux/demuxer.c57
-rw-r--r--libmpdemux/demuxer.h9
-rw-r--r--libmpdemux/ebml.c440
-rw-r--r--libmpdemux/ebml.h195
-rw-r--r--libmpdemux/ebml_defs.c382
-rw-r--r--libmpdemux/ebml_types.h433
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, "[m