Home | History | Annotate | Download | only in Carbon
      1 # Parsers/generators for QuickTime media descriptions
      2 import struct
      3 
      4 Error = 'MediaDescr.Error'
      5 
      6 class _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
     44 def _tofixed(float):
     45     hi = int(float)
     46     lo = int(float*0x10000) & 0xffff
     47     return (hi<<16)|lo
     48 
     49 def _fromfixed(fixed):
     50     hi = (fixed >> 16) & 0xffff
     51     lo = (fixed & 0xffff)
     52     return hi + (lo / float(0x10000))
     53 
     54 def _tostr31(str):
     55     return chr(len(str)) + str + '\0'*(31-len(str))
     56 
     57 def _fromstr31(str31):
     58     return str31[1:1+ord(str31[0])]
     59 
     60 SampleDescription = _MediaDescriptionCodec(
     61         1,      # May be longer, truncate
     62         16,     # size
     63         ('descSize', 'dataFormat', 'resvd1', 'resvd2', 'dataRefIndex'), # Attributes
     64         "l4slhh"        # Format
     65 )
     66 
     67 SoundDescription = _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 
     76 SoundDescriptionV1 = _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 
     86 ImageDescription = _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