Пример #1
0
 def __init__(self, fileobj):
     header = fileobj.read(76)
     if len(header) != 76 or not header.startswith(b"MAC "):
         raise MonkeysAudioHeaderError("not a Monkey's Audio file")
     self.version = cdata.ushort_le(header[4:6])
     if self.version >= 3980:
         (blocks_per_frame, final_frame_blocks, total_frames,
          self.bits_per_sample, self.channels,
          self.sample_rate) = struct_unpack("<IIIHHI", header[56:76])
     else:
         compression_level = cdata.ushort_le(header[6:8])
         self.channels, self.sample_rate = struct_unpack(
             "<HI", header[10:16])
         total_frames, final_frame_blocks = struct_unpack(
             "<II", header[24:32])
         if self.version >= 3950:
             blocks_per_frame = 73728 * 4
         elif self.version >= 3900 or (self.version >= 3800 and
                                       compression_level == 4):
             blocks_per_frame = 73728
         else:
             blocks_per_frame = 9216
     self.version /= 1000.0
     self.length = 0.0
     if self.sample_rate != 0 and total_frames > 0:
         total_blocks = ((total_frames - 1) * blocks_per_frame +
                         final_frame_blocks)
         self.length = float(total_blocks) / self.sample_rate
Пример #2
0
 def __init__(self, fileobj):
     header = fileobj.read(76)
     if len(header) != 76 or not header.startswith(b"MAC "):
         raise MonkeysAudioHeaderError("not a Monkey's Audio file")
     self.version = cdata.ushort_le(header[4:6])
     if self.version >= 3980:
         (blocks_per_frame, final_frame_blocks, total_frames,
          self.bits_per_sample, self.channels,
          self.sample_rate) = struct_unpack("<IIIHHI", header[56:76])
     else:
         compression_level = cdata.ushort_le(header[6:8])
         self.channels, self.sample_rate = struct_unpack(
             "<HI", header[10:16])
         total_frames, final_frame_blocks = struct_unpack(
             "<II", header[24:32])
         if self.version >= 3950:
             blocks_per_frame = 73728 * 4
         elif self.version >= 3900 or (self.version >= 3800
                                       and compression_level == 4):
             blocks_per_frame = 73728
         else:
             blocks_per_frame = 9216
     self.version /= 1000.0
     self.length = 0.0
     if self.sample_rate != 0 and total_frames > 0:
         total_blocks = ((total_frames - 1) * blocks_per_frame +
                         final_frame_blocks)
         self.length = float(total_blocks) / self.sample_rate
Пример #3
0
 def __read_offsets(self, filename):
     fileobj = open(filename, 'rb')
     atoms = Atoms(fileobj)
     moov = atoms['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["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
Пример #4
0
 def load(self, data):
     self.type, length = struct_unpack('>2I', data.read(8))
     self.mime = data.read(length).decode('UTF-8', 'replace')
     length, = struct_unpack('>I', data.read(4))
     self.desc = data.read(length).decode('UTF-8', 'replace')
     (self.width, self.height, self.depth,
      self.colors, length) = struct_unpack('>5I', data.read(20))
     self.data = data.read(length)
Пример #5
0
 def load(self, data):
     self.type, length = struct_unpack('>2I', data.read(8))
     self.mime = data.read(length).decode('UTF-8', 'replace')
     length, = struct_unpack('>I', data.read(4))
     self.desc = data.read(length).decode('UTF-8', 'replace')
     (self.width, self.height, self.depth, self.colors,
      length) = struct_unpack('>5I', data.read(20))
     self.data = data.read(length)
Пример #6
0
    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
Пример #7
0
 def __init__(self, fileobj):
     header = fileobj.read(76)
     if (len(header) != 76 or not header.startswith(b"OFR ") or
         struct_unpack("<I", header[4:8])[0] not in [12, 15]):
         raise OptimFROGHeaderError("not an OptimFROG file")
     (total_samples, total_samples_high, sample_type, self.channels,
      self.sample_rate) = struct_unpack("<IHBBI", header[8:20])
     total_samples += total_samples_high << 32
     self.channels += 1
     if self.sample_rate:
         self.length = float(total_samples) / (self.channels * 
                                               self.sample_rate)
     else:
         self.length = 0.0
Пример #8
0
    def __init__(self, fileobj):
        header = bytearray(fileobj.read(32))
        if len(header) != 32:
            raise MusepackHeaderError("not a Musepack file")
        # Skip ID3v2 tags
        if header[:3] == b"ID3":
            size = 10 + BitPaddedInt(header[6:10])
            fileobj.seek(size)
            header = bytearray(fileobj.read(32))
            if len(header) != 32:
                raise MusepackHeaderError("not a Musepack file")
        # SV7
        if header.startswith(b"MP+"):
            self.version = header[3] & 0xF
            if self.version < 7:
                raise MusepackHeaderError("not a Musepack file")
            frames = cdata.uint_le(header[4:8])
            flags = cdata.uint_le(header[8:12])

            self.title_peak, self.title_gain = struct_unpack(
                "<Hh", header[12:16])
            self.album_peak, self.album_gain = struct_unpack(
                "<Hh", header[16:20])
            self.title_gain /= 100.0
            self.album_gain /= 100.0
            self.title_peak /= 65535.0
            self.album_peak /= 65535.0

            self.sample_rate = RATES[(flags >> 16) & 0x0003]
            self.bitrate = 0
        # SV4-SV6
        else:
            header_dword = cdata.uint_le(header[0:4])
            self.version = (header_dword >> 11) & 0x03FF;
            if self.version < 4 or self.version > 6:
                raise MusepackHeaderError("not a Musepack file")
            self.bitrate = (header_dword >> 23) & 0x01FF;
            self.sample_rate = 44100
            if self.version >= 5:
                frames = cdata.uint_le(header[4:8])
            else:
                frames = cdata.ushort_le(header[6:8])
            if self.version < 6:
                frames -= 1
        self.channels = 2
        self.length = float(frames * 1152 - 576) / self.sample_rate
        if not self.bitrate and self.length != 0:
            fileobj.seek(0, 2)
            self.bitrate = int(fileobj.tell() * 8 / (self.length * 1000) + 0.5)
Пример #9
0
    def __init__(self, fileobj):
        header = bytearray(fileobj.read(32))
        if len(header) != 32:
            raise MusepackHeaderError("not a Musepack file")
        # Skip ID3v2 tags
        if header[:3] == b"ID3":
            size = 10 + BitPaddedInt(header[6:10])
            fileobj.seek(size)
            header = bytearray(fileobj.read(32))
            if len(header) != 32:
                raise MusepackHeaderError("not a Musepack file")
        # SV7
        if header.startswith(b"MP+"):
            self.version = header[3] & 0xF
            if self.version < 7:
                raise MusepackHeaderError("not a Musepack file")
            frames = cdata.uint_le(header[4:8])
            flags = cdata.uint_le(header[8:12])

            self.title_peak, self.title_gain = struct_unpack(
                "<Hh", header[12:16])
            self.album_peak, self.album_gain = struct_unpack(
                "<Hh", header[16:20])
            self.title_gain /= 100.0
            self.album_gain /= 100.0
            self.title_peak /= 65535.0
            self.album_peak /= 65535.0

            self.sample_rate = RATES[(flags >> 16) & 0x0003]
            self.bitrate = 0
        # SV4-SV6
        else:
            header_dword = cdata.uint_le(header[0:4])
            self.version = (header_dword >> 11) & 0x03FF
            if self.version < 4 or self.version > 6:
                raise MusepackHeaderError("not a Musepack file")
            self.bitrate = (header_dword >> 23) & 0x01FF
            self.sample_rate = 44100
            if self.version >= 5:
                frames = cdata.uint_le(header[4:8])
            else:
                frames = cdata.ushort_le(header[6:8])
            if self.version < 6:
                frames -= 1
        self.channels = 2
        self.length = float(frames * 1152 - 576) / self.sample_rate
        if not self.bitrate and self.length != 0:
            fileobj.seek(0, 2)
            self.bitrate = int(fileobj.tell() * 8 / (self.length * 1000) + 0.5)
Пример #10
0
 def parse(self, asf, data, fileobj, size):
     super(HeaderExtensionObject, self).parse(asf, data, fileobj, size)
     asf.header_extension_obj = self
     datasize, = struct_unpack("<I", data[18:22])
     datapos = 0
     self.objects = []
     while datapos < datasize:
         guid, size = struct_unpack("<16sQ", data[22+datapos:22+datapos+24])
         if guid in _object_types:
             obj = _object_types[guid]()
         else:
             obj = UnknownObject(guid)
         obj.parse(asf, data[22+datapos+24:22+datapos+size], fileobj, size)
         self.objects.append(obj)
         datapos += size
Пример #11
0
    def __init__(self, fileobj):
        self.offset = fileobj.tell()
        self.length, self.name = struct_unpack(">I4s", fileobj.read(8))
        if self.length == 1:
            self.length, = struct_unpack(">Q", fileobj.read(8))
        elif self.length < 8:
            return

        if self.name in _CONTAINERS:
            self.children = []
            fileobj.seek(_SKIP_SIZE.get(self.name, 0), 1)
            while fileobj.tell() < self.offset + self.length:
                self.children.append(Atom(fileobj))
        else:
            fileobj.seek(self.offset + self.length, 0)
Пример #12
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 = struct_unpack(">I", data[37:40] + b"\x00")[0]
     self.serial = page.serial
Пример #13
0
 def parse(self, asf, data, fileobj, size):
     super(ExtendedContentDescriptionObject, self).parse(asf, data, fileobj, size)
     asf.extended_content_description_obj = self
     num_attributes, = struct_unpack("<H", data[0:2])
     pos = 2
     for i in range(num_attributes):
         name_length, = struct_unpack("<H", data[pos:pos+2])
         pos += 2
         name = data[pos:pos+name_length].decode("utf-16-le").strip("\x00")
         pos += name_length
         value_type, value_length = struct_unpack("<HH", data[pos:pos+4])
         pos += 4
         value = data[pos:pos+value_length]
         pos += value_length
         attr = _attribute_types[value_type](data=value)
         asf.tags.append((name, attr))
Пример #14
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 = struct_unpack(">I", data[37:40] + b"\x00")[0]
     self.serial = page.serial
Пример #15
0
 def load(self, data):
     self.seekpoints = []
     sp = data.read(self.__SEEKPOINT_SIZE)
     while len(sp) == self.__SEEKPOINT_SIZE:
         self.seekpoints.append(
             SeekPoint(*struct_unpack(self.__SEEKPOINT_FORMAT, sp)))
         sp = data.read(self.__SEEKPOINT_SIZE)
Пример #16
0
    def __init__(self, fileobj):
        page = OggPage(fileobj)
        while not page.packets[0].startswith(b"\x01vorbis"):
            page = OggPage(fileobj)
        if not page.first:
            raise OggVorbisHeaderError(
                "page has ID header, but doesn't start a stream")
        (self.channels, self.sample_rate, max_bitrate, nominal_bitrate,
         min_bitrate) = struct_unpack("<B4i", page.packets[0][11:28])
        self.serial = page.serial

        max_bitrate = max(0, max_bitrate)
        min_bitrate = max(0, min_bitrate)
        nominal_bitrate = max(0, nominal_bitrate)

        if nominal_bitrate == 0:
            self.bitrate = (max_bitrate + min_bitrate) // 2
        elif max_bitrate and max_bitrate < nominal_bitrate:
            # If the max bitrate is less than the nominal, we know
            # the nominal is wrong.
            self.bitrate = max_bitrate
        elif min_bitrate > nominal_bitrate:
            self.bitrate = min_bitrate
        else:
            self.bitrate = nominal_bitrate

        if self.bitrate == 0 and self.length > 0:
            fileobj.seek(0, 2)
            self.bitrate = int((fileobj.tell() * 8) / self.length)
Пример #17
0
 def load(self, data):
     self.seekpoints = []
     sp = data.read(self.__SEEKPOINT_SIZE)
     while len(sp) == self.__SEEKPOINT_SIZE:
         self.seekpoints.append(SeekPoint(
             *struct_unpack(self.__SEEKPOINT_FORMAT, sp)))
         sp = data.read(self.__SEEKPOINT_SIZE)
Пример #18
0
    def __init__(self, atoms, fileobj):
        hdlr = atoms["moov.trak.mdia.hdlr"]
        fileobj.seek(hdlr.offset)
        if b"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 = 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 = 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
Пример #19
0
 def __parse_cover(self, atom, data):
     length, name, imageformat = struct_unpack(">I4sI", data[:12])
     if name != b"data":
         raise M4AMetadataError(
             "unexpected atom %r inside 'covr'" % name)
     if imageformat not in (M4ACover.FORMAT_JPEG, M4ACover.FORMAT_PNG):
         imageformat = M4ACover.FORMAT_JPEG
     self[atom.name]= M4ACover(data[16:length], imageformat)
Пример #20
0
 def parse(self, asf, data, fileobj, size):
     super(MetadataLibraryObject, self).parse(asf, data, fileobj, size)
     asf.metadata_library_obj = self
     num_attributes, = struct_unpack("<H", data[0:2])
     pos = 2
     for i in range(num_attributes):
         (language, stream, name_length, value_type,
          value_length) = struct_unpack("<HHHHI", data[pos:pos+12])
         pos += 12
         name = data[pos:pos+name_length].decode("utf-16-le").strip("\x00")
         pos += name_length
         value = data[pos:pos+value_length]
         pos += value_length
         args = {'data': value, 'language': language, 'stream': stream}
         if value_type == 2:
             args['dword'] = False
         attr = _attribute_types[value_type](**args)
         asf.tags.append((name, attr))
Пример #21
0
 def __parse_data(self, atom, data):
     pos = 0
     while pos < atom.length - 8:
         length, name, flags = struct_unpack(">I4sI", data[pos:pos+12])
         if name != b"data":
             raise MP4MetadataError(
                 "unexpected atom %r inside %r" % (name, atom.name))
         yield flags, data[pos+16:pos+length]
         pos += length
Пример #22
0
 def __read_object(self, fileobj):
     guid, size = struct_unpack("<16sQ", fileobj.read(24))
     if guid in _object_types:
         obj = _object_types[guid]()
     else:
         obj = UnknownObject(guid)
     data = fileobj.read(size - 24)
     obj.parse(self, data, fileobj, size)
     self.objects.append(obj)
Пример #23
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))
Пример #24
0
    def __read_file(self, fileobj):
        header = fileobj.read(30)
        if len(header) != 30 or header[:16] != HeaderObject.GUID:
            raise ASFHeaderError("Not an ASF file.")

        self.extended_content_description_obj = None
        self.content_description_obj = None
        self.header_extension_obj = None
        self.metadata_obj = None
        self.metadata_library_obj = None

        self.size, self.num_objects = struct_unpack("<QL", header[16:28])
        self.objects = []
        for i in range(self.num_objects):
            self.__read_object(fileobj)
Пример #25
0
 def load(self, data):
     header = data.read(self.__CUESHEET_SIZE)
     media_catalog_number, lead_in_samples, flags, num_tracks = \
         struct_unpack(self.__CUESHEET_FORMAT, header)
     self.media_catalog_number = media_catalog_number.rstrip(b'\0')
     self.lead_in_samples = lead_in_samples
     self.compact_disc = bool(flags & 0x80)
     self.tracks = []
     for i in range(num_tracks):
         track = data.read(self.__CUESHEET_TRACK_SIZE)
         start_offset, track_number, isrc_padded, flags, num_indexes = \
             struct_unpack(self.__CUESHEET_TRACK_FORMAT, track)
         isrc = isrc_padded.rstrip(b'\0')
         type_ = (flags & 0x80) >> 7
         pre_emphasis = bool(flags & 0x40)
         val = CueSheetTrack(track_number, start_offset, isrc, type_,
                             pre_emphasis)
         for j in range(num_indexes):
             index = data.read(self.__CUESHEET_TRACKINDEX_SIZE)
             index_offset, index_number = struct_unpack(
                 self.__CUESHEET_TRACKINDEX_FORMAT, index)
             val.indexes.append(
                 CueSheetTrackIndex(index_number, index_offset))
         self.tracks.append(val)
Пример #26
0
 def load(self, data):
     header = data.read(self.__CUESHEET_SIZE)
     media_catalog_number, lead_in_samples, flags, num_tracks = \
         struct_unpack(self.__CUESHEET_FORMAT, header)
     self.media_catalog_number = media_catalog_number.rstrip(b'\0')
     self.lead_in_samples = lead_in_samples
     self.compact_disc = bool(flags & 0x80)
     self.tracks = []
     for i in range(num_tracks): 
         track = data.read(self.__CUESHEET_TRACK_SIZE)
         start_offset, track_number, isrc_padded, flags, num_indexes = \
             struct_unpack(self.__CUESHEET_TRACK_FORMAT, track)
         isrc = isrc_padded.rstrip(b'\0')
         type_ = (flags & 0x80) >> 7
         pre_emphasis = bool(flags & 0x40)
         val = CueSheetTrack(
             track_number, start_offset, isrc, type_, pre_emphasis)
         for j in range(num_indexes):
             index = data.read(self.__CUESHEET_TRACKINDEX_SIZE)
             index_offset, index_number = struct_unpack(
                 self.__CUESHEET_TRACKINDEX_FORMAT, index)
             val.indexes.append(
                 CueSheetTrackIndex(index_number, index_offset))
         self.tracks.append(val)
Пример #27
0
    def load(self, data):
        page = OggPage(data)
        while not page.packets[0].startswith(b"\x7FFLAC"):
            page = OggPage(data)
        major, minor, self.packets, flac = struct_unpack(
            ">BBH4s", page.packets[0][5:13])
        if flac != b"fLaC":
            raise OggFLACHeaderError("invalid FLAC marker (%r)" % flac)
        elif (major, minor) != (1, 0):
            raise OggFLACHeaderError("unknown mapping version: %d.%d" %
                                     (major, minor))
        self.serial = page.serial

        # Skip over the block header.
        stringobj = BytesIO(page.packets[0][17:])
        super(OggFLACStreamInfo, self).load(stringobj)
Пример #28
0
 def __parse_cover(self, atom, data):
     self[atom.name] = []
     pos = 0
     while pos < atom.length - 8:
         length, name, imageformat = struct_unpack(">I4sI", data[pos:pos+12])
         if name != b"data":
             if name == b"name":
                 pos += length
                 continue
             raise MP4MetadataError(
                 "unexpected atom %r inside b'covr'" % name)
         if imageformat not in (MP4Cover.FORMAT_JPEG, MP4Cover.FORMAT_PNG):
             imageformat = MP4Cover.FORMAT_JPEG
         cover = MP4Cover(data[pos+16:pos+length], imageformat)
         self[atom.name].append(cover)
         pos += length
Пример #29
0
    def load(self, data):
        page = OggPage(data)
        while not page.packets[0].startswith(b"\x7FFLAC"):
            page = OggPage(data)
        major, minor, self.packets, flac = struct_unpack(
            ">BBH4s", page.packets[0][5:13])
        if flac != b"fLaC":
            raise OggFLACHeaderError("invalid FLAC marker (%r)" % flac)
        elif (major, minor) != (1, 0):
            raise OggFLACHeaderError(
                "unknown mapping version: %d.%d" % (major, minor))
        self.serial = page.serial

        # Skip over the block header.
        stringobj = BytesIO(page.packets[0][17:])
        super(OggFLACStreamInfo, self).load(stringobj)
Пример #30
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))
         value.append(data[pos+16:pos+length])
         pos += length
     if value:
         self[atom.name + b":" + mean + b":" + name] = value
Пример #31
0
    def __init__(self, fileobj, offset=None):
        """Parse MPEG stream information from a file-like object.

        If an offset argument is given, it is used to start looking
        for stream information and Xing headers; otherwise, ID3v2 tags
        will be skipped automatically. A correct offset can make
        loading files significantly faster.
        """

        try:
            size = os.path.getsize(fileobj.name)
        except (IOError, OSError, AttributeError):
            fileobj.seek(0, 2)
            size = fileobj.tell()

        # If we don't get an offset, try to skip an ID3v2 tag.
        if offset is None:
            fileobj.seek(0, 0)
            idata = fileobj.read(10)
            try:
                id3, insize = struct_unpack('>3sxxx4s', idata)
            except struct_error:
                id3, insize = '', 0
            insize = BitPaddedInt(insize)
            if id3 == b'ID3' and insize > 0:
                offset = insize
            else:
                offset = 0

        # Try to find two valid headers (meaning, very likely MPEG data)
        # at the given offset, 30% through the file, 60% through the file,
        # and 90% through the file.
        for i in [offset, 0.3 * size, 0.6 * size, 0.9 * size]:
            try:
                self.__try(fileobj, int(i), size - offset)
            except error:
                pass
            else:
                break
        # If we can't find any two consecutive frames, try to find just
        # one frame back at the original offset given.
        else:
            self.__try(fileobj, offset, size - offset, False)
            self.sketchy = True
Пример #32
0
    def __init__(self, fileobj, offset=None):
        """Parse MPEG stream information from a file-like object.

        If an offset argument is given, it is used to start looking
        for stream information and Xing headers; otherwise, ID3v2 tags
        will be skipped automatically. A correct offset can make
        loading files significantly faster.
        """

        try:
            size = os.path.getsize(fileobj.name)
        except (IOError, OSError, AttributeError):
            fileobj.seek(0, 2)
            size = fileobj.tell()

        # If we don't get an offset, try to skip an ID3v2 tag.
        if offset is None:
            fileobj.seek(0, 0)
            idata = fileobj.read(10)
            try:
                id3, insize = struct_unpack(">3sxxx4s", idata)
            except struct_error:
                id3, insize = "", 0
            insize = BitPaddedInt(insize)
            if id3 == b"ID3" and insize > 0:
                offset = insize
            else:
                offset = 0

        # Try to find two valid headers (meaning, very likely MPEG data)
        # at the given offset, 30% through the file, 60% through the file,
        # and 90% through the file.
        for i in [offset, 0.3 * size, 0.6 * size, 0.9 * size]:
            try:
                self.__try(fileobj, int(i), size - offset)
            except error:
                pass
            else:
                break
        # If we can't find any two consecutive frames, try to find just
        # one frame back at the original offset given.
        else:
            self.__try(fileobj, offset, size - offset, False)
            self.sketchy = True
Пример #33
0
    def __init__(self, fileobj=None):
        self.packets = []

        if fileobj is None:
            return

        self.offset = fileobj.tell()

        header = fileobj.read(27)
        if len(header) == 0:
            raise EOFError

        try:
            (oggs, self.version, self.__type_flags, self.position, self.serial,
             self.sequence, crc,
             segments) = struct_unpack("<4sBBqIIiB", header)
        except struct_error:
            raise error("unable to read full header; got %r" % header)

        if oggs != b"OggS":
            raise error("read %r, expected %r, at 0x%x" %
                        (oggs, b"OggS", fileobj.tell() - 27))

        if self.version != 0:
            raise error("version %r unsupported" % self.version)

        total = 0
        lacings = []
        lacing_bytes = bytearray(fileobj.read(segments))
        if len(lacing_bytes) != segments:
            raise error("unable to read %r lacing bytes" % segments)
        for c in lacing_bytes:
            total += c
            if c < 255:
                lacings.append(total)
                total = 0
        if total:
            lacings.append(total)
            self.complete = False

        self.packets = list(map(fileobj.read, lacings))
        if list(map(len, self.packets)) != lacings:
            raise error("unable to read full data")
Пример #34
0
    def __init__(self, fileobj=None):
        self.packets = []

        if fileobj is None:
            return

        self.offset = fileobj.tell()

        header = fileobj.read(27)
        if len(header) == 0:
            raise EOFError

        try:
            (oggs, self.version, self.__type_flags, self.position,
             self.serial, self.sequence, crc, segments) = struct_unpack(
                "<4sBBqIIiB", header)
        except struct_error:
            raise error("unable to read full header; got %r" % header)

        if oggs != b"OggS":
            raise error("read %r, expected %r, at 0x%x" % (
                oggs, b"OggS", fileobj.tell() - 27))

        if self.version != 0:
            raise error("version %r unsupported" % self.version)

        total = 0
        lacings = []
        lacing_bytes = bytearray(fileobj.read(segments))
        if len(lacing_bytes) != segments:
            raise error("unable to read %r lacing bytes" % segments)
        for c in lacing_bytes:
            total += c
            if c < 255:
                lacings.append(total)
                total = 0
        if total:
            lacings.append(total)
            self.complete = False

        self.packets = list(map(fileobj.read, lacings))
        if list(map(len, self.packets)) != lacings:
            raise error("unable to read full data")
Пример #35
0
 def parse(self, asf, data, fileobj, size):
     super(ContentDescriptionObject, self).parse(asf, data, fileobj, size)
     asf.content_description_obj = self
     lengths = struct_unpack("<HHHHH", data[:10])
     texts = []
     pos = 10
     for length in lengths:
         end = pos + length
         if length > 0:
             texts.append(data[pos:end].decode("utf-16-le").strip("\x00"))
         else:
             texts.append(None)
         pos = end
     title, author, copyright, desc, rating = texts
     for key, value in list(dict(
         Title=title,
         Author=author,
         Copyright=copyright,
         Description=desc,
         Rating=rating).items()):
         if value is not None:
             asf.tags[key] = value
Пример #36
0
 def parse(self, asf, data, fileobj, size):
     super(StreamPropertiesObject, self).parse(asf, data, fileobj, size)
     channels, sample_rate, bitrate = struct_unpack("<HII", data[56:66])
     asf.info.channels = channels
     asf.info.sample_rate = sample_rate
     asf.info.bitrate = bitrate * 8
Пример #37
0
 def parse(self, asf, data, fileobj, size):
     super(FilePropertiesObject, self).parse(asf, data, fileobj, size)
     length, _, preroll = struct_unpack("<QQQ", data[40:64])
     asf.info.length = length / 10000000.0 - preroll / 1000.0
Пример #38
0
 def __parse_pair(self, atom, data):
     self[atom.name] = [struct_unpack(">2H", data[2:6]) for
                        flags, data in self.__parse_data(atom, data)]
Пример #39
0
 def parse(self, data):
     return struct_unpack("<H", data)[0]
Пример #40
0
    def __try(self, fileobj, offset, real_size, check_second=True):
        # This is going to be one really long function; bear with it,
        # because there's not really a sane point to cut it up.
        fileobj.seek(offset, 0)

        # We "know" we have an MPEG file if we find two frames that look like
        # valid MPEG data. If we can't find them in 32k of reads, something
        # is horribly wrong (the longest frame can only be about 4k). This
        # is assuming the offset didn't lie.
        data = fileobj.read(32768)

        frame_1 = data.find(b"\xff")
        while 0 <= frame_1 <= len(data) - 4:
            frame_data = struct_unpack(">I", data[frame_1:frame_1 + 4])[0]
            if (frame_data >> 16) & 0xE0 != 0xE0:
                frame_1 = data.find(b"\xff", frame_1 + 2)
            else:
                version = (frame_data >> 19) & 0x3
                layer = (frame_data >> 17) & 0x3
                protection = (frame_data >> 16) & 0x1
                bitrate = (frame_data >> 12) & 0xF
                sample_rate = (frame_data >> 10) & 0x3
                padding = (frame_data >> 9) & 0x1
                private = (frame_data >> 8) & 0x1
                self.mode = (frame_data >> 6) & 0x3
                mode_extension = (frame_data >> 4) & 0x3
                copyright = (frame_data >> 3) & 0x1
                original = (frame_data >> 2) & 0x1
                emphasis = (frame_data >> 0) & 0x3
                # remove unused variables
                del private, mode_extension, copyright, original, emphasis
                if (version == 1 or layer == 0 or sample_rate == 0x3
                        or bitrate == 0 or bitrate == 0xF):
                    frame_1 = data.find(b"\xff", frame_1 + 2)
                else:
                    break
        else:
            raise HeaderNotFoundError("can't sync to an MPEG frame")

        # There is a serious problem here, which is that many flags
        # in an MPEG header are backwards.
        self.version = [2.5, None, 2, 1][version]
        self.layer = 4 - layer
        self.protected = not protection
        self.padding = bool(padding)

        self.bitrate = self.__BITRATE[(self.version, self.layer)][bitrate]
        self.bitrate *= 1000
        self.sample_rate = self.__RATES[self.version][sample_rate]

        if self.layer == 1:
            frame_length = (12 * self.bitrate // self.sample_rate +
                            padding) * 4
            frame_size = 384
        elif self.version >= 2 and self.layer == 3:
            frame_length = 72 * self.bitrate // self.sample_rate + padding
            frame_size = 576
        else:
            frame_length = 144 * self.bitrate // self.sample_rate + padding
            frame_size = 1152

        if check_second:
            possible = frame_1 + frame_length
            if possible > len(data) + 4:
                raise HeaderNotFoundError("can't sync to second MPEG frame")
            try:
                frame_data = struct_unpack(">H",
                                           data[possible:possible + 2])[0]
            except struct_error:
                raise HeaderNotFoundError("can't sync to second MPEG frame")
            if frame_data & 0xFFE0 != 0xFFE0:
                raise HeaderNotFoundError("can't sync to second MPEG frame")

        frame_count = real_size / frame_length
        samples = frame_size * frame_count
        self.length = samples / self.sample_rate

        # Try to find/parse the Xing header, which trumps the above length
        # and bitrate calculation.
        fileobj.seek(offset, 0)
        data = fileobj.read(32768)
        try:
            xing = data[:-4].index(b"Xing")
        except ValueError:
            # Try to find/parse the VBRI header, which trumps the above length
            # calculation.
            try:
                vbri = data[:-24].index(b"VBRI")
            except ValueError:
                pass
            else:
                # If a VBRI header was found, this is definitely MPEG audio.
                self.sketchy = False
                vbri_version = struct_unpack('>H', data[vbri + 4:vbri + 6])[0]
                if vbri_version == 1:
                    frame_count = struct_unpack('>I',
                                                data[vbri + 14:vbri + 18])[0]
                    samples = frame_size * frame_count
                    self.length = (samples / self.sample_rate) or self.length
        else:
            # If a Xing header was found, this is definitely MPEG audio.
            self.sketchy = False
            flags = struct_unpack('>I', data[xing + 4:xing + 8])[0]
            if flags & 0x1:
                frame_count = struct_unpack('>I', data[xing + 8:xing + 12])[0]
                samples = frame_size * frame_count
                self.length = (samples / self.sample_rate) or self.length
            if flags & 0x2:
                byte = struct_unpack('>I', data[xing + 12:xing + 16])[0]
                self.bitrate = int((byte * 8) // self.length)

        # If the bitrate * the length is nowhere near the file
        # length, recalculate using the bitrate and file length.
        # Don't do this for very small files.
        fileobj.seek(2, 0)
        size = fileobj.tell()
        expected = (self.bitrate // 8) * self.length
        if not (size // 2 < expected < size * 2) and size > 2**16:
            self.length = size / (self.bitrate * 8)