Example #1
0
    def __parse_freeform(self, atom, data):
        length = cdata.uint_be(data[:4])
        mean = data[12:length]
        pos = length
        length = cdata.uint_be(data[pos:pos + 4])
        name = data[pos + 12:pos + length]
        pos += length
        value = []
        while pos < atom.length - 8:
            length, atom_name = struct.unpack(">I4s", data[pos:pos + 8])
            if atom_name != b"data":
                raise MP4MetadataError("unexpected atom %r inside %r" %
                                       (atom_name, atom.name))
            if length < 1:
                raise MP4MetadataError("atom %r has a length of zero" %
                                       atom.name)
            version = ord(data[pos + 8:pos + 8 + 1])
            flags = struct.unpack(">I", b"\x00" + data[pos + 9:pos + 12])[0]
            value.append(
                MP4FreeForm(data[pos + 16:pos + length],
                            dataformat=flags,
                            version=version))
            pos += length

        key = _name2key(atom.name + b":" + mean + b":" + name)
        self.__add(key, value)
    def __parse_freeform(self, atom, data):
        length = cdata.uint_be(data[:4])
        mean = data[12:length]
        pos = length
        length = cdata.uint_be(data[pos : pos + 4])
        name = data[pos + 12 : pos + length]
        pos += length
        value = []
        while pos < atom.length - 8:
            length, atom_name = struct.unpack(">I4s", data[pos : pos + 8])
            if atom_name != b"data":
                raise MP4MetadataError(
                    "unexpected atom %r inside %r" % (atom_name, atom.name)
                )

            version = ord(data[pos + 8 : pos + 8 + 1])
            flags = struct.unpack(">I", b"\x00" + data[pos + 9 : pos + 12])[0]
            value.append(
                MP4FreeForm(
                    data[pos + 16 : pos + length], dataformat=flags, version=version
                )
            )
            pos += length

        key = _name2key(atom.name + b":" + mean + b":" + name)
        self.__add(key, value)
Example #3
0
 def __read_offsets(self, filename):
     fileobj = open(filename, 'rb')
     atoms = Atoms(fileobj)
     moov = atoms[b'moov']
     samples = []
     for atom in moov.findall(b'stco', True):
         fileobj.seek(atom.offset + 12)
         data = fileobj.read(atom.length - 12)
         fmt = ">%dI" % cdata.uint_be(data[:4])
         offsets = struct.unpack(fmt, data[4:])
         for offset in offsets:
             fileobj.seek(offset)
             samples.append(fileobj.read(8))
     for atom in moov.findall(b'co64', True):
         fileobj.seek(atom.offset + 12)
         data = fileobj.read(atom.length - 12)
         fmt = ">%dQ" % cdata.uint_be(data[:4])
         offsets = struct.unpack(fmt, data[4:])
         for offset in offsets:
             fileobj.seek(offset)
             samples.append(fileobj.read(8))
     try:
         for atom in atoms[b"moof"].findall(b'tfhd', True):
             data = fileobj.read(atom.length - 9)
             flags = cdata.uint_be(b"\x00" + data[:3])
             if flags & 1:
                 offset = cdata.ulonglong_be(data[7:15])
                 fileobj.seek(offset)
                 samples.append(fileobj.read(8))
     except KeyError:
         pass
     fileobj.close()
     return samples
Example #4
0
 def __read_offsets(self, filename):
     fileobj = open(filename, 'rb')
     atoms = Atoms(fileobj)
     moov = atoms['moov']
     samples = []
     for atom in moov.findall('stco', True):
         fileobj.seek(atom.offset + 12)
         data = fileobj.read(atom.length - 12)
         fmt = ">%dI" % cdata.uint_be(data[:4])
         offsets = struct.unpack(fmt, data[4:])
         for offset in offsets:
             fileobj.seek(offset)
             samples.append(fileobj.read(8))
     for atom in moov.findall('co64', True):
         fileobj.seek(atom.offset + 12)
         data = fileobj.read(atom.length - 12)
         fmt = ">%dQ" % cdata.uint_be(data[:4])
         offsets = struct.unpack(fmt, data[4:])
         for offset in offsets:
             fileobj.seek(offset)
             samples.append(fileobj.read(8))
     try:
         for atom in atoms["moof"].findall('tfhd', True):
             data = fileobj.read(atom.length - 9)
             flags = cdata.uint_be("\x00" + data[:3])
             if flags & 1:
                 offset = cdata.ulonglong_be(data[7:15])
                 fileobj.seek(offset)
                 samples.append(fileobj.read(8))
     except KeyError:
         pass
     fileobj.close()
     return samples
Example #5
0
File: mp4.py Project: mattbun/sift
    def __init__(self, atoms, fileobj):
        for trak in list(atoms["moov"].findall(b"trak")):
            hdlr = trak["mdia", "hdlr"]
            fileobj.seek(hdlr.offset)
            data = fileobj.read(hdlr.length)
            if data[16:20] == b"soun":
                break
        else:
            raise MP4StreamInfoError("track has no audio data")

        mdhd = trak["mdia", "mdhd"]
        fileobj.seek(mdhd.offset)
        data = bytearray(fileobj.read(mdhd.length))
        if data[8] == 0:
            offset = 20
            fmt = ">2I"
        else:
            offset = 28
            fmt = ">IQ"
        end = offset + struct_calcsize(fmt)
        unit, length = struct_unpack(fmt, data[offset:end])
        self.length = float(length) / unit

        try:
            atom = trak["mdia", "minf", "stbl", "stsd"]
            fileobj.seek(atom.offset)
            data = bytearray(fileobj.read(atom.length))
            if data[20:24] == b"mp4a":
                length = cdata.uint_be(data[16:20])
                (self.channels, self.bits_per_sample, _,
                 self.sample_rate) = struct_unpack(">3HI", data[40:50])
                # ES descriptor type
                if data[56:60] == b"esds" and ord(data[64:65]) == 0x03:
                    pos = 65
                    # skip extended descriptor type tag, length, ES ID
                    # and stream priority
                    if data[pos:pos+3] == b"\x80\x80\x80":
                        pos += 3
                    pos += 4
                    # decoder config descriptor type
                    if data[pos] == 0x04:
                        pos += 1
                        # skip extended descriptor type tag, length,
                        # object type ID, stream type, buffer size
                        # and maximum bitrate
                        if data[pos:pos+3] == b"\x80\x80\x80":
                            pos += 3
                        pos += 10
                        # average bitrate
                        self.bitrate = cdata.uint_be(data[pos:pos+4])
        except (ValueError, KeyError):
            # stsd atoms are optional
            pass
Example #6
0
    def test_uint(self):
        self.failUnlessEqual(cdata.uint_le(self.ZERO(4)), 0)
        self.failUnlessEqual(cdata.uint_le(self.LEONE(4)), 1)
        self.failUnlessEqual(cdata.uint_le(self.BEONE(4)), 2**32 >> 8)
        self.failUnlessEqual(cdata.uint_le(self.NEGONE(4)), 2**32 - 1)
        self.assertTrue(cdata.uint_le is cdata.uint32_le)

        self.failUnlessEqual(cdata.uint_be(self.ZERO(4)), 0)
        self.failUnlessEqual(cdata.uint_be(self.LEONE(4)), 2**32 >> 8)
        self.failUnlessEqual(cdata.uint_be(self.BEONE(4)), 1)
        self.failUnlessEqual(cdata.uint_be(self.NEGONE(4)), 2**32 - 1)
        self.assertTrue(cdata.uint_be is cdata.uint32_be)
Example #7
0
    def test_uint(self):
        self.failUnlessEqual(cdata.uint_le(self.ZERO(4)), 0)
        self.failUnlessEqual(cdata.uint_le(self.LEONE(4)), 1)
        self.failUnlessEqual(cdata.uint_le(self.BEONE(4)), 2 ** 32 >> 8)
        self.failUnlessEqual(cdata.uint_le(self.NEGONE(4)), 2 ** 32 - 1)
        self.assertTrue(cdata.uint_le is cdata.uint32_le)

        self.failUnlessEqual(cdata.uint_be(self.ZERO(4)), 0)
        self.failUnlessEqual(cdata.uint_be(self.LEONE(4)), 2 ** 32 >> 8)
        self.failUnlessEqual(cdata.uint_be(self.BEONE(4)), 1)
        self.failUnlessEqual(cdata.uint_be(self.NEGONE(4)), 2 ** 32 - 1)
        self.assertTrue(cdata.uint_be is cdata.uint32_be)
Example #8
0
 def __update_parents(self, fileobj, path, delta, offset):
     # Update all parent atoms with the new size.
     for atom in path:
         fileobj.seek(atom.offset + offset)
         size = cdata.uint_be(fileobj.read(4)) + delta
         fileobj.seek(atom.offset + offset)
         fileobj.write(cdata.to_uint_be(size))
Example #9
0
 def __update_parents(self, fileobj, path, delta, offset):
     # Update all parent atoms with the new size.
     for atom in path:
         fileobj.seek(atom.offset + offset)
         size = cdata.uint_be(fileobj.read(4)) + delta
         fileobj.seek(atom.offset + offset)
         fileobj.write(cdata.to_uint_be(size))
Example #10
0
    def __init__(self, atoms, fileobj):
        hdlr = atoms["moov.trak.mdia.hdlr"]
        fileobj.seek(hdlr.offset)
        if "soun" not in fileobj.read(hdlr.length):
            raise M4AStreamInfoError("track has no audio data")

        mdhd = atoms["moov.trak.mdia.mdhd"]
        fileobj.seek(mdhd.offset)
        data = fileobj.read(mdhd.length)
        if ord(data[8]) == 0:
            offset = 20
            fmt = ">2I"
        else:
            offset = 28
            fmt = ">IQ"
        end = offset + struct.calcsize(fmt)
        unit, length = struct.unpack(fmt, data[offset:end])
        self.length = float(length) / unit

        try:
            atom = atoms["moov.trak.mdia.minf.stbl.stsd"]
            fileobj.seek(atom.offset)
            data = fileobj.read(atom.length)
            self.bitrate = cdata.uint_be(data[-17:-13])
        except (ValueError, KeyError):
            # Bitrate values are optional.
            pass
Example #11
0
    def __init__(self, atoms, fileobj):
        hdlr = atoms["moov.trak.mdia.hdlr"]
        fileobj.seek(hdlr.offset)
        if "soun" not in fileobj.read(hdlr.length):
            raise M4AStreamInfoError("track has no audio data")

        mdhd = atoms["moov.trak.mdia.mdhd"]
        fileobj.seek(mdhd.offset)
        data = fileobj.read(mdhd.length)
        if ord(data[8]) == 0:
            offset = 20
            fmt = ">2I"
        else:
            offset = 28
            fmt = ">IQ"
        end = offset + struct.calcsize(fmt)
        unit, length = struct.unpack(fmt, data[offset:end])
        self.length = float(length) / unit

        try:
            atom = atoms["moov.trak.mdia.minf.stbl.stsd"]
            fileobj.seek(atom.offset)
            data = fileobj.read(atom.length)
            self.bitrate = cdata.uint_be(data[-17:-13])
        except (ValueError, KeyError):
            # Bitrate values are optional.
            pass
Example #12
0
File: mp4.py Project: kwytay/Magger
 def __parse_freeform(self, atom, data):
     length = cdata.uint_be(data[:4])
     mean = data[12:length]
     pos = length
     length = cdata.uint_be(data[pos : pos + 4])
     name = data[pos + 12 : pos + length]
     pos += length
     value = []
     while pos < atom.length - 8:
         length, atom_name = struct.unpack(">I4s", data[pos : pos + 8])
         if atom_name != "data":
             raise MP4MetadataError("unexpected atom %r inside %r" % (atom_name, atom.name))
         value.append(data[pos + 16 : pos + length])
         pos += length
     if value:
         self["%s:%s:%s" % (atom.name, mean, name)] = value
Example #13
0
 def __parse_freeform(self, atom, data):
     try:
         fileobj = StringIO(data)
         mean_length = cdata.uint_be(fileobj.read(4))
         # skip over 8 bytes of atom name, flags
         mean = fileobj.read(mean_length - 4)[8:]
         name_length = cdata.uint_be(fileobj.read(4))
         name = fileobj.read(name_length - 4)[8:]
         value_length = cdata.uint_be(fileobj.read(4))
         # Name, flags, and reserved bytes
         value = fileobj.read(value_length - 4)[12:]
     except struct.error:
         # Some ---- atoms have no data atom, I have no clue why
         # they actually end up in the file.
         pass
     else:
         self["%s:%s:%s" % (atom.name, mean, name)] = value
Example #14
0
 def __parse_freeform(self, atom, data):
     try:
         fileobj = StringIO(data)
         mean_length = cdata.uint_be(fileobj.read(4))
         # skip over 8 bytes of atom name, flags
         mean = fileobj.read(mean_length - 4)[8:]
         name_length = cdata.uint_be(fileobj.read(4))
         name = fileobj.read(name_length - 4)[8:]
         value_length = cdata.uint_be(fileobj.read(4))
         # Name, flags, and reserved bytes
         value = fileobj.read(value_length - 4)[12:]
     except struct.error:
         # Some ---- atoms have no data atom, I have no clue why
         # they actually end up in the file.
         pass
     else:
         self["%s:%s:%s" % (atom.name, mean, name)] = value
Example #15
0
File: mp4.py Project: mattbun/sift
 def __parse_freeform(self, atom, data):
     length = cdata.uint_be(data[:4])
     mean = data[12:length]
     pos = length
     length = cdata.uint_be(data[pos:pos+4])
     name = data[pos+12:pos+length]
     pos += length
     value = []
     while pos < atom.length - 8:
         length, atom_name = struct_unpack(">I4s", data[pos:pos+8])
         if atom_name != b"data":
             raise MP4MetadataError(
                 "unexpected atom %r inside %r" % (atom_name, atom.name))
         value.append(data[pos+16:pos+length])
         pos += length
     if value:
         self[atom.name + b":" + mean + b":" + name] = value
Example #16
0
def _parse_full_atom(data):
    """Some atoms are versioned. Split them up in (version, flags, payload).
    Can raise ValueError.
    """

    if len(data) < 4:
        raise ValueError("not enough data")

    version = ord(data[0:1])
    flags = cdata.uint_be(b"\x00" + data[1:4])
    return version, flags, data[4:]
Example #17
0
def parse_full_atom(data):
    """Some atoms are versioned. Split them up in (version, flags, payload).
    Can raise ValueError.
    """

    if len(data) < 4:
        raise ValueError("not enough data")

    version = ord(data[0:1])
    flags = cdata.uint_be(b"\x00" + data[1:4])
    return version, flags, data[4:]
Example #18
0
File: mp4.py Project: mattbun/sift
 def __update_offset_table(self, fileobj, fmt, atom, delta, offset):
     """Update offset table in the specified atom."""
     if atom.offset > offset:
         atom.offset += delta
     fileobj.seek(atom.offset + 12)
     data = fileobj.read(atom.length - 12)
     fmt = fmt % cdata.uint_be(data[:4])
     offsets = struct_unpack(fmt, data[4:])
     offsets = [o + (0, delta)[offset < o] for o in offsets]
     fileobj.seek(atom.offset + 16)
     fileobj.write(struct_pack(fmt, *offsets))
Example #19
0
 def __update_offset_table(self, fileobj, fmt, atom, delta, offset):
     """Update offset table in the specified atom."""
     if atom.offset > offset:
         atom.offset += delta
     fileobj.seek(atom.offset + 12)
     data = fileobj.read(atom.length - 12)
     fmt = fmt % cdata.uint_be(data[:4])
     offsets = struct.unpack(fmt, data[4:])
     offsets = [o + (0, delta)[offset < o] for o in offsets]
     fileobj.seek(atom.offset + 16)
     fileobj.write(struct.pack(fmt, *offsets))
Example #20
0
File: mp4.py Project: mattbun/sift
 def __update_tfhd(self, fileobj, atom, delta, offset):
     if atom.offset > offset:
         atom.offset += delta
     fileobj.seek(atom.offset + 9)
     data = fileobj.read(atom.length - 9)
     flags = cdata.uint_be(b"\x00" + data[:3])
     if flags & 1:
         o = cdata.ulonglong_be(data[7:15])
         if o > offset:
             o += delta
         fileobj.seek(atom.offset + 16)
         fileobj.write(cdata.to_ulonglong_be(o))
Example #21
0
 def __update_tfhd(self, fileobj, atom, delta, offset):
     if atom.offset > offset:
         atom.offset += delta
     fileobj.seek(atom.offset + 9)
     data = fileobj.read(atom.length - 9)
     flags = cdata.uint_be(b"\x00" + data[:3])
     if flags & 1:
         o = cdata.ulonglong_be(data[7:15])
         if o > offset:
             o += delta
         fileobj.seek(atom.offset + 16)
         fileobj.write(cdata.to_ulonglong_be(o))
Example #22
0
File: mp4.py Project: mattbun/sift
 def __update_parents(self, fileobj, path, delta):
     """Update all parent atoms with the new size."""
     for atom in path:
         fileobj.seek(atom.offset)
         size = cdata.uint_be(fileobj.read(4))
         if size == 1: # 64bit
             # skip name (4B) and read size (8B)
             size = cdata.ulonglong_be(fileobj.read(12)[4:])
             fileobj.seek(atom.offset + 8)
             fileobj.write(cdata.to_ulonglong_be(size + delta))
         else: # 32bit
             fileobj.seek(atom.offset)
             fileobj.write(cdata.to_uint_be(size + delta))
Example #23
0
    def __parse_freeform(self, atom, data):
        length = cdata.uint_be(data[:4])
        mean = data[12:length]
        pos = length
        length = cdata.uint_be(data[pos : pos + 4])
        name = data[pos + 12 : pos + length]
        pos += length
        value = []
        while pos < atom.length - 8:
            length, atom_name = struct.unpack(">I4s", data[pos : pos + 8])
            if atom_name != "data":
                raise MP4MetadataError("unexpected atom %r inside %r" % (atom_name, atom.name))

            version = ord(data[pos + 8])
            if version != 0:
                raise MP4MetadataError("Unsupported version: %r" % version)

            flags = struct.unpack(">I", "\x00" + data[pos + 9 : pos + 12])[0]
            value.append(MP4FreeForm(data[pos + 16 : pos + length], dataformat=flags))
            pos += length
        if value:
            self["%s:%s:%s" % (atom.name, mean, name)] = value
Example #24
0
File: mp4.py Project: stedy/mutagen
    def __parse_freeform(self, atom, data):
        length = cdata.uint_be(data[:4])
        mean = data[12:length]
        pos = length
        length = cdata.uint_be(data[pos:pos + 4])
        name = data[pos + 12:pos + length]
        pos += length
        value = []
        while pos < atom.length - 8:
            length, atom_name = struct.unpack(">I4s", data[pos:pos + 8])
            if atom_name != b"data":
                raise MP4MetadataError("unexpected atom %r inside %r" %
                                       (atom_name, atom.name))

            version = ord(data[pos + 8:pos + 8 + 1])
            if version != 0:
                raise MP4MetadataError("Unsupported version: %r" % version)

            flags = struct.unpack(">I", b"\x00" + data[pos + 9:pos + 12])[0]
            value.append(
                MP4FreeForm(data[pos + 16:pos + length], dataformat=flags))
            pos += length
        if value:
            self[atom.name + b":" + mean + b":" + name] = value
Example #25
0
 def __init__(self, fileobj):
     page = OggPage(fileobj)
     while not page.packets[0].startswith("\x80theora"):
         page = OggPage(fileobj)
     if not page.first:
         raise OggTheoraHeaderError(
             "page has ID header, but doesn't start a stream")
     data = page.packets[0]
     vmaj, vmin = struct.unpack("2B", data[7:9])
     if (vmaj, vmin) != (3, 2):
         raise OggTheoraHeaderError(
             "found Theora version %d.%d != 3.2" % (vmaj, vmin))
     fps_num, fps_den = struct.unpack(">2I", data[22:30])
     self.fps = fps_num / float(fps_den)
     self.bitrate = cdata.uint_be("\x00" + data[37:40])
     self.granule_shift = (cdata.ushort_be(data[40:42]) >> 5) & 0x1F
     self.serial = page.serial
Example #26
0
 def __init__(self, fileobj):
     page = OggPage(fileobj)
     while not page.packets[0].startswith(b"\x80theora"):
         page = OggPage(fileobj)
     if not page.first:
         raise OggTheoraHeaderError(
             "page has ID header, but doesn't start a stream")
     data = page.packets[0]
     vmaj, vmin = struct.unpack("2B", data[7:9])
     if (vmaj, vmin) != (3, 2):
         raise OggTheoraHeaderError(
             "found Theora version %d.%d != 3.2" % (vmaj, vmin))
     fps_num, fps_den = struct.unpack(">2I", data[22:30])
     self.fps = fps_num / float(fps_den)
     self.bitrate = cdata.uint_be(b"\x00" + data[37:40])
     self.granule_shift = (cdata.ushort_be(data[40:42]) >> 5) & 0x1F
     self.serial = page.serial
Example #27
0
 def __parse_uint32(self, atom, data):
     self[atom.name] = [cdata.uint_be(value[1]) for
                        value in self.__parse_data(atom, data)]
Example #28
0
 def __parse_text(self, atom, data):
     flags = cdata.uint_be(data[8:12])
     if flags == 1:
         self[atom.name] = data[16:].decode('utf-8', 'replace')
Example #29
0
 def __parse_text(self, atom, data):
     flags = cdata.uint_be(data[8:12])
     if flags == 1:
         self[atom.name] = data[16:].decode('utf-8', 'replace')