--- a
+++ b/jython/CPythonLib/plat-mac/Carbon/MediaDescr.py
@@ -0,0 +1,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', descr)
+        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(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.