Exemple #1
0
    def _parse_adif(self, fileobj):
        r = BitReader(fileobj)
        try:
            copyright_id_present = r.bits(1)
            if copyright_id_present:
                r.skip(72)  # copyright_id
            r.skip(1 + 1)  # original_copy, home
            bitstream_type = r.bits(1)
            self.bitrate = r.bits(23)
            npce = r.bits(4)
            if bitstream_type == 0:
                r.skip(20)  # adif_buffer_fullness

            pce = ProgramConfigElement(r)
            try:
                self.sample_rate = _FREQS[pce.sampling_frequency_index]
            except IndexError:
                pass
            self.channels = pce.channels

            # other pces..
            for i in xrange(npce):
                ProgramConfigElement(r)
            r.align()
        except BitReaderError as e:
            raise AACError(e)

        # use bitrate + data size to guess length
        start = fileobj.tell()
        fileobj.seek(0, 2)
        length = fileobj.tell() - start
        if self.bitrate != 0:
            self.length = (8.0 * length) / self.bitrate
    def _parse_adif(self, fileobj):
        r = BitReader(fileobj)
        try:
            copyright_id_present = r.bits(1)
            if copyright_id_present:
                r.skip(72)  # copyright_id
            r.skip(1 + 1)  # original_copy, home
            bitstream_type = r.bits(1)
            self.bitrate = r.bits(23)
            npce = r.bits(4)
            if bitstream_type == 0:
                r.skip(20)  # adif_buffer_fullness

            pce = ProgramConfigElement(r)
            try:
                self.sample_rate = _FREQS[pce.sampling_frequency_index]
            except IndexError:
                pass
            self.channels = pce.channels

            # other pces..
            for i in xrange(npce):
                ProgramConfigElement(r)
            r.align()
        except BitReaderError as e:
            raise AACError(e)

        # use bitrate + data size to guess length
        start = fileobj.tell()
        fileobj.seek(0, 2)
        length = fileobj.tell() - start
        if self.bitrate != 0:
            self.length = (8.0 * length) / self.bitrate
    def _parse_adts(self, fileobj, start_offset):
        max_initial_read = 512
        max_resync_read = 10
        max_sync_tries = 10

        frames_max = 100
        frames_needed = 3

        # Try up to X times to find a sync word and read up to Y frames.
        # If more than Z frames are valid we assume a valid stream
        offset = start_offset
        for i in xrange(max_sync_tries):
            fileobj.seek(offset)
            s = _ADTSStream.find_stream(fileobj, max_initial_read)
            if s is None:
                raise AACError("sync not found")
            # start right after the last found offset
            offset += s.offset + 1

            for i in xrange(frames_max):
                if not s.parse_frame():
                    break
                if not s.sync(max_resync_read):
                    break

            if s.parsed_frames >= frames_needed:
                break
        else:
            raise AACError("no valid stream found (only %d frames)" %
                           s.parsed_frames)

        self.sample_rate = s.frequency
        self.channels = s.channels
        self.bitrate = s.bitrate

        # size from stream start to end of file
        fileobj.seek(0, 2)
        stream_size = fileobj.tell() - (offset + s.offset)
        # approx
        self.length = float(s.samples * stream_size) / (s.size * s.frequency)
Exemple #4
0
    def _parse_adts(self, fileobj, start_offset):
        max_initial_read = 512
        max_resync_read = 10
        max_sync_tries = 10

        frames_max = 100
        frames_needed = 3

        # Try up to X times to find a sync word and read up to Y frames.
        # If more than Z frames are valid we assume a valid stream
        offset = start_offset
        for i in xrange(max_sync_tries):
            fileobj.seek(offset)
            s = _ADTSStream.find_stream(fileobj, max_initial_read)
            if s is None:
                raise AACError("sync not found")
            # start right after the last found offset
            offset += s.offset + 1

            for i in xrange(frames_max):
                if not s.parse_frame():
                    break
                if not s.sync(max_resync_read):
                    break

            if s.parsed_frames >= frames_needed:
                break
        else:
            raise AACError(
                "no valid stream found (only %d frames)" % s.parsed_frames)

        self.sample_rate = s.frequency
        self.channels = s.channels
        self.bitrate = s.bitrate

        # size from stream start to end of file
        fileobj.seek(0, 2)
        stream_size = fileobj.tell() - (offset + s.offset)
        # approx
        self.length = float(s.samples * stream_size) / (s.size * s.frequency)
Exemple #5
0
 def _key_sort(item):
     (key, v) = item
     # iTunes always writes the tags in order of "relevance", try
     # to copy it as closely as possible.
     order = ["\xa9nam", "\xa9ART", "\xa9wrt", "\xa9alb",
              "\xa9gen", "gnre", "trkn", "disk",
              "\xa9day", "cpil", "pgap", "pcst", "tmpo",
              "\xa9too", "----", "covr", "\xa9lyr"]
     order = dict(izip(order, xrange(len(order))))
     last = len(order)
     # If there's no key-based way to distinguish, order by length.
     # If there's still no way, go by string comparison on the
     # values, so we at least have something determinstic.
     return (order.get(key[:4], last), len(repr(v)), repr(v))
Exemple #6
0
    def parse_full(cls, asf, fileobj):
        """Raises ASFHeaderError"""

        header = cls()

        size, num_objects = cls.parse_size(fileobj)
        for i in xrange(num_objects):
            guid, size = struct.unpack("<16sQ", fileobj.read(24))
            obj = BaseObject._get_object(guid)
            data = fileobj.read(size - 24)
            obj.parse(asf, data)
            header.objects.append(obj)

        return header
Exemple #7
0
    def parse_full(cls, asf, fileobj):
        """Raises ASFHeaderError"""

        header = cls()

        size, num_objects = cls.parse_size(fileobj)
        for i in xrange(num_objects):
            guid, size = struct.unpack("<16sQ", fileobj.read(24))
            obj = BaseObject._get_object(guid)
            data = fileobj.read(size - 24)
            obj.parse(asf, data)
            header.objects.append(obj)

        return header
 def _key_sort(item):
     (key, v) = item
     # iTunes always writes the tags in order of "relevance", try
     # to copy it as closely as possible.
     order = [
         "\xa9nam", "\xa9ART", "\xa9wrt", "\xa9alb", "\xa9gen", "gnre",
         "trkn", "disk", "\xa9day", "cpil", "pgap", "pcst", "tmpo",
         "\xa9too", "----", "covr", "\xa9lyr"
     ]
     order = dict(izip(order, xrange(len(order))))
     last = len(order)
     # If there's no key-based way to distinguish, order by length.
     # If there's still no way, go by string comparison on the
     # values, so we at least have something determinstic.
     return (order.get(key[:4], last), len(repr(v)), repr(v))
Exemple #9
0
 def parse(self, asf, data):
     super(ExtendedContentDescriptionObject, self).parse(asf, data)
     num_attributes, = struct.unpack("<H", data[0:2])
     pos = 2
     for i in xrange(num_attributes):
         name_length, = struct.unpack("<H", data[pos:pos + 2])
         pos += 2
         name = data[pos:pos + name_length]
         name = name.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 = ASFBaseAttribute._get_type(value_type)(data=value)
         asf._tags.setdefault(self.GUID, []).append((name, attr))
Exemple #10
0
 def parse(self, asf, data):
     super(ExtendedContentDescriptionObject, self).parse(asf, data)
     num_attributes, = struct.unpack("<H", data[0:2])
     pos = 2
     for i in xrange(num_attributes):
         name_length, = struct.unpack("<H", data[pos:pos + 2])
         pos += 2
         name = data[pos:pos + name_length]
         name = name.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 = ASFBaseAttribute._get_type(value_type)(data=value)
         asf._tags.setdefault(self.GUID, []).append((name, attr))
Exemple #11
0
    def _parse_desc_length_file(cls, fileobj):
        """May raise ValueError"""

        value = 0
        for i in xrange(4):
            try:
                b = cdata.uint8(fileobj.read(1))
            except cdata.error as e:
                raise ValueError(e)
            value = (value << 7) | (b & 0x7f)
            if not b >> 7:
                break
        else:
            raise ValueError("invalid descriptor length")

        return value
Exemple #12
0
    def _parse_desc_length_file(cls, fileobj):
        """May raise ValueError"""

        value = 0
        for i in xrange(4):
            try:
                b = cdata.uint8(fileobj.read(1))
            except cdata.error as e:
                raise ValueError(e)
            value = (value << 7) | (b & 0x7f)
            if not b >> 7:
                break
        else:
            raise ValueError("invalid descriptor length")

        return value
Exemple #13
0
 def parse(self, asf, data):
     super(MetadataLibraryObject, self).parse(asf, data)
     num_attributes, = struct.unpack("<H", data[0:2])
     pos = 2
     for i in xrange(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]
         name = name.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 = ASFBaseAttribute._get_type(value_type)(**args)
         asf._tags.setdefault(self.GUID, []).append((name, attr))
Exemple #14
0
 def parse(self, asf, data):
     super(MetadataLibraryObject, self).parse(asf, data)
     num_attributes, = struct.unpack("<H", data[0:2])
     pos = 2
     for i in xrange(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]
         name = name.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 = ASFBaseAttribute._get_type(value_type)(**args)
         asf._tags.setdefault(self.GUID, []).append((name, attr))
Exemple #15
0
    def __init__(self, r):
        """Reads the program_config_element()

        Raises BitReaderError
        """

        self.element_instance_tag = r.bits(4)
        self.object_type = r.bits(2)
        self.sampling_frequency_index = r.bits(4)
        num_front_channel_elements = r.bits(4)
        num_side_channel_elements = r.bits(4)
        num_back_channel_elements = r.bits(4)
        num_lfe_channel_elements = r.bits(2)
        num_assoc_data_elements = r.bits(3)
        num_valid_cc_elements = r.bits(4)

        mono_mixdown_present = r.bits(1)
        if mono_mixdown_present == 1:
            r.skip(4)
        stereo_mixdown_present = r.bits(1)
        if stereo_mixdown_present == 1:
            r.skip(4)
        matrix_mixdown_idx_present = r.bits(1)
        if matrix_mixdown_idx_present == 1:
            r.skip(3)

        elms = num_front_channel_elements + num_side_channel_elements + \
            num_back_channel_elements
        channels = 0
        for i in xrange(elms):
            channels += 1
            element_is_cpe = r.bits(1)
            if element_is_cpe:
                channels += 1
            r.skip(4)
        channels += num_lfe_channel_elements
        self.channels = channels

        r.skip(4 * num_lfe_channel_elements)
        r.skip(4 * num_assoc_data_elements)
        r.skip(5 * num_valid_cc_elements)
        r.align()
        comment_field_bytes = r.bits(8)
        r.skip(8 * comment_field_bytes)
    def __init__(self, r):
        """Reads the program_config_element()

        Raises BitReaderError
        """

        self.element_instance_tag = r.bits(4)
        self.object_type = r.bits(2)
        self.sampling_frequency_index = r.bits(4)
        num_front_channel_elements = r.bits(4)
        num_side_channel_elements = r.bits(4)
        num_back_channel_elements = r.bits(4)
        num_lfe_channel_elements = r.bits(2)
        num_assoc_data_elements = r.bits(3)
        num_valid_cc_elements = r.bits(4)

        mono_mixdown_present = r.bits(1)
        if mono_mixdown_present == 1:
            r.skip(4)
        stereo_mixdown_present = r.bits(1)
        if stereo_mixdown_present == 1:
            r.skip(4)
        matrix_mixdown_idx_present = r.bits(1)
        if matrix_mixdown_idx_present == 1:
            r.skip(3)

        elms = num_front_channel_elements + num_side_channel_elements + \
            num_back_channel_elements
        channels = 0
        for i in xrange(elms):
            channels += 1
            element_is_cpe = r.bits(1)
            if element_is_cpe:
                channels += 1
            r.skip(4)
        channels += num_lfe_channel_elements
        self.channels = channels

        r.skip(4 * num_lfe_channel_elements)
        r.skip(4 * num_assoc_data_elements)
        r.skip(5 * num_valid_cc_elements)
        r.align()
        comment_field_bytes = r.bits(8)
        r.skip(8 * comment_field_bytes)
Exemple #17
0
    def parse(self, asf, data):
        super(CodecListObject, self).parse(asf, data)

        offset = 16
        count, offset = cdata.uint32_le_from(data, offset)
        for i in xrange(count):
            try:
                offset, type_, name, desc, codec = \
                    self._parse_entry(data, offset)
            except cdata.error:
                raise ASFError("invalid codec entry")

            # go with the first audio entry
            if type_ == 2:
                name = name.strip()
                desc = desc.strip()
                asf.info.codec_type = codec
                asf.info.codec_name = name
                asf.info.codec_description = desc
                return
Exemple #18
0
    def parse(self, asf, data):
        super(CodecListObject, self).parse(asf, data)

        offset = 16
        count, offset = cdata.uint32_le_from(data, offset)
        for i in xrange(count):
            try:
                offset, type_, name, desc, codec = \
                    self._parse_entry(data, offset)
            except cdata.error:
                raise ASFError("invalid codec entry")

            # go with the first audio entry
            if type_ == 2:
                name = name.strip()
                desc = desc.strip()
                asf.info.codec_type = codec
                asf.info.codec_name = name
                asf.info.codec_description = desc
                return