1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
| # Parsers/generators for QuickTime media descriptions
| import struct
|
| Error = 'MediaDescr.Error'
|
| class _MediaDescriptionCodec:
| def __init__(self, trunc, size, names, fmt):
| self.trunc = trunc
| self.size = size
| self.names = names
| self.fmt = fmt
|
| def decode(self, data):
| if self.trunc:
| data = data[:self.size]
| values = struct.unpack(self.fmt, data)
| if len(values) != len(self.names):
| raise Error, ('Format length does not match number of names')
| rv = {}
| for i in range(len(values)):
| name = self.names[i]
| value = values[i]
| if type(name) == type(()):
| name, cod, dec = name
| value = dec(value)
| rv[name] = value
| return rv
|
| def encode(self, dict):
| list = [self.fmt]
| for name in self.names:
| if type(name) == type(()):
| name, cod, dec = name
| else:
| cod = dec = None
| value = dict[name]
| if cod:
| value = cod(value)
| list.append(value)
| rv = struct.pack(*list)
| return rv
|
| # Helper functions
| def _tofixed(float):
| hi = int(float)
| lo = int(float*0x10000) & 0xffff
| return (hi<<16)|lo
|
| def _fromfixed(fixed):
| hi = (fixed >> 16) & 0xffff
| lo = (fixed & 0xffff)
| return hi + (lo / float(0x10000))
|
| def _tostr31(str):
| return chr(len(str)) + str + '\0'*(31-len(str))
|
| def _fromstr31(str31):
| return str31[1:1+ord(str31[0])]
|
| SampleDescription = _MediaDescriptionCodec(
| 1, # May be longer, truncate
| 16, # size
| ('descSize', 'dataFormat', 'resvd1', 'resvd2', 'dataRefIndex'), # Attributes
| "l4slhh" # Format
| )
|
| SoundDescription = _MediaDescriptionCodec(
| 1,
| 36,
| ('descSize', 'dataFormat', 'resvd1', 'resvd2', 'dataRefIndex',
| 'version', 'revlevel', 'vendor', 'numChannels', 'sampleSize',
| 'compressionID', 'packetSize', ('sampleRate', _tofixed, _fromfixed)),
| "l4slhhhh4shhhhl" # Format
| )
|
| SoundDescriptionV1 = _MediaDescriptionCodec(
| 1,
| 52,
| ('descSize', 'dataFormat', 'resvd1', 'resvd2', 'dataRefIndex',
| 'version', 'revlevel', 'vendor', 'numChannels', 'sampleSize',
| 'compressionID', 'packetSize', ('sampleRate', _tofixed, _fromfixed), 'samplesPerPacket',
| 'bytesPerPacket', 'bytesPerFrame', 'bytesPerSample'),
| "l4slhhhh4shhhhlllll" # Format
| )
|
| ImageDescription = _MediaDescriptionCodec(
| 1, # May be longer, truncate
| 86, # size
| ('idSize', 'cType', 'resvd1', 'resvd2', 'dataRefIndex', 'version',
| 'revisionLevel', 'vendor', 'temporalQuality', 'spatialQuality',
| 'width', 'height', ('hRes', _tofixed, _fromfixed), ('vRes', _tofixed, _fromfixed),
| 'dataSize', 'frameCount', ('name', _tostr31, _fromstr31),
| 'depth', 'clutID'),
| 'l4slhhhh4sllhhlllh32shh',
| )
|
| # XXXX Others, like TextDescription and such, remain to be done.
|
|