diff options
Diffstat (limited to 'libmpdemux')
-rw-r--r-- | libmpdemux/demux_mkv.c | 40 | ||||
-rw-r--r-- | libmpdemux/ebml.c | 400 | ||||
-rw-r--r-- | libmpdemux/ebml.h | 191 | ||||
-rw-r--r-- | libmpdemux/ebml_defs.c | 382 | ||||
-rw-r--r-- | libmpdemux/ebml_types.h | 433 |
5 files changed, 1275 insertions, 171 deletions
diff --git a/libmpdemux/demux_mkv.c b/libmpdemux/demux_mkv.c index b4a17d036f..99e3302c1d 100644 --- a/libmpdemux/demux_mkv.c +++ b/libmpdemux/demux_mkv.c @@ -607,7 +607,7 @@ static int demux_mkv_read_trackaudio(demuxer_t *demuxer, mkv_track_t *track) len += il; while (length > 0) { switch (ebml_read_id(s, &il)) { - case MATROSKA_ID_AUDIOSAMPLINGFREQ: + case MATROSKA_ID_SAMPLINGFREQUENCY: fnum = ebml_read_float(s, &l); if (fnum == EBML_FLOAT_INVALID) return 0; @@ -616,7 +616,7 @@ static int demux_mkv_read_trackaudio(demuxer_t *demuxer, mkv_track_t *track) "[mkv] | + Sampling frequency: %f\n", track->a_sfreq); break; - case MATROSKA_ID_AUDIOBITDEPTH: + case MATROSKA_ID_BITDEPTH: num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) return 0; @@ -625,7 +625,7 @@ static int demux_mkv_read_trackaudio(demuxer_t *demuxer, mkv_track_t *track) track->a_bps); break; - case MATROSKA_ID_AUDIOCHANNELS: + case MATROSKA_ID_CHANNELS: num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) return 0; @@ -655,7 +655,7 @@ static int demux_mkv_read_trackvideo(demuxer_t *demuxer, mkv_track_t *track) len += il; while (length > 0) { switch (ebml_read_id(s, &il)) { - case MATROSKA_ID_VIDEOFRAMERATE: + case MATROSKA_ID_FRAMERATE: fnum = ebml_read_float(s, &l); if (fnum == EBML_FLOAT_INVALID) return 0; @@ -666,7 +666,7 @@ static int demux_mkv_read_trackvideo(demuxer_t *demuxer, mkv_track_t *track) track->default_duration = 1 / track->v_frate; break; - case MATROSKA_ID_VIDEODISPLAYWIDTH: + case MATROSKA_ID_DISPLAYWIDTH: num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) return 0; @@ -675,7 +675,7 @@ static int demux_mkv_read_trackvideo(demuxer_t *demuxer, mkv_track_t *track) track->v_dwidth); break; - case MATROSKA_ID_VIDEODISPLAYHEIGHT: + case MATROSKA_ID_DISPLAYHEIGHT: num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) return 0; @@ -684,7 +684,7 @@ static int demux_mkv_read_trackvideo(demuxer_t *demuxer, mkv_track_t *track) track->v_dheight); break; - case MATROSKA_ID_VIDEOPIXELWIDTH: + case MATROSKA_ID_PIXELWIDTH: num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) return 0; @@ -693,7 +693,7 @@ static int demux_mkv_read_trackvideo(demuxer_t *demuxer, mkv_track_t *track) track->v_width); break; - case MATROSKA_ID_VIDEOPIXELHEIGHT: + case MATROSKA_ID_PIXELHEIGHT: num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) return 0; @@ -755,7 +755,7 @@ static int demux_mkv_read_trackentry(demuxer_t *demuxer) track->tnum); break; - case MATROSKA_ID_TRACKNAME: + case MATROSKA_ID_NAME: track->name = ebml_read_utf8(s, &l); if (track->name == NULL) goto err_out; @@ -785,14 +785,14 @@ static int demux_mkv_read_trackentry(demuxer_t *demuxer) } break; - case MATROSKA_ID_TRACKAUDIO: + case MATROSKA_ID_AUDIO: 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: + case MATROSKA_ID_VIDEO: mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Video track\n"); l = demux_mkv_read_trackvideo(demuxer, track); if (l == 0) @@ -838,7 +838,7 @@ static int demux_mkv_read_trackentry(demuxer_t *demuxer) track->private_size); break; - case MATROSKA_ID_TRACKLANGUAGE: + case MATROSKA_ID_LANGUAGE: free(track->language); track->language = ebml_read_utf8(s, &l); if (track->language == NULL) @@ -847,7 +847,7 @@ static int demux_mkv_read_trackentry(demuxer_t *demuxer) track->language); break; - case MATROSKA_ID_TRACKFLAGDEFAULT: + case MATROSKA_ID_FLAGDEFAULT: num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) goto err_out; @@ -856,7 +856,7 @@ static int demux_mkv_read_trackentry(demuxer_t *demuxer) track->default_track); break; - case MATROSKA_ID_TRACKDEFAULTDURATION: + case MATROSKA_ID_DEFAULTDURATION: num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) goto err_out; @@ -873,7 +873,7 @@ static int demux_mkv_read_trackentry(demuxer_t *demuxer) } break; - case MATROSKA_ID_TRACKENCODINGS: + case MATROSKA_ID_CONTENTENCODINGS: l = demux_mkv_read_trackencodings(demuxer, track); if (l == 0) goto err_out; @@ -955,7 +955,7 @@ static int demux_mkv_read_cues(demuxer_t *demuxer) time = track = pos = EBML_UINT_INVALID; switch (ebml_read_id(s, &il)) { - case MATROSKA_ID_POINTENTRY:; + case MATROSKA_ID_CUEPOINT:; uint64_t len; len = ebml_read_length(s, &i); @@ -970,7 +970,7 @@ static int demux_mkv_read_cues(demuxer_t *demuxer) time = ebml_read_uint(s, &l); break; - case MATROSKA_ID_CUETRACKPOSITION:; + case MATROSKA_ID_CUETRACKPOSITIONS:; uint64_t le = ebml_read_length(s, &i); l = le + i; @@ -1386,7 +1386,7 @@ static int demux_mkv_read_seekhead(demuxer_t *demuxer) seek_pos = EBML_UINT_INVALID; switch (ebml_read_id(s, &il)) { - case MATROSKA_ID_SEEKENTRY:; + case MATROSKA_ID_SEEK:; uint64_t len = ebml_read_length(s, &i); l = len + i; @@ -2747,7 +2747,7 @@ static int demux_mkv_fill_buffer(demuxer_t *demuxer, demux_stream_t *ds) if (mkv_d->cluster_size > 0) { switch (ebml_read_id(s, &il)) { - case MATROSKA_ID_CLUSTERTIMECODE:; + case MATROSKA_ID_TIMECODE:; uint64_t num = ebml_read_uint(s, &l); if (num == EBML_UINT_INVALID) return 0; @@ -2858,7 +2858,7 @@ static void demux_mkv_seek(demuxer_t *demuxer, float rel_seek_secs, if (type == MATROSKA_ID_CLUSTER) { while (!s->eof && stream_tell(s) < end) { if (ebml_read_id(s, NULL) - == MATROSKA_ID_CLUSTERTIMECODE) { + == MATROSKA_ID_TIMECODE) { uint64_t tc = ebml_read_uint(s, NULL); tc *= mkv_d->tc_scale; add_cluster_position(mkv_d, start, tc); diff --git a/libmpdemux/ebml.c b/libmpdemux/ebml.c index 30528e15cb..37e2fe0ffb 100644 --- a/libmpdemux/ebml.c +++ b/libmpdemux/ebml.c @@ -1,5 +1,6 @@ /* * native ebml reader for the Matroska demuxer + * new parser copyright (c) 2010 Uoti Urpala * copyright (c) 2004 Aurelien Jacobs <aurel@gnuage.org> * based on the one written by Ronald Bultje for gstreamer * @@ -23,13 +24,18 @@ #include "config.h" #include <stdlib.h> - -#include "stream/stream.h" +#include <stdbool.h> +#include <inttypes.h> +#include <stddef.h> +#include <assert.h> + +#include <libavutil/intfloat_readwrite.h> +#include <libavutil/common.h> +#include "talloc.h" #include "ebml.h" -#include "libavutil/common.h" +#include "stream/stream.h" #include "mpbswap.h" -#include "libavutil/intfloat_readwrite.h" - +#include "mp_msg.h" #ifndef SIZE_MAX #define SIZE_MAX ((size_t)-1) @@ -288,7 +294,7 @@ char *ebml_read_header(stream_t *s, int *version) uint32_t id; char *str = NULL; - if (ebml_read_master(s, &length) != EBML_ID_HEADER) + if (ebml_read_master(s, &length) != EBML_ID_EBML) return 0; if (version) @@ -350,3 +356,385 @@ char *ebml_read_header(stream_t *s, int *version) return str; } + + + +#define EVALARGS(F, ...) F(__VA_ARGS__) +#define E(str, N, type) const struct ebml_elem_desc ebml_ ## N ## _desc = { str, type }; +#define E_SN(str, count, N) const struct ebml_elem_desc ebml_ ## N ## _desc = { str, EBML_TYPE_SUBELEMENTS, sizeof(struct ebml_ ## N), count, (const struct ebml_field_desc[]){ +#define E_S(str, count) EVALARGS(E_SN, str, count, N) +#define FN(id, name, multiple, N) { id, multiple, offsetof(struct ebml_ ## N, name), offsetof(struct ebml_ ## N, n_ ## name), &ebml_##name##_desc}, +#define F(id, name, multiple) EVALARGS(FN, id, name, multiple, N) +#include "ebml_defs.c" +#undef EVALARGS +#undef SN +#undef S +#undef FN +#undef F + +// Used to read/write pointers to different struct types +struct generic; +#define generic_struct struct generic + +static uint32_t ebml_parse_id(uint8_t *data, int *length) +{ + int len = 1; + uint32_t id = *data++; + for (int len_mask = 0x80; !(id & len_mask); len_mask >>= 1) { + len++; + if (len > 4) { + *length = -1; + return EBML_ID_INVALID; + } + } + *length = len; + while (--len) + id = (id << 8) | *data++; + return id; +} + +static uint64_t parse_vlen(uint8_t *data, int *length, bool is_length) +{ + uint64_t r = *data++; + int len = 1; + int len_mask; + for (len_mask = 0x80; !(r & len_mask); len_mask >>= 1) { + len++; + if (len > 8) { + *length = -1; + return -1; + } + } + r &= len_mask - 1; + + int num_allones = 0; + if (r == len_mask - 1) + num_allones++; + for (int i = 1; i < len; i++) { + if (*data == 255) + num_allones++; + r = (r << 8) | *data++; + } + if (is_length && num_allones == len) { + // According to Matroska specs this means "unknown length" + // Could be supported if there are any actual files using it + *length = -1; + return -1; + } + *length = len; + return r; +} + +static uint64_t ebml_parse_length(uint8_t *data, int *length) +{ + return parse_vlen(data, length, true); +} + +static uint64_t ebml_parse_uint(uint8_t *data, int length) +{ + assert(length >= 1 && length <= 8); + uint64_t r = 0; + while (length--) + r = (r << 8) + *data++; + return r; +} + +static int64_t ebml_parse_sint(uint8_t *data, int length) +{ + assert(length >=1 && length <= 8); + int64_t r = 0; + if (*data & 0x80) + r = -1; + while (length--) + r = (r << 8) | *data++; + return r; +} + +static double ebml_parse_float(uint8_t *data, int length) +{ + assert(length == 4 || length == 8); + uint64_t i = ebml_parse_uint(data, length); + if (length == 4) + return av_int2flt(i); + else + return av_int2dbl(i); +} + + +// target must be initialized to zero +static void ebml_parse_element(struct ebml_parse_ctx *ctx, void *target, + uint8_t *data, int size, + const struct ebml_elem_desc *type, int level) +{ + assert(type->type == EBML_TYPE_SUBELEMENTS); + assert(level < 8); + mp_msg(MSGT_DEMUX, MSGL_DBG2, "%.*s[mkv] Parsing element %s\n", + level, " ", type->name); + + char *s = target; + int len; + uint8_t *end = data + size; + uint8_t *p = data; + int num_elems[MAX_EBML_SUBELEMENTS] = {}; + while (p < end) { + uint8_t *startp = p; + uint32_t id = ebml_parse_id(p, &len); + if (len > end - p) + goto past_end_error; + if (len < 0) { + mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] Error parsing subelement " + "id\n"); + goto other_error; + } + p += len; + uint64_t length = ebml_parse_length(p, &len); + if (len > end - p) + goto past_end_error; + if (len < 0) { + mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] Error parsing subelement " + "length\n"); + goto other_error; + } + p += len; + + int field_idx = -1; + for (int i = 0; i < type->field_count; i++) + if (type->fields[i].id == id) { + field_idx = i; + num_elems[i]++; + break; + } + + if (length > end - p) { + if (field_idx >= 0 && type->fields[field_idx].desc->type + != EBML_TYPE_SUBELEMENTS) { + mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] Subelement content goes " + "past end of containing element\n"); + goto other_error; + } + // Try to parse what is possible from inside this partial element + ctx->has_errors = true; + length = end - p; + } + p += length; + + continue; + + past_end_error: + mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] Subelement headers go " + "past end of containing element\n"); + other_error: + ctx->has_errors = true; + end = startp; + break; + } + + for (int i = 0; i < type->field_count; i++) + if (num_elems[i] && type->fields[i].multiple) { + char *ptr = s + type->fields[i].offset; + switch (type->fields[i].desc->type) { + case EBML_TYPE_SUBELEMENTS: + num_elems[i] = FFMIN(num_elems[i], + 1000000000 / type->fields[i].desc->size); + int size = num_elems[i] * type->fields[i].desc->size; + *(generic_struct **) ptr = talloc_zero_size(ctx->talloc_ctx, + size); + break; + case EBML_TYPE_UINT: + *(uint64_t **) ptr = talloc_zero_array(ctx->talloc_ctx, + uint64_t, num_elems[i]); + break; + case EBML_TYPE_SINT: + *(int64_t **) ptr = talloc_zero_array(ctx->talloc_ctx, + int64_t, num_elems[i]); + break; + case EBML_TYPE_FLOAT: + *(double **) ptr = talloc_zero_array(ctx->talloc_ctx, + double, num_elems[i]); + break; + case EBML_TYPE_STR: + case EBML_TYPE_BINARY: + *(struct bstr **) ptr = talloc_zero_array(ctx->talloc_ctx, + struct bstr, + num_elems[i]); + break; + case EBML_TYPE_EBML_ID: + *(int32_t **) ptr = talloc_zero_array(ctx->talloc_ctx, + uint32_t, num_elems[i]); + break; + default: + abort(); + } + } + + while (data < end) { + int len; + uint32_t id = ebml_parse_id(data, &len); + assert(len >= 0 && len <= end - data); + data += len; + uint64_t length = ebml_parse_length(data, &len); + assert(len >= 0 && len <= end - data); + data += len; + if (length > end - data) { + // Try to parse what is possible from inside this partial element + length = end - data; + mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] Next subelement content goes " + "past end of containing element, will be truncated\n"); + } + int field_idx = -1; + for (int i = 0; i < type->field_count; i++) + if (type->fields[i].id == id) { + field_idx = i; + break; + } + if (field_idx < 0) { + if (id == 0xec) + mp_msg(MSGT_DEMUX, MSGL_DBG2, "%.*s[mkv] Ignoring Void element " + "size: %"PRIu64"\n", level+1, " ", length); + else if (id == 0xbf) + mp_msg(MSGT_DEMUX, MSGL_DBG2, "%.*s[mkv] Ignoring CRC-32 " + "element size: %"PRIu64"\n", level+1, " ", + length); + else + mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] Ignoring unrecognized " + "subelement. ID: %x size: %"PRIu64"\n", id, length); + data += length; + continue; + } + const struct ebml_field_desc *fd = &type->fields[field_idx]; + const struct ebml_elem_desc *ed = fd->desc; + bool multiple = fd->multiple; + int *countptr = (int *) (s + fd->count_offset); + if (*countptr >= num_elems[field_idx]) { + // Shouldn't happen with on any sane file without bugs + mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] Too many subelems?\n"); + ctx->has_errors = true; + data += length; + continue; + } + if (*countptr > 0 && !multiple) { + mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] Another subelement of type " + "%x %s (size: %"PRIu64"). Only one allowed. Ignoring.\n", + id, ed->name, length); + ctx->has_errors = true; + data += length; + continue; + } + mp_msg(MSGT_DEMUX, MSGL_DBG2, "%.*s[mkv] Parsing %x %s size: %"PRIu64 + " value: ", level+1, " ", id, ed->name, length); + + char *fieldptr = s + fd->offset; + switch (ed->type) { + case EBML_TYPE_SUBELEMENTS: + mp_msg(MSGT_DEMUX, MSGL_DBG2, "subelements\n"); + char *subelptr; + if (multiple) { + char *array_start = (char *) *(generic_struct **) fieldptr; + subelptr = array_start + *countptr * ed->size; + } else + subelptr = fieldptr; + ebml_parse_element(ctx, subelptr, data, length, ed, level + 1); + break; + + case EBML_TYPE_UINT:; + uint64_t *uintptr; +#define GETPTR(subelptr, fieldtype) \ + if (multiple) \ + subelptr = *(fieldtype **) fieldptr + *countptr; \ + else \ + subelptr = (fieldtype *) fieldptr + GETPTR(uintptr, uint64_t); + if (length < 1 || length > 8) { + mp_msg(MSGT_DEMUX, MSGL_DBG2, "uint invalid length %"PRIu64 + "\n", length); + goto error; + } + *uintptr = ebml_parse_uint(data, length); + mp_msg(MSGT_DEMUX, MSGL_DBG2, "uint %"PRIu64"\n", *uintptr); + break; + + case EBML_TYPE_SINT:; + int64_t *sintptr; + GETPTR(sintptr, int64_t); + if (length < 1 || length > 8) { + mp_msg(MSGT_DEMUX, MSGL_DBG2, "sint invalid length %"PRIu64 + "\n", length); + goto error; + } + *sintptr = ebml_parse_sint(data, length); + mp_msg(MSGT_DEMUX, MSGL_DBG2, "sint %"PRId64"\n", *sintptr); + break; + + case EBML_TYPE_FLOAT:; + double *floatptr; + GETPTR(floatptr, double); + if (length != 4 && length != 8) { + mp_msg(MSGT_DEMUX, MSGL_DBG2, "float invalid length %"PRIu64 + "\n", length); + goto error; + } + *floatptr = ebml_parse_float(data, length); + mp_msg(MSGT_DEMUX, MSGL_DBG2, "float %f\n", *floatptr); + break; + + case EBML_TYPE_STR: + case EBML_TYPE_BINARY:; + struct bstr *strptr; + GETPTR(strptr, struct bstr); + strptr->start = data; + strptr->len = length; + if (ed->type == EBML_TYPE_STR) + mp_msg(MSGT_DEMUX, MSGL_DBG2, "string \"%.*s\"\n", + strptr->len, strptr->start); + else + mp_msg(MSGT_DEMUX, MSGL_DBG2, "binary %d bytes\n", + strptr->len); + break; + + case EBML_TYPE_EBML_ID:; + uint32_t *idptr; + GETPTR(idptr, uint32_t); + *idptr = ebml_parse_id(data, &len); + if (len != length) { + mp_msg(MSGT_DEMUX, MSGL_DBG2, "ebml_id broken value\n"); + goto error; + } + mp_msg(MSGT_DEMUX, MSGL_DBG2, "ebml_id %x\n", (unsigned)*idptr); + break; + default: + abort(); + } + *countptr += 1; + error: + data += length; + } +} + +// target must be initialized to zero +int ebml_read_element(struct stream *s, struct ebml_parse_ctx *ctx, + void *target, const struct ebml_elem_desc *desc) +{ + ctx->has_errors = false; + int msglevel = ctx->no_error_messages ? MSGL_DBG2 : MSGL_WARN; + uint64_t length = ebml_read_length(s, NULL); + if (s->eof) { + mp_msg(MSGT_DEMUX, msglevel, "[mkv] Unexpected end of file " + "- partial or corrupt file?\n"); + return -1; + } + if (length > 1000000000) { + mp_msg(MSGT_DEMUX, msglevel, "[mkv] Refusing to read element over " + "100 MB in size\n"); + return -1; + } + ctx->talloc_ctx = talloc_size(NULL, length + 8); + int read_len = stream_read(s, ctx->talloc_ctx, length); + if (read_len < length) + mp_msg(MSGT_DEMUX, msglevel, "[mkv] Unexpected end of file " + "- partial or corrupt file?\n"); + ebml_parse_element(ctx, target, ctx->talloc_ctx, read_len, desc, 0); + if (ctx->has_errors) + mp_msg(MSGT_DEMUX, msglevel, "[mkv] Error parsing element %s\n", + desc->name); + return 0; +} diff --git a/libmpdemux/ebml.h b/libmpdemux/ebml.h index c3a785099c..fc6a0ddbac 100644 --- a/libmpdemux/ebml.h +++ b/libmpdemux/ebml.h @@ -20,158 +20,56 @@ #define MPLAYER_EBML_H #include <inttypes.h> +#include <stddef.h> +#include <stdbool.h> + #include "stream/stream.h" /* EBML version supported */ #define EBML_VERSION 1 -/* - * EBML element IDs. max. 32-bit. - */ - -/* top-level master-IDs */ -#define EBML_ID_HEADER 0x1A45DFA3 - -/* IDs in the HEADER master */ -#define EBML_ID_EBMLVERSION 0x4286 -#define EBML_ID_EBMLREADVERSION 0x42F7 -#define EBML_ID_EBMLMAXIDLENGTH 0x42F2 -#define EBML_ID_EBMLMAXSIZELENGTH 0x42F3 -#define EBML_ID_DOCTYPE 0x4282 -#define EBML_ID_DOCTYPEVERSION 0x4287 -#define EBML_ID_DOCTYPEREADVERSION 0x4285 - -/* general EBML types */ -#define EBML_ID_VOID 0xEC +enum ebml_elemtype { + EBML_TYPE_SUBELEMENTS, + EBML_TYPE_UINT, + EBML_TYPE_SINT, + EBML_TYPE_FLOAT, + EBML_TYPE_STR, + EBML_TYPE_BINARY, + EBML_TYPE_EBML_ID, +}; + +struct ebml_field_desc { + uint32_t id; + bool multiple; + int offset; + int count_offset; + const struct ebml_elem_desc *desc; +}; + +struct ebml_elem_desc { + char *name; + enum ebml_elemtype type; + int size; + int field_count; + const struct ebml_field_desc *fields; +}; + +struct ebml_parse_ctx { + void *talloc_ctx; + bool has_errors; + bool no_error_messages; +}; + +struct bstr { + uint8_t *start; + int len; +}; + +#include "ebml_types.h" + +#define EBML_ID_INVALID 0xffffffff -/* ID returned in error cases */ -#define EBML_ID_INVALID 0xFFFFFFFF - - -/* - * Matroska element IDs. max. 32-bit. - */ - -/* toplevel segment */ -#define MATROSKA_ID_SEGMENT 0x18538067 - -/* matroska top-level master IDs */ -#define MATROSKA_ID_INFO 0x1549A966 -#define MATROSKA_ID_TRACKS 0x1654AE6B -#define MATROSKA_ID_CUES 0x1C53BB6B -#define MATROSKA_ID_TAGS 0x1254C367 -#define MATROSKA_ID_SEEKHEAD 0x114D9B74 -#define MATROSKA_ID_ATTACHMENTS 0x1941A469 -#define MATROSKA_ID_CHAPTERS 0x1043A770 -#define MATROSKA_ID_CLUSTER 0x1F43B675 - -/* IDs in the info master */ -#define MATROSKA_ID_TIMECODESCALE 0x2AD7B1 -#define MATROSKA_ID_DURATION 0x4489 -#define MATROSKA_ID_WRITINGAPP 0x5741 -#define MATROSKA_ID_MUXINGAPP 0x4D80 -#define MATROSKA_ID_DATEUTC 0x4461 -#define MATROSKA_ID_SEGMENTUID 0x73A4 - -/* ID in the tracks master */ -#define MATROSKA_ID_TRACKENTRY 0xAE - -/* IDs in the trackentry master */ -#define MATROSKA_ID_TRACKNUMBER 0xD7 -#define MATROSKA_ID_TRACKUID 0x73C5 -#define MATROSKA_ID_TRACKTYPE 0x83 -#define MATROSKA_ID_TRACKAUDIO 0xE1 -#define MATROSKA_ID_TRACKVIDEO 0xE0 -#define MATROSKA_ID_CODECID 0x86 -#define MATROSKA_ID_CODECPRIVATE 0x63A2 -#define MATROSKA_ID_CODECNAME 0x258688 -#define MATROSKA_ID_CODECINFOURL 0x3B4040 -#define MATROSKA_ID_CODECDOWNLOADURL 0x26B240 -#define MATROSKA_ID_TRACKNAME 0x536E -#define MATROSKA_ID_TRACKLANGUAGE 0x22B59C -#define MATROSKA_ID_TRACKFLAGENABLED 0xB9 -#define MATROSKA_ID_TRACKFLAGDEFAULT 0x88 -#define MATROSKA_ID_TRACKFLAGLACING 0x9C -#define MATROSKA_ID_TRACKMINCACHE 0x6DE7 -#define MATROSKA_ID_TRACKMAXCACHE 0x6DF8 -#define MATROSKA_ID_TRACKDEFAULTDURATION 0x23E383 -#define MATROSKA_ID_TRACKENCODINGS 0x6D80 - -/* IDs in the trackaudio master */ -#define MATROSKA_ID_AUDIOSAMPLINGFREQ 0xB5 -#define MATROSKA_ID_AUDIOBITDEPTH 0x6264 -#define MATROSKA_ID_AUDIOCHANNELS 0x9F - -/* IDs in the trackvideo master */ -#define MATROSKA_ID_VIDEOFRAMERATE 0x2383E3 -#define MATROSKA_ID_VIDEODISPLAYWIDTH 0x54B0 -#define MATROSKA_ID_VIDEODISPLAYHEIGHT 0x54BA -#define MATROSKA_ID_VIDEOPIXELWIDTH 0xB0 -#define MATROSKA_ID_VIDEOPIXELHEIGHT 0xBA -#define MATROSKA_ID_VIDEOFLAGINTERLACED 0x9A -#define MATROSKA_ID_VIDEOSTEREOMODE 0x53B9 -#define MATROSKA_ID_VIDEODISPLAYUNIT 0x54B2 -#define MATROSKA_ID_VIDEOASPECTRATIO 0x54B3 -#define MATROSKA_ID_VIDEOCOLOURSPACE 0x2EB524 -#define MATROSKA_ID_VIDEOGAMMA 0x2FB523 - -/* IDs in the trackencodings master */ -#define MATROSKA_ID_CONTENTENCODING 0x6240 -#define MATROSKA_ID_CONTENTENCODINGORDER 0x5031 -#define MATROSKA_ID_CONTENTENCODINGSCOPE 0x5032 -#define MATROSKA_ID_CONTENTENCODINGTYPE 0x5033 -#define MATROSKA_ID_CONTENTCOMPRESSION 0x5034 -#define MATROSKA_ID_CONTENTCOMPALGO 0x4254 -#define MATROSKA_ID_CONTENTCOMPSETTINGS 0x4255 - -/* ID in the cues master */ -#define MATROSKA_ID_POINTENTRY 0xBB - -/* IDs in the pointentry master */ -#define MATROSKA_ID_CUETIME 0xB3 -#define MATROSKA_ID_CUETRACKPOSITION 0xB7 - -/* IDs in the cuetrackposition master */ -#define MATROSKA_ID_CUETRACK 0xF7 -#define MATROSKA_ID_CUECLUSTERPOSITION 0xF1 - -/* IDs in the seekhead master */ -#define MATROSKA_ID_SEEKENTRY 0x4DBB - -/* IDs in the seekpoint master */ -#define MATROSKA_ID_SEEKID 0x53AB -#define MATROSKA_ID_SEEKPOSITION 0x53AC - -/* IDs in the chapters master */ -#define MATROSKA_ID_EDITIONENTRY 0x45B9 -#define MATROSKA_ID_EDITIONFLAGDEFAULT 0x45DB -#define MATROSKA_ID_EDITIONFLAGORDERED 0x45DD -#define MATROSKA_ID_CHAPTERATOM 0xB6 -#define MATROSKA_ID_CHAPTERTIMESTART 0x91 -#define MATROSKA_ID_CHAPTERTIMEEND 0x92 -#define MATROSKA_ID_CHAPTERDISPLAY 0x80 -#define MATROSKA_ID_CHAPSTRING 0x85 -#define MATROSKA_ID_CHAPTERSEGMENTUID 0x6E67 -#define MATROSKA_ID_CHAPTERSEGMENTEDITIONUID\ - 0x6EBC - -/* IDs in the cluster master */ -#define MATROSKA_ID_CLUSTERTIMECODE 0xE7 -#define MATROSKA_ID_BLOCKGROUP 0xA0 - -/* IDs in the blockgroup master */ -#define MATROSKA_ID_BLOCKDURATION 0x9B -#define MATROSKA_ID_BLOCK 0xA1 -#define MATROSKA_ID_SIMPLEBLOCK 0xA3 -#define MATROSKA_ID_REFERENCEBLOCK 0xFB - -/* IDs in the attachments master */ -#define MATROSKA_ID_ATTACHEDFILE 0x61A7 -#define MATROSKA_ID_FILENAME 0x466E -#define MATROSKA_ID_FILEMIMETYPE 0x4660 -#define MATROSKA_ID_FILEDATA 0x465C -#define MATROSKA_ID_FILEUID 0x46AE /* matroska track types */ #define MATROSKA_TRACK_VIDEO 0x01 /* rectangle-shaped pictures aka video */ @@ -213,4 +111,7 @@ int ebml_read_skip (stream_t *s, uint64_t *length); uint32_t ebml_read_master (stream_t *s, uint64_t *length); char *ebml_read_header (stream_t *s, int *version); +int ebml_read_element(struct stream *s, struct ebml_parse_ctx *ctx, + void *target, const struct ebml_elem_desc *desc); + #endif /* MPLAYER_EBML_H */ diff --git a/libmpdemux/ebml_defs.c b/libmpdemux/ebml_defs.c new file mode 100644 index 0000000000..f0296a3d62 --- /dev/null +++ b/libmpdemux/ebml_defs.c @@ -0,0 +1,382 @@ +// Generated by TOOLS/matroska.py, do not edit manually + + +E("TargetTypeValue", target_type_value, EBML_TYPE_UINT) + +#define N targets +E_S("Targets", 1) +F(MATROSKA_ID_TARGETTYPEVALUE, target_type_value, 0) +}}; +#undef N + +#define N tag +E_S("Tag", 1) +F(MATROSKA_ID_TARGETS, targets, 0) +}}; +#undef N + +#define N tags +E_S("Tags", 1) +F(MATROSKA_ID_TAG, tag, 1) +}}; +#undef N + +E("ChapLanguage", chap_language, EBML_TYPE_STR) + +E("ChapString", chap_string, EBML_TYPE_STR) + +#define N chapter_display +E_S("ChapterDisplay", 2) +F(MATROSKA_ID_CHAPSTRING, chap_string, 0) +F(MATROSKA_ID_CHAPLANGUAGE, chap_language, 1) +}}; +#undef N + +E("ChapterSegmentEditionUID", chapter_segment_edition_uid, EBML_TYPE_UINT) + +E("ChapterSegmentUID", chapter_segment_uid, EBML_TYPE_BINARY) + +E("ChapterFlagEnabled", chapter_flag_enabled, EBML_TYPE_UINT) + +E("ChapterFlagHidden", chapter_flag_hidden, EBML_TYPE_UINT) + +E("ChapterTimeEnd", chapter_time_end, EBML_TYPE_UINT) + +E("ChapterTimeStart", chapter_time_start, EBML_TYPE_UINT) + +E("ChapterUID", chapter_uid, EBML_TYPE_UINT) + +#define N chapter_atom +E_S("ChapterAtom", 8) +F(MATROSKA_ID_CHAPTERUID, chapter_uid, 0) +F(MATROSKA_ID_CHAPTERTIMESTART, chapter_time_start, 0) +F(MATROSKA_ID_CHAPTERTIMEEND, chapter_time_end, 0) +F(MATROSKA_ID_CHAPTERFLAGHIDDEN, chapter_flag_hidden, 0) +F(MATROSKA_ID_CHAPTERFLAGENABLED, chapter_flag_enabled, 0) +F(MATROSKA_ID_CHAPTERSEGMENTUID, chapter_segment_uid, 0) +F(MATROSKA_ID_CHAPTERSEGMENTEDITIONUID, chapter_segment_edition_uid, 0) +F(MATROSKA_ID_CHAPTERDISPLAY, chapter_display, 1) +}}; +#undef N + +E("EditionFlagOrdered", edition_flag_ordered, EBML_TYPE_UINT) + +E("EditionFlagDefault", edition_flag_default, EBML_TYPE_UINT) + +E("EditionFlagHidden", edition_flag_hidden, EBML_TYPE_UINT) + +E("EditionUID", edition_uid, EBML_TYPE_UINT) + +#define N edition_entry +E_S("EditionEntry", 5) +F(MATROSKA_ID_EDITIONUID, edition_uid, 0) +F(MATROSKA_ID_EDITIONFLAGHIDDEN, edition_flag_hidden, 0) +F(MATROSKA_ID_EDITIONFLAGDEFAULT, edition_flag_default, 0) +F(MATROSKA_ID_EDITIONFLAGORDERED, edition_flag_ordered, 0) +F(MATROSKA_ID_CHAPTERATOM, chapter_atom, 1) +}}; +#undef N + +#define N chapters +E_S("Chapters", 1) +F(MATROSKA_ID_EDITIONENTRY, edition_entry, 1) +}}; +#undef N + +E("FileUID", file_uid, EBML_TYPE_UINT) + +E("FileData", file_data, EBML_TYPE_BINARY) + +E("FileMimeType", file_mime_type, EBML_TYPE_STR) + +E("FileName", file_name, EBML_TYPE_STR) + +#define N attached_file +E_S("AttachedFile", 4) +F(MATROSKA_ID_FILENAME, file_name, 0) +F(MATROSKA_ID_FILEMIMETYPE, file_mime_type, 0) +F(MATROSKA_ID_FILEDATA, file_data, 0) +F(MATROSKA_ID_FILEUID, file_uid, 0) +}}; +#undef N + +#define N attachments +E_S("Attachments", 1) +F(MATROSKA_ID_ATTACHEDFILE, attached_file, 1) +}}; +#undef N + +E("CueClusterPosition", cue_cluster_position, EBML_TYPE_UINT) + +E("CueTrack", cue_track, EBML_TYPE_UINT) + +#define N cue_track_positions +E_S("CueTrackPositions", 2) +F(MATROSKA_ID_CUETRACK, cue_track, 0) +F(MATROSKA_ID_CUECLUSTERPOSITION, cue_cluster_position, 0) +}}; +#undef N + +E("CueTime", cue_time, EBML_TYPE_UINT) + +#define N cue_point +E_S("CuePoint", 2) +F(MATROSKA_ID_CUETIME, cue_time, 0) +F(MATROSKA_ID_CUETRACKPOSITIONS, cue_track_positions, 1) +}}; +#undef N + +#define N cues +E_S("Cues", 1) +F(MATROSKA_ID_CUEPOINT, cue_point, 1) +}}; +#undef N + +E("ContentCompSettings", content_comp_settings, EBML_TYPE_BINARY) + +E("ContentCompAlgo", content_comp_algo, EBML_TYPE_UINT) + +#define N content_compression +E_S("ContentCompression", 2) +F(MATROSKA_ID_CONTENTCOMPALGO, content_comp_algo, 0) +F(MATROSKA_ID_CONTENTCOMPSETTINGS, content_comp_settings, 0) +}}; +#undef N + +E("ContentEncodingType", content_encoding_type, EBML_TYPE_UINT) + +E("ContentEncodingScope", content_encoding_scope, EBML_TYPE_UINT) + +E("ContentEncodingOrder", content_encoding_order, EBML_TYPE_UINT) + +#define N content_encoding +E_S("ContentEncoding", 4) +F(MATROSKA_ID_CONTENTENCODINGORDER, content_encoding_order, 0) +F(MATROSKA_ID_CONTENTENCODINGSCOPE, content_encoding_scope, 0) +F(MATROSKA_ID_CONTENTENCODINGTYPE, content_encoding_type, 0) +F(MATROSKA_ID_CONTENTCOMPRESSION, content_compression, 0) +}}; +#undef N + +#define N content_encodings +E_S("ContentEncodings", 1) +F(MATROSKA_ID_CONTENTENCODING, content_encoding, 1) +}}; +#undef N + +E("BitDepth", bit_depth, EBML_TYPE_UINT) + +E("Channels", channels, EBML_TYPE_UINT) + +E("SamplingFrequency", sampling_frequency, EBML_TYPE_FLOAT) |