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