1
mirror of https://github.com/mpv-player/mpv synced 2024-10-26 07:22:17 +02:00

Merge branch 'matroska'

This commit is contained in:
Uoti Urpala 2010-01-28 00:56:26 +02:00
commit c710c5ee50
10 changed files with 2302 additions and 1289 deletions

View File

@ -894,7 +894,9 @@ TAGS:
tags:
rm -f $@; find . -name '*.[chS]' -o -name '*.asm' | xargs ctags -a
generated_ebml:
TOOLS/matroska.py --generate-header >libmpdemux/ebml_types.h
TOOLS/matroska.py --generate-definitions >libmpdemux/ebml_defs.c
###### tests / tools #######

397
TOOLS/matroska.py Executable file
View File

@ -0,0 +1,397 @@
#!/usr/bin/python
"""
Generate C definitions for parsing Matroska files.
Can also be used to directly parse Matroska files and display their contents.
"""
#
# This file is part of MPlayer.
#
# MPlayer is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# MPlayer is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with MPlayer; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
elements_ebml = (
'EBML, 1a45dfa3, sub', (
'EBMLVersion, 4286, uint',
'EBMLReadVersion, 42f7, uint',
'EBMLMaxIDLength, 42f2, uint',
'EBMLMaxSizeLength, 42f3, uint',
'DocType, 4282, str',
'DocTypeVersion, 4287, uint',
'DocTypeReadVersion, 4285, uint',
),
'CRC32, bf, binary',
'Void, ec, binary',
)
elements_matroska = (
'Segment, 18538067, sub', (
'SeekHead*, 114d9b74, sub', (
'Seek*, 4dbb, sub', (
'SeekID, 53ab, ebml_id',
'SeekPosition, 53ac, uint',
),
),
'Info*, 1549a966, sub', (
'SegmentUID, 73a4, binary',
'PrevUID, 3cb923, binary',
'NextUID, 3eb923, binary',
'TimecodeScale, 2ad7b1, uint',
'DateUTC, 4461, sint',
'Title, 7ba9, str',
'MuxingApp, 4d80, str',
'WritingApp, 5741, str',
'Duration, 4489, float',
),
'Cluster*, 1f43b675, sub', (
'Timecode, e7, uint',
'BlockGroup*, a0, sub', (
'Block, a1, binary',
'BlockDuration, 9b, uint',
'ReferenceBlock*, fb, sint',
),
'SimpleBlock*, a3, binary',
),
'Tracks*, 1654ae6b, sub', (
'TrackEntry*, ae, sub', (
'TrackNumber, d7, uint',
'TrackUID, 73c5, uint',
'TrackType, 83, uint',
'FlagEnabled, b9, uint',
'FlagDefault, 88, uint',
'FlagForced, 55aa, uint',
'FlagLacing, 9c, uint',
'MinCache, 6de7, uint',
'DefaultDuration, 23e383, uint',
'TrackTimecodeScale, 23314f, float',
'MaxBlockAdditionID, 55ee, uint',
'Name, 536e, str',
'Language, 22b59c, str',
'CodecID, 86, str',
'CodecPrivate, 63a2, binary',
'CodecDecodeAll, aa, uint',
'Video, e0, sub', (
'FlagInterlaced, 9a, uint',
'PixelWidth, b0, uint',
'PixelHeight, ba, uint',
'DisplayWidth, 54b0, uint',
'DisplayHeight, 54ba, uint',
'FrameRate, 2383e3, float',
),
'Audio, e1, sub', (
'SamplingFrequency, b5, float',
'Channels, 9f, uint',
'BitDepth, 6264, uint',
),
'ContentEncodings, 6d80, sub', (
'ContentEncoding*, 6240, sub', (
'ContentEncodingOrder, 5031, uint',
'ContentEncodingScope, 5032, uint',
'ContentEncodingType, 5033, uint',
'ContentCompression, 5034, sub', (
'ContentCompAlgo, 4254, uint',
'ContentCompSettings, 4255, binary',
),
),
),
),
),
'Cues, 1c53bb6b, sub', (
'CuePoint*, bb, sub', (
'CueTime, b3, uint',
'CueTrackPositions*, b7, sub', (
'CueTrack, f7, uint',
'CueClusterPosition, f1, uint',
),
),
),
'Attachments, 1941a469, sub', (
'AttachedFile*, 61a7, sub', (
'FileName, 466e, str',
'FileMimeType, 4660, str',
'FileData, 465c, binary',
'FileUID, 46ae, uint',
),
),
'Chapters, 1043a770, sub', (
'EditionEntry*, 45b9, sub', (
'EditionUID, 45bc, uint',
'EditionFlagHidden, 45bd, uint',
'EditionFlagDefault, 45db, uint',
'EditionFlagOrdered, 45dd, uint',
'ChapterAtom*, b6, sub', (
'ChapterUID, 73c4, uint',
'ChapterTimeStart, 91, uint',
'ChapterTimeEnd, 92, uint',
'ChapterFlagHidden, 98, uint',
'ChapterFlagEnabled, 4598, uint',
'ChapterSegmentUID, 6e67, binary',
'ChapterSegmentEditionUID, 6ebc, uint',
'ChapterDisplay*, 80, sub', (
'ChapString, 85, str',
'ChapLanguage*, 437c, str',
),
),
),
),
'Tags*, 1254c367, sub', (
'Tag*, 7373, sub', (
'Targets, 63c0, sub', (
'TargetTypeValue, 68ca, uint',
),
),
),
),
)
import sys
from math import ldexp
def byte2num(s):
return int(s.encode('hex'), 16)
def camelcase_to_words(name):
parts = []
start = 0
for i in range(1, len(name)):
if name[i].isupper() and (name[i-1].islower() or
name[i+1:i+2].islower()):
parts.append(name[start:i])
start = i
parts.append(name[start:])
return '_'.join(parts).lower()
class MatroskaElement(object):
def __init__(self, name, elid, valtype, namespace):
self.name = name
self.definename = '%s_ID_%s' % (namespace, name.upper())
self.fieldname = camelcase_to_words(name)
self.structname = 'ebml_' + self.fieldname
self.elid = elid
self.valtype = valtype
if valtype == 'sub':
self.ebmltype = 'EBML_TYPE_SUBELEMENTS'
self.valname = 'struct %s' % self.structname
else:
self.ebmltype = 'EBML_TYPE_' + valtype.upper()
try:
self.valname = {'uint': 'uint64_t', 'str': 'struct bstr',
'binary': 'struct bstr', 'ebml_id': 'uint32_t',
'float': 'double', 'sint': 'int64_t',
}[valtype]
except KeyError:
raise SyntaxError('Unrecognized value type ' + valtype)
self.subelements = ()
def add_subelements(self, subelements):
self.subelements = subelements
self.subids = set(x[0].elid for x in subelements)
elementd = {}
elementlist = []
def parse_elems(l, namespace):
subelements = []
for el in l:
if isinstance(el, str):
name, hexid, eltype = [x.strip() for x in el.split(',')]
multiple = name.endswith('*')
name = name.strip('*')
new = MatroskaElement(name, hexid, eltype, namespace)
elementd[hexid] = new
elementlist.append(new)
subelements.append((new, multiple))
else:
new.add_subelements(parse_elems(el, namespace))
return subelements
parse_elems(elements_ebml, 'EBML')
parse_elems(elements_matroska, 'MATROSKA')
def generate_C_header():
print('// Generated by TOOLS/matroska.py, do not edit manually')
print
for el in elementlist:
print('#define %-40s 0x%s' % (el.definename, el.elid))
print
for el in reversed(elementlist):
if not el.subelements:
continue
print
print('struct %s {' % el.structname)
l = max(len(subel.valname) for subel, multiple in el.subelements)+1
for subel, multiple in el.subelements:
print(' %-*s %s%s;' % (l, subel.valname, (' ', '*')[multiple],
subel.fieldname))
print
for subel, multiple in el.subelements:
print(' int n_%s;' % (subel.fieldname))
print('};')
for el in elementlist:
if not el.subelements:
continue
print('extern const struct ebml_elem_desc %s_desc;' % el.structname)
print
print('#define MAX_EBML_SUBELEMENTS %d' % max(len(el.subelements)
for el in elementlist))
def generate_C_definitions():
print('// Generated by TOOLS/matroska.py, do not edit manually')
print
for el in reversed(elementlist):
print
if el.subelements:
print('#define N %s' % el.fieldname)
print('E_S("%s", %d)' % (el.name, len(el.subelements)))
for subel, multiple in el.subelements:
print('F(%s, %s, %d)' % (subel.definename, subel.fieldname,
multiple))
print('}};')
print('#undef N')
else:
print('E("%s", %s, %s)' % (el.name, el.fieldname, el.ebmltype))
def read(s, length):
t = s.read(length)
if len(t) != length:
raise IOError
return t
def read_id(s):
t = read(s, 1)
i = 0
mask = 128
if ord(t) == 0:
raise SyntaxError
while not ord(t) & mask:
i += 1
mask >>= 1
t += read(s, i)
return t
def read_vint(s):
t = read(s, 1)
i = 0
mask = 128
if ord(t) == 0:
raise SyntaxError
while not ord(t) & mask:
i += 1
mask >>= 1
t = chr(ord(t) & (mask - 1))
t += read(s, i)
return i+1, byte2num(t)
def read_str(s, length):
return read(s, length)
def read_uint(s, length):
t = read(s, length)
return byte2num(t)
def read_sint(s, length):
i = read_uint(s, length)
mask = 1 << (length * 8 - 1)
if i & mask:
i -= 2 * mask
return i
def read_float(s, length):
t = read(s, length)
i = byte2num(t)
if length == 4:
f = ldexp((i & 0x7fffff) + (1 << 23), (i >> 23 & 0xff) - 150)
if i & (1 << 31):
f = -f
return f
raise SyntaxError
def parse_one(s, depth, parent, maxlen):
elid = read_id(s).encode('hex')
elem = elementd.get(elid)
if parent is not None and elid not in parent.subids and elid not in ('ec', 'bf'):
print('Unexpected:', elid)
if 1:
raise NotImplementedError
size, length = read_vint(s)
this_length = len(elid) / 2 + size + length
if elem is not None:
if elem.valtype != 'skip':
print depth, elid, elem.name, 'size:', length, 'value:',
if elem.valtype == 'sub':
print('subelements:')
while length > 0:
length -= parse_one(s, depth + 1, elem, length)
if length < 0:
raise SyntaxError
elif elem.valtype == 'str':
print 'string', repr(read_str(s, length))
elif elem.valtype in ('binary', 'ebml_id'):
t = read_str(s, length)
dec = ''
if elem.valtype == 'ebml_id':
idelem = elementd.get(t.encode('hex'))
if idelem is None:
dec = '(UNKNOWN)'
else:
dec = '(%s)' % idelem.name
if len(t) < 20:
t = t.encode('hex')
else:
t = '<skipped %d bytes>' % len(t)
print 'binary', t, dec
elif elem.valtype == 'uint':
print 'uint', read_uint(s, length)
elif elem.valtype == 'sint':
print 'sint', read_sint(s, length)
elif elem.valtype == 'float':
print 'float', read_float(s, length)
elif elem.valtype == 'skip':
read(s, length)
else:
raise NotImplementedError
else:
print(depth, 'Unknown element:', elid, 'size:', length)
read(s, length)
return this_length
def parse_toplevel(s):
parse_one(s, 0, None, 1 << 63)
if sys.argv[1] == '--generate-header':
generate_C_header()
elif sys.argv[1] == '--generate-definitions':
generate_C_definitions()
else:
s = open(sys.argv[1])
while 1:
parse_toplevel(s)

View File

@ -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++)

File diff suppressed because it is too large Load Diff

View File

@ -394,19 +394,6 @@ void free_demuxer(demuxer_t *demuxer)
free(demuxer->info);
}
free(demuxer->filename);
if (demuxer->chapters) {
for (i = 0; i < demuxer->num_chapters; i++)
free(demuxer->chapters[i].name);
free(demuxer->chapters);
}
if (demuxer->attachments) {
for (i = 0; i < demuxer->num_attachments; i++) {
free(demuxer->attachments[i].name);
free(demuxer->attachments[i].type);
free(demuxer->attachments[i].data);
}
free(demuxer->attachments);
}
if (demuxer->teletext)
teletext_control(demuxer->teletext, TV_VBI_CONTROL_STOP, NULL);
talloc_free(demuxer);
@ -1455,41 +1442,45 @@ int demuxer_switch_video(demuxer_t *demuxer, int index)
}
int demuxer_add_attachment(demuxer_t *demuxer, const char *name,
const char *type, const void *data, size_t size)
int name_maxlen, const char *type, int type_maxlen,
const void *data, size_t size)
{
if (!(demuxer->num_attachments & 31))
demuxer->attachments = realloc(demuxer->attachments,
(demuxer->num_attachments + 32) * sizeof(demux_attachment_t));
if (!(demuxer->num_attachments % 32))
demuxer->attachments = talloc_realloc(demuxer, demuxer->attachments,
struct demux_attachment,
demuxer->num_attachments + 32);
demuxer->attachments[demuxer->num_attachments].name = strdup(name);
demuxer->attachments[demuxer->num_attachments].type = strdup(type);
demuxer->attachments[demuxer->num_attachments].data = malloc(size);
memcpy(demuxer->attachments[demuxer->num_attachments].data, data, size);
demuxer->attachments[demuxer->num_attachments].data_size = size;
struct demux_attachment *att =
demuxer->attachments + demuxer->num_attachments;
att->name = talloc_strndup(demuxer->attachments, name, name_maxlen);
att->type = talloc_strndup(demuxer->attachments, type, type_maxlen);
att->data = talloc_size(demuxer->attachments, size);
memcpy(att->data, data, size);
att->data_size = size;
return demuxer->num_attachments++;
}
int demuxer_add_chapter(demuxer_t *demuxer, const char *name, uint64_t start,
uint64_t end)
int demuxer_add_chapter(demuxer_t *demuxer, const char *name, int name_maxlen,
uint64_t start, uint64_t end)
{
if (demuxer->chapters == NULL)
demuxer->chapters = malloc(32 * sizeof(*demuxer->chapters));
else if (!(demuxer->num_chapters % 32))
demuxer->chapters = realloc(demuxer->chapters,
(demuxer->num_chapters + 32) *
sizeof(*demuxer->chapters));
if (!(demuxer->num_chapters % 32))
demuxer->chapters = talloc_realloc(demuxer, demuxer->chapters,
struct demux_chapter,
demuxer->num_chapters + 32);
demuxer->chapters[demuxer->num_chapters].start = start;
demuxer->chapters[demuxer->num_chapters].end = end;
demuxer->chapters[demuxer->num_chapters].name = strdup(name ? name : mp_gtext("unknown"));
demuxer->chapters[demuxer->num_chapters].name = name ?
talloc_strndup(demuxer->chapters, name, name_maxlen) :
talloc_strdup(demuxer->chapters, mp_gtext("unknown"));
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CHAPTER_ID=%d\n", demuxer->num_chapters);
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CHAPTER_%d_START=%"PRIu64"\n", demuxer->num_chapters, start);
if (end)
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CHAPTER_%d_END=%"PRIu64"\n", demuxer->num_chapters, end);
if (name)
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CHAPTER_%d_NAME=%s\n", demuxer->num_chapters, name);
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CHAPTER_%d_NAME=%.*s\n", demuxer->num_chapters, name_maxlen, name);
return demuxer->num_chapters++;
}

View File

@ -453,10 +453,11 @@ int demuxer_type_by_filename(char* filename);
void demuxer_help(void);
int get_demuxer_type_from_name(char *demuxer_name, int *force);
int demuxer_add_attachment(demuxer_t* demuxer, const char* name,
const char* type, const void* data, size_t size);
int demuxer_add_chapter(demuxer_t* demuxer, const char* name, uint64_t start, uint64_t end);
int demuxer_add_attachment(demuxer_t *demuxer, const char *name,
int name_maxlen, const char *type, int type_maxlen,
const void *data, size_t size);
int demuxer_add_chapter(demuxer_t *demuxer, const char *name, int name_maxlen,
uint64_t start, uint64_t end);
int demuxer_seek_chapter(demuxer_t *demuxer, int chapter, double *seek_pts,
char **chapter_name);

View File

@ -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 <stdbool.h>
#include <inttypes.h>
#include <stddef.h>
#include <assert.h>
#include "stream/stream.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)
@ -176,9 +182,9 @@ int64_t ebml_read_int(stream_t *s, uint64_t *length)
/*
* Read the next element as a float.
*/
long double ebml_read_float(stream_t *s, uint64_t *length)
double ebml_read_float(stream_t *s, uint64_t *length)
{
long double value;
double value;
uint64_t len;
int l;
@ -279,74 +285,384 @@ uint32_t ebml_read_master(stream_t *s, uint64_t *length)
}
/*
* Read an EBML header.
*/
char *ebml_read_header(stream_t *s, int *version)
#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)
{
uint64_t length, l, num;
uint32_t id;
char *str = NULL;
if (ebml_read_master(s, &length) != EBML_ID_HEADER)
return 0;
if (version)
*version = 1;
while (length > 0) {
id = ebml_read_id(s, NULL);
if (id == EBML_ID_INVALID)
return NULL;
length -= 2;
switch (id) {
/* is our read version uptodate? */
case EBML_ID_EBMLREADVERSION:
num = ebml_read_uint(s, &l);
if (num != EBML_VERSION)
return NULL;
break;
/* we only handle 8 byte lengths at max */
case EBML_ID_EBMLMAXSIZELENGTH:
num = ebml_read_uint(s, &l);
if (num != sizeof(uint64_t))
return NULL;
break;
/* we handle 4 byte IDs at max */
case EBML_ID_EBMLMAXIDLENGTH:
num = ebml_read_uint(s, &l);
if (num != sizeof(uint32_t))
return NULL;
break;
case EBML_ID_DOCTYPE:
str = ebml_read_ascii(s, &l);
if (str == NULL)
return NULL;
break;
case EBML_ID_DOCTYPEREADVERSION:
num = ebml_read_uint(s, &l);
if (num == EBML_UINT_INVALID)
return NULL;
if (version)
*version = num;
break;
/* we ignore these two, they don't tell us anything we care about */
case EBML_ID_VOID:
case EBML_ID_EBMLVERSION:
case EBML_ID_DOCTYPEVERSION:
default:
if (ebml_read_skip(s, &l))
return NULL;
break;
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 -= l;
}
*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;
}
return str;
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, &ctx->bytes_read);
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);
ctx->bytes_read += read_len;
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;
}

View File

@ -20,158 +20,57 @@
#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.
*/
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,
};
/* top-level master-IDs */
#define EBML_ID_HEADER 0x1A45DFA3
struct ebml_field_desc {
uint32_t id;
bool multiple;
int offset;
int count_offset;
const struct ebml_elem_desc *desc;
};
/* 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
struct ebml_elem_desc {
char *name;
enum ebml_elemtype type;
int size;
int field_count;
const struct ebml_field_desc *fields;
};
/* general EBML types */
#define EBML_ID_VOID 0xEC
struct ebml_parse_ctx {
void *talloc_ctx;
int bytes_read;
bool has_errors;
bool no_error_messages;
};
/* ID returned in error cases */
#define EBML_ID_INVALID 0xFFFFFFFF
struct bstr {
uint8_t *start;
int len;
};
#include "ebml_types.h"
/*
* Matroska element IDs. max. 32-bit.
*/
#define EBML_ID_INVALID 0xffffffff
/* 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 */
@ -206,11 +105,13 @@ int64_t ebml_read_vlen_int (uint8_t *buffer, int *length);
uint64_t ebml_read_length (stream_t *s, int *length);
uint64_t ebml_read_uint (stream_t *s, uint64_t *length);
int64_t ebml_read_int (stream_t *s, uint64_t *length);
long double ebml_read_float (stream_t *s, uint64_t *length);
double ebml_read_float (stream_t *s, uint64_t *length);
char *ebml_read_ascii (stream_t *s, uint64_t *length);
char *ebml_read_utf8 (stream_t *s, uint64_t *length);
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 */

382
libmpdemux/ebml_defs.c Normal file
View File

@ -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)
#define N audio
E_S("Audio", 3)
F(MATROSKA_ID_SAMPLINGFREQUENCY, sampling_frequency, 0)
F(MATROSKA_ID_CHANNELS, channels, 0)
F(MATROSKA_ID_BITDEPTH, bit_depth, 0)
}};
#undef N
E("FrameRate", frame_rate, EBML_TYPE_FLOAT)
E("DisplayHeight", display_height, EBML_TYPE_UINT)
E("DisplayWidth", display_width, EBML_TYPE_UINT)
E("PixelHeight", pixel_height, EBML_TYPE_UINT)
E("PixelWidth", pixel_width, EBML_TYPE_UINT)
E("FlagInterlaced", flag_interlaced, EBML_TYPE_UINT)
#define N video
E_S("Video", 6)
F(MATROSKA_ID_FLAGINTERLACED, flag_interlaced, 0)
F(MATROSKA_ID_PIXELWIDTH, pixel_width, 0)
F(MATROSKA_ID_PIXELHEIGHT, pixel_height, 0)
F(MATROSKA_ID_DISPLAYWIDTH, display_width, 0)
F(MATROSKA_ID_DISPLAYHEIGHT, display_height, 0)
F(MATROSKA_ID_FRAMERATE, frame_rate, 0)
}};
#undef N
E("CodecDecodeAll", codec_decode_all, EBML_TYPE_UINT)
E("CodecPrivate", codec_private, EBML_TYPE_BINARY)
E("CodecID", codec_id, EBML_TYPE_STR)
E("Language", language, EBML_TYPE_STR)
E("Name", name, EBML_TYPE_STR)
E("MaxBlockAdditionID", max_block_addition_id, EBML_TYPE_UINT)
E("TrackTimecodeScale", track_timecode_scale, EBML_TYPE_FLOAT)
E("DefaultDuration", default_duration, EBML_TYPE_UINT)
E("MinCache", min_cache, EBML_TYPE_UINT)
E("FlagLacing", flag_lacing, EBML_TYPE_UINT)
E("FlagForced", flag_forced, EBML_TYPE_UINT)
E("FlagDefault", flag_default, EBML_TYPE_UINT)
E("FlagEnabled", flag_enabled, EBML_TYPE_UINT)
E("TrackType", track_type, EBML_TYPE_UINT)
E("TrackUID", track_uid, EBML_TYPE_UINT)
E("TrackNumber", track_number, EBML_TYPE_UINT)
#define N track_entry
E_S("TrackEntry", 19)
F(MATROSKA_ID_TRACKNUMBER, track_number, 0)
F(MATROSKA_ID_TRACKUID, track_uid, 0)
F(MATROSKA_ID_TRACKTYPE, track_type, 0)
F(MATROSKA_ID_FLAGENABLED, flag_enabled, 0)
F(MATROSKA_ID_FLAGDEFAULT, flag_default, 0)
F(MATROSKA_ID_FLAGFORCED, flag_forced, 0)
F(MATROSKA_ID_FLAGLACING, flag_lacing, 0)
F(MATROSKA_ID_MINCACHE, min_cache, 0)
F(MATROSKA_ID_DEFAULTDURATION, default_duration, 0)
F(MATROSKA_ID_TRACKTIMECODESCALE, track_timecode_scale, 0)
F(MATROSKA_ID_MAXBLOCKADDITIONID, max_block_addition_id, 0)
F(MATROSKA_ID_NAME, name, 0)
F(MATROSKA_ID_LANGUAGE, language, 0)
F(MATROSKA_ID_CODECID, codec_id, 0)
F(MATROSKA_ID_CODECPRIVATE, codec_private, 0)
F(MATROSKA_ID_CODECDECODEALL, codec_decode_all, 0)
F(MATROSKA_ID_VIDEO, video, 0)
F(MATROSKA_ID_AUDIO, audio, 0)
F(MATROSKA_ID_CONTENTENCODINGS, content_encodings, 0)
}};
#undef N
#define N tracks
E_S("Tracks", 1)
F(MATROSKA_ID_TRACKENTRY, track_entry, 1)
}};
#undef N
E("SimpleBlock", simple_block, EBML_TYPE_BINARY)
E("ReferenceBlock", reference_block, EBML_TYPE_SINT)
E("BlockDuration", block_duration, EBML_TYPE_UINT)
E("Block", block, EBML_TYPE_BINARY)
#define N block_group
E_S("BlockGroup", 3)
F(MATROSKA_ID_BLOCK, block, 0)
F(MATROSKA_ID_BLOCKDURATION, block_duration, 0)
F(MATROSKA_ID_REFERENCEBLOCK, reference_block, 1)
}};
#undef N
E("Timecode", timecode, EBML_TYPE_UINT)
#define N cluster
E_S("Cluster", 3)
F(MATROSKA_ID_TIMECODE, timecode, 0)
F(MATROSKA_ID_BLOCKGROUP, block_group, 1)
F(MATROSKA_ID_SIMPLEBLOCK, simple_block, 1)
}};
#undef N
E("Duration", duration, EBML_TYPE_FLOAT)
E("WritingApp", writing_app, EBML_TYPE_STR)
E("MuxingApp", muxing_app, EBML_TYPE_STR)
E("Title", title, EBML_TYPE_STR)
E("DateUTC", date_utc, EBML_TYPE_SINT)
E("TimecodeScale", timecode_scale, EBML_TYPE_UINT)
E("NextUID", next_uid, EBML_TYPE_BINARY)
E("PrevUID", prev_uid, EBML_TYPE_BINARY)
E("SegmentUID", segment_uid, EBML_TYPE_BINARY)
#define N info
E_S("Info", 9)
F(MATROSKA_ID_SEGMENTUID, segment_uid, 0)
F(MATROSKA_ID_PREVUID, prev_uid, 0)
F(MATROSKA_ID_NEXTUID, next_uid, 0)
F(MATROSKA_ID_TIMECODESCALE, timecode_scale, 0)
F(MATROSKA_ID_DATEUTC, date_utc, 0)
F(MATROSKA_ID_TITLE, title, 0)
F(MATROSKA_ID_MUXINGAPP, muxing_app, 0)
F(MATROSKA_ID_WRITINGAPP, writing_app, 0)
F(MATROSKA_ID_DURATION, duration, 0)
}};
#undef N
E("SeekPosition", seek_position, EBML_TYPE_UINT)
E("SeekID", seek_id, EBML_TYPE_EBML_ID)
#define N seek
E_S("Seek", 2)
F(MATROSKA_ID_SEEKID, seek_id, 0)
F(MATROSKA_ID_SEEKPOSITION, seek_position, 0)
}};
#undef N
#define N seek_head
E_S("SeekHead", 1)
F(MATROSKA_ID_SEEK, seek, 1)
}};
#undef N
#define N segment
E_S("Segment", 8)
F(MATROSKA_ID_SEEKHEAD, seek_head, 1)
F(MATROSKA_ID_INFO, info, 1)
F(MATROSKA_ID_CLUSTER, cluster, 1)
F(MATROSKA_ID_TRACKS, tracks, 1)
F(MATROSKA_ID_CUES, cues, 0)
F(MATROSKA_ID_ATTACHMENTS, attachments, 0)
F(MATROSKA_ID_CHAPTERS, chapters, 0)
F(MATROSKA_ID_TAGS, tags, 1)
}};
#undef N
E("Void", void, EBML_TYPE_BINARY)
E("CRC32", crc32, EBML_TYPE_BINARY)
E("DocTypeReadVersion", doc_type_read_version, EBML_TYPE_UINT)
E("DocTypeVersion", doc_type_version, EBML_TYPE_UINT)
E("DocType", doc_type, EBML_TYPE_STR)
E("EBMLMaxSizeLength", ebml_max_size_length, EBML_TYPE_UINT)
E("EBMLMaxIDLength", ebml_max_id_length, EBML_TYPE_UINT)
E("EBMLReadVersion", ebml_read_version, EBML_TYPE_UINT)
E("EBMLVersion", ebml_version, EBML_TYPE_UINT)
#define N ebml
E_S("EBML", 7)
F(EBML_ID_EBMLVERSION, ebml_version, 0)
F(EBML_ID_EBMLREADVERSION, ebml_read_version, 0)
F(EBML_ID_EBMLMAXIDLENGTH, ebml_max_id_length, 0)
F(EBML_ID_EBMLMAXSIZELENGTH, ebml_max_size_length, 0)
F(EBML_ID_DOCTYPE, doc_type, 0)
F(EBML_ID_DOCTYPEVERSION, doc_type_version, 0)
F(EBML_ID_DOCTYPEREADVERSION, doc_type_read_version, 0)
}};
#undef N

433
libmpdemux/ebml_types.h Normal file
View File

@ -0,0 +1,433 @@
// Generated by TOOLS/matroska.py, do not edit manually
#define EBML_ID_EBML 0x1a45dfa3
#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
#define EBML_ID_CRC32 0xbf
#define EBML_ID_VOID 0xec
#define MATROSKA_ID_SEGMENT 0x18538067
#define MATROSKA_ID_SEEKHEAD 0x114d9b74
#define MATROSKA_ID_SEEK 0x4dbb
#define MATROSKA_ID_SEEKID 0x53ab
#define MATROSKA_ID_SEEKPOSITION 0x53ac
#define MATROSKA_ID_INFO 0x1549a966
#define MATROSKA_ID_SEGMENTUID 0x73a4
#define MATROSKA_ID_PREVUID 0x3cb923
#define MATROSKA_ID_NEXTUID 0x3eb923
#define MATROSKA_ID_TIMECODESCALE 0x2ad7b1
#define MATROSKA_ID_DATEUTC 0x4461
#define MATROSKA_ID_TITLE 0x7ba9
#define MATROSKA_ID_MUXINGAPP 0x4d80
#define MATROSKA_ID_WRITINGAPP 0x5741
#define MATROSKA_ID_DURATION 0x4489
#define MATROSKA_ID_CLUSTER 0x1f43b675
#define MATROSKA_ID_TIMECODE 0xe7
#define MATROSKA_ID_BLOCKGROUP 0xa0
#define MATROSKA_ID_BLOCK 0xa1
#define MATROSKA_ID_BLOCKDURATION 0x9b
#define MATROSKA_ID_REFERENCEBLOCK 0xfb
#define MATROSKA_ID_SIMPLEBLOCK 0xa3
#define MATROSKA_ID_TRACKS 0x1654ae6b
#define MATROSKA_ID_TRACKENTRY 0xae
#define MATROSKA_ID_TRACKNUMBER 0xd7
#define MATROSKA_ID_TRACKUID 0x73c5
#define MATROSKA_ID_TRACKTYPE 0x83
#define MATROSKA_ID_FLAGENABLED 0xb9
#define MATROSKA_ID_FLAGDEFAULT 0x88
#define MATROSKA_ID_FLAGFORCED 0x55aa
#define MATROSKA_ID_FLAGLACING 0x9c
#define MATROSKA_ID_MINCACHE 0x6de7
#define MATROSKA_ID_DEFAULTDURATION 0x23e383
#define MATROSKA_ID_TRACKTIMECODESCALE 0x23314f
#define MATROSKA_ID_MAXBLOCKADDITIONID 0x55ee
#define MATROSKA_ID_NAME 0x536e
#define MATROSKA_ID_LANGUAGE 0x22b59c
#define MATROSKA_ID_CODECID 0x86
#define MATROSKA_ID_CODECPRIVATE 0x63a2
#define MATROSKA_ID_CODECDECODEALL 0xaa
#define MATROSKA_ID_VIDEO 0xe0
#define MATROSKA_ID_FLAGINTERLACED 0x9a
#define MATROSKA_ID_PIXELWIDTH 0xb0
#define MATROSKA_ID_PIXELHEIGHT 0xba
#define MATROSKA_ID_DISPLAYWIDTH 0x54b0
#define MATROSKA_ID_DISPLAYHEIGHT 0x54ba
#define MATROSKA_ID_FRAMERATE 0x2383e3
#define MATROSKA_ID_AUDIO 0xe1
#define MATROSKA_ID_SAMPLINGFREQUENCY 0xb5
#define MATROSKA_ID_CHANNELS 0x9f
#define MATROSKA_ID_BITDEPTH 0x6264
#define MATROSKA_ID_CONTENTENCODINGS 0x6d80
#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
#define MATROSKA_ID_CUES 0x1c53bb6b
#define MATROSKA_ID_CUEPOINT 0xbb
#define MATROSKA_ID_CUETIME 0xb3
#define MATROSKA_ID_CUETRACKPOSITIONS 0xb7
#define MATROSKA_ID_CUETRACK 0xf7
#define MATROSKA_ID_CUECLUSTERPOSITION 0xf1
#define MATROSKA_ID_ATTACHMENTS 0x1941a469
#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
#define MATROSKA_ID_CHAPTERS 0x1043a770
#define MATROSKA_ID_EDITIONENTRY 0x45b9
#define MATROSKA_ID_EDITIONUID 0x45bc
#define MATROSKA_ID_EDITIONFLAGHIDDEN 0x45bd
#define MATROSKA_ID_EDITIONFLAGDEFAULT 0x45db
#define MATROSKA_ID_EDITIONFLAGORDERED 0x45dd
#define MATROSKA_ID_CHAPTERATOM 0xb6
#define MATROSKA_ID_CHAPTERUID 0x73c4
#define MATROSKA_ID_CHAPTERTIMESTART 0x91
#define MATROSKA_ID_CHAPTERTIMEEND 0x92
#define MATROSKA_ID_CHAPTERFLAGHIDDEN 0x98
#define MATROSKA_ID_CHAPTERFLAGENABLED 0x4598
#define MATROSKA_ID_CHAPTERSEGMENTUID 0x6e67
#define MATROSKA_ID_CHAPTERSEGMENTEDITIONUID 0x6ebc
#define MATROSKA_ID_CHAPTERDISPLAY 0x80
#define MATROSKA_ID_CHAPSTRING 0x85
#define MATROSKA_ID_CHAPLANGUAGE 0x437c
#define MATROSKA_ID_TAGS 0x1254c367
#define MATROSKA_ID_TAG 0x7373
#define MATROSKA_ID_TARGETS 0x63c0
#define MATROSKA_ID_TARGETTYPEVALUE 0x68ca
struct ebml_targets {
uint64_t target_type_value;
int n_target_type_value;
};
struct ebml_tag {
struct ebml_targets targets;
int n_targets;
};
struct ebml_tags {
struct ebml_tag *tag;
int n_tag;
};
struct ebml_chapter_display {
struct bstr chap_string;
struct bstr *chap_language;
int n_chap_string;
int n_chap_language;
};
struct ebml_chapter_atom {
uint64_t chapter_uid;
uint64_t chapter_time_start;
uint64_t chapter_time_end;
uint64_t chapter_flag_hidden;
uint64_t chapter_flag_enabled;
struct bstr chapter_segment_uid;
uint64_t chapter_segment_edition_uid;
struct ebml_chapter_display *chapter_display;
int n_chapter_uid;
int n_chapter_time_start;
int n_chapter_time_end;
int n_chapter_flag_hidden;
int n_chapter_flag_enabled;
int n_chapter_segment_uid;
int n_chapter_segment_edition_uid;
int n_chapter_display;
};
struct ebml_edition_entry {
uint64_t edition_uid;
uint64_t edition_flag_hidden;
uint64_t edition_flag_default;
uint64_t edition_flag_ordered;
struct ebml_chapter_atom *chapter_atom;
int n_edition_uid;
int n_edition_flag_hidden;
int n_edition_flag_default;
int n_edition_flag_ordered;
int n_chapter_atom;
};
struct ebml_chapters {
struct ebml_edition_entry *edition_entry;
int n_edition_entry;
};
struct ebml_attached_file {
struct bstr file_name;
struct bstr file_mime_type;
struct bstr file_data;
uint64_t file_uid;
int n_file_name;
int n_file_mime_type;
int n_file_data;
int n_file_uid;
};
struct ebml_attachments {
struct ebml_attached_file *attached_file;
int n_attached_file;
};
struct ebml_cue_track_positions {
uint64_t cue_track;
uint64_t cue_cluster_position;
int n_cue_track;
int n_cue_cluster_position;
};
struct ebml_cue_point {
uint64_t cue_time;
struct ebml_cue_track_positions *cue_track_positions;
int n_cue_time;
int n_cue_track_positions;
};
struct ebml_cues {
struct ebml_cue_point *cue_point;
int n_cue_point;
};
struct ebml_content_compression {
uint64_t content_comp_algo;
struct bstr content_comp_settings;
int n_content_comp_algo;
int n_content_comp_settings;
};
struct ebml_content_encoding {
uint64_t content_encoding_order;
uint64_t content_encoding_scope;
uint64_t content_encoding_type;
struct ebml_content_compression content_compression;
int n_content_encoding_order;
int n_content_encoding_scope;
int n_content_encoding_type;
int n_content_compression;
};
struct ebml_content_encodings {
struct ebml_content_encoding *content_encoding;
int n_content_encoding;
};
struct ebml_audio {
double sampling_frequency;
uint64_t channels;
uint64_t bit_depth;
int n_sampling_frequency;
int n_channels;
int n_bit_depth;
};
struct ebml_video {
uint64_t flag_interlaced;
uint64_t pixel_width;
uint64_t pixel_height;
uint64_t display_width;
uint64_t display_height;
double frame_rate;
int n_flag_interlaced;
int n_pixel_width;
int n_pixel_height;
int n_display_width;
int n_display_height;
int n_frame_rate;
};
struct ebml_track_entry {
uint64_t track_number;
uint64_t track_uid;
uint64_t track_type;
uint64_t flag_enabled;
uint64_t flag_default;
uint64_t flag_forced;
uint64_t flag_lacing;
uint64_t min_cache;
uint64_t default_duration;
double track_timecode_scale;
uint64_t max_block_addition_id;
struct bstr name;
struct bstr language;
struct bstr codec_id;
struct bstr codec_private;
uint64_t codec_decode_all;
struct ebml_video video;
struct ebml_audio audio;
struct ebml_content_encodings content_encodings;
int n_track_number;
int n_track_uid;
int n_track_type;
int n_flag_enabled;
int n_flag_default;
int n_flag_forced;
int n_flag_lacing;
int n_min_cache;
int n_default_duration;
int n_track_timecode_scale;
int n_max_block_addition_id;
int n_name;
int n_language;
int n_codec_id;
int n_codec_private;
int n_codec_decode_all;
int n_video;
int n_audio;
int n_content_encodings;
};
struct ebml_tracks {
struct ebml_track_entry *track_entry;
int n_track_entry;
};
struct ebml_block_group {
struct bstr block;
uint64_t block_duration;
int64_t *reference_block;
int n_block;
int n_block_duration;
int n_reference_block;
};
struct ebml_cluster {
uint64_t timecode;
struct ebml_block_group *block_group;
struct bstr *simple_block;
int n_timecode;
int n_block_group;
int n_simple_block;
};
struct ebml_info {
struct bstr segment_uid;
struct bstr prev_uid;
struct bstr next_uid;
uint64_t timecode_scale;
int64_t date_utc;
struct bstr title;
struct bstr muxing_app;
struct bstr writing_app;
double duration;
int n_segment_uid;
int n_prev_uid;
int n_next_uid;
int n_timecode_scale;
int n_date_utc;
int n_title;
int n_muxing_app;
int n_writing_app;
int n_duration;
};
struct ebml_seek {
uint32_t seek_id;
uint64_t seek_position;
int n_seek_id;
int n_seek_position;
};
struct ebml_seek_head {
struct ebml_seek *seek;
int n_seek;
};
struct ebml_segment {
struct ebml_seek_head *seek_head;
struct ebml_info *info;
struct ebml_cluster *cluster;
struct ebml_tracks *tracks;
struct ebml_cues cues;
struct ebml_attachments attachments;
struct ebml_chapters chapters;
struct ebml_tags *tags;
int n_seek_head;
int n_info;
int n_cluster;
int n_tracks;
int n_cues;
int n_attachments;
int n_chapters;
int n_tags;
};
struct ebml_ebml {
uint64_t ebml_version;
uint64_t ebml_read_version;
uint64_t ebml_max_id_length;
uint64_t ebml_max_size_length;
struct bstr doc_type;
uint64_t doc_type_version;
uint64_t doc_type_read_version;
int n_ebml_version;
int n_ebml_read_version;
int n_ebml_max_id_length;
int n_ebml_max_size_length;
int n_doc_type;
int n_doc_type_version;
int n_doc_type_read_version;
};
extern const struct ebml_elem_desc ebml_ebml_desc;
extern const struct ebml_elem_desc ebml_segment_desc;
extern const struct ebml_elem_desc ebml_seek_head_desc;
extern const struct ebml_elem_desc ebml_seek_desc;
extern const struct ebml_elem_desc ebml_info_desc;
extern const struct ebml_elem_desc ebml_cluster_desc;
extern const struct ebml_elem_desc ebml_block_group_desc;
extern const struct ebml_elem_desc ebml_tracks_desc;
extern const struct ebml_elem_desc ebml_track_entry_desc;
extern const struct ebml_elem_desc ebml_video_desc;
extern const struct ebml_elem_desc ebml_audio_desc;
extern const struct ebml_elem_desc ebml_content_encodings_desc;
extern const struct ebml_elem_desc ebml_content_encoding_desc;
extern const struct ebml_elem_desc ebml_content_compression_desc;
extern const struct ebml_elem_desc ebml_cues_desc;
extern const struct ebml_elem_desc ebml_cue_point_desc;
extern const struct ebml_elem_desc ebml_cue_track_positions_desc;
extern const struct ebml_elem_desc ebml_attachments_desc;
extern const struct ebml_elem_desc ebml_attached_file_desc;
extern const struct ebml_elem_desc ebml_chapters_desc;
extern const struct ebml_elem_desc ebml_edition_entry_desc;
extern const struct ebml_elem_desc ebml_chapter_atom_desc;
extern const struct ebml_elem_desc ebml_chapter_display_desc;
extern const struct ebml_elem_desc ebml_tags_desc;
extern const struct ebml_elem_desc ebml_tag_desc;
extern const struct ebml_elem_desc ebml_targets_desc;
#define MAX_EBML_SUBELEMENTS 19