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:
commit
c710c5ee50
4
Makefile
4
Makefile
@ -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
397
TOOLS/matroska.py
Executable 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)
|
@ -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
@ -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++;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
382
libmpdemux/ebml_defs.c
Normal 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
433
libmpdemux/ebml_types.h
Normal 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
|
Loading…
Reference in New Issue
Block a user