Example #1
0
    def test_is_aligned(self):
        r = BitReader(BytesIO(b"\xAB\xCD\xEF"))
        self.assertTrue(r.is_aligned())

        r.skip(1)
        self.assertFalse(r.is_aligned())
        r.skip(7)
        self.assertTrue(r.is_aligned())

        r.bits(7)
        self.assertFalse(r.is_aligned())
        r.bits(1)
        self.assertTrue(r.is_aligned())
Example #2
0
    def test_is_aligned(self):
        r = BitReader(cBytesIO(b"\xAB\xCD\xEF"))
        self.assertTrue(r.is_aligned())

        r.skip(1)
        self.assertFalse(r.is_aligned())
        r.skip(7)
        self.assertTrue(r.is_aligned())

        r.bits(7)
        self.assertFalse(r.is_aligned())
        r.bits(1)
        self.assertTrue(r.is_aligned())
    def __init__(self, fileobj, length):
        """Raises DescriptorError"""

        r = BitReader(fileobj)
        try:
            self.ES_ID = r.bits(16)
            self.streamDependenceFlag = r.bits(1)
            self.URL_Flag = r.bits(1)
            self.OCRstreamFlag = r.bits(1)
            self.streamPriority = r.bits(5)
            if self.streamDependenceFlag:
                self.dependsOn_ES_ID = r.bits(16)
            if self.URL_Flag:
                URLlength = r.bits(8)
                self.URLstring = r.bytes(URLlength)
            if self.OCRstreamFlag:
                self.OCR_ES_Id = r.bits(16)

            tag = r.bits(8)
        except BitReaderError as e:
            raise DescriptorError(e)

        if tag != DecoderConfigDescriptor.TAG:
            raise DescriptorError("unexpected DecoderConfigDescrTag %d" % tag)

        assert r.is_aligned()
        self.decConfigDescr = DecoderConfigDescriptor.parse(fileobj)
    def __init__(self, fileobj, length):
        """Raises DescriptorError"""

        r = BitReader(fileobj)

        try:
            self.objectTypeIndication = r.bits(8)
            self.streamType = r.bits(6)
            self.upStream = r.bits(1)
            self.reserved = r.bits(1)
            self.bufferSizeDB = r.bits(24)
            self.maxBitrate = r.bits(32)
            self.avgBitrate = r.bits(32)

            if (self.objectTypeIndication, self.streamType) != (0x40, 0x5):
                return

            # all from here is optional
            if length * 8 == r.get_position():
                return

            tag = r.bits(8)
        except BitReaderError as e:
            raise DescriptorError(e)

        if tag == DecoderSpecificInfo.TAG:
            assert r.is_aligned()
            self.decSpecificInfo = DecoderSpecificInfo.parse(fileobj)
Example #5
0
    def __init__(self, fileobj, length):
        """Raises DescriptorError"""

        r = BitReader(fileobj)

        try:
            self.objectTypeIndication = r.bits(8)
            self.streamType = r.bits(6)
            self.upStream = r.bits(1)
            self.reserved = r.bits(1)
            self.bufferSizeDB = r.bits(24)
            self.maxBitrate = r.bits(32)
            self.avgBitrate = r.bits(32)

            if (self.objectTypeIndication, self.streamType) != (0x40, 0x5):
                return

            # all from here is optional
            if length * 8 == r.get_position():
                return

            tag = r.bits(8)
        except BitReaderError as e:
            raise DescriptorError(e)

        if tag == DecoderSpecificInfo.TAG:
            assert r.is_aligned()
            self.decSpecificInfo = DecoderSpecificInfo.parse(fileobj)
Example #6
0
    def __init__(self, fileobj, length):
        """Raises DescriptorError"""

        r = BitReader(fileobj)
        try:
            self.ES_ID = r.bits(16)
            self.streamDependenceFlag = r.bits(1)
            self.URL_Flag = r.bits(1)
            self.OCRstreamFlag = r.bits(1)
            self.streamPriority = r.bits(5)
            if self.streamDependenceFlag:
                self.dependsOn_ES_ID = r.bits(16)
            if self.URL_Flag:
                URLlength = r.bits(8)
                self.URLstring = r.bytes(URLlength)
            if self.OCRstreamFlag:
                self.OCR_ES_Id = r.bits(16)

            tag = r.bits(8)
        except BitReaderError as e:
            raise DescriptorError(e)

        if tag != DecoderConfigDescriptor.TAG:
            raise DescriptorError("unexpected DecoderConfigDescrTag %d" % tag)

        assert r.is_aligned()
        self.decConfigDescr = DecoderConfigDescriptor.parse(fileobj)
    def _parse_esds(self, esds, fileobj):
        assert esds.name == b"esds"

        ok, data = esds.read(fileobj)
        if not ok:
            raise ASEntryError("truncated %s atom" % esds.name)

        try:
            version, flags, data = parse_full_atom(data)
        except ValueError as e:
            raise ASEntryError(e)

        if version != 0:
            raise ASEntryError("Unsupported version %d" % version)

        fileobj = cBytesIO(data)
        r = BitReader(fileobj)

        try:
            tag = r.bits(8)
            if tag != ES_Descriptor.TAG:
                raise ASEntryError("unexpected descriptor: %d" % tag)
            assert r.is_aligned()
        except BitReaderError as e:
            raise ASEntryError(e)

        try:
            decSpecificInfo = ES_Descriptor.parse(fileobj)
        except DescriptorError as e:
            raise ASEntryError(e)
        dec_conf_desc = decSpecificInfo.decConfigDescr

        self.bitrate = dec_conf_desc.avgBitrate
        self.codec += dec_conf_desc.codec_param
        self.codec_description = dec_conf_desc.codec_desc

        decSpecificInfo = dec_conf_desc.decSpecificInfo
        if decSpecificInfo is not None:
            if decSpecificInfo.channels != 0:
                self.channels = decSpecificInfo.channels

            if decSpecificInfo.sample_rate != 0:
                self.sample_rate = decSpecificInfo.sample_rate
Example #8
0
    def _parse_esds(self, esds, fileobj):
        assert esds.name == b"esds"

        ok, data = esds.read(fileobj)
        if not ok:
            raise ASEntryError("truncated %s atom" % esds.name)

        try:
            version, flags, data = parse_full_atom(data)
        except ValueError as e:
            raise ASEntryError(e)

        if version != 0:
            raise ASEntryError("Unsupported version %d" % version)

        fileobj = cBytesIO(data)
        r = BitReader(fileobj)

        try:
            tag = r.bits(8)
            if tag != ES_Descriptor.TAG:
                raise ASEntryError("unexpected descriptor: %d" % tag)
            assert r.is_aligned()
        except BitReaderError as e:
            raise ASEntryError(e)

        try:
            decSpecificInfo = ES_Descriptor.parse(fileobj)
        except DescriptorError as e:
            raise ASEntryError(e)
        dec_conf_desc = decSpecificInfo.decConfigDescr

        self.bitrate = dec_conf_desc.avgBitrate
        self.codec += dec_conf_desc.codec_param
        self.codec_description = dec_conf_desc.codec_desc

        decSpecificInfo = dec_conf_desc.decSpecificInfo
        if decSpecificInfo is not None:
            if decSpecificInfo.channels != 0:
                self.channels = decSpecificInfo.channels

            if decSpecificInfo.sample_rate != 0:
                self.sample_rate = decSpecificInfo.sample_rate
    def __init__(self, atom, fileobj):
        ok, data = atom.read(fileobj)
        if not ok:
            raise ASEntryError("too short %r atom" % atom.name)

        fileobj = cBytesIO(data)
        r = BitReader(fileobj)

        try:
            # SampleEntry
            r.skip(6 * 8)  # reserved
            r.skip(2 * 8)  # data_ref_index

            # AudioSampleEntry
            r.skip(8 * 8)  # reserved
            self.channels = r.bits(16)
            self.sample_size = r.bits(16)
            r.skip(2 * 8)  # pre_defined
            r.skip(2 * 8)  # reserved
            self.sample_rate = r.bits(32) >> 16
        except BitReaderError as e:
            raise ASEntryError(e)

        assert r.is_aligned()

        try:
            extra = Atom(fileobj)
        except AtomError as e:
            raise ASEntryError(e)

        self.codec = atom.name.decode("latin-1")
        self.codec_description = None

        if atom.name == b"mp4a" and extra.name == b"esds":
            self._parse_esds(extra, fileobj)
        elif atom.name == b"alac" and extra.name == b"alac":
            self._parse_alac(extra, fileobj)
        elif atom.name == b"ac-3" and extra.name == b"dac3":
            self._parse_dac3(extra, fileobj)

        if self.codec_description is None:
            self.codec_description = self.codec.upper()
Example #10
0
    def __init__(self, atom, fileobj):
        ok, data = atom.read(fileobj)
        if not ok:
            raise ASEntryError("too short %r atom" % atom.name)

        fileobj = cBytesIO(data)
        r = BitReader(fileobj)

        try:
            # SampleEntry
            r.skip(6 * 8)  # reserved
            r.skip(2 * 8)  # data_ref_index

            # AudioSampleEntry
            r.skip(8 * 8)  # reserved
            self.channels = r.bits(16)
            self.sample_size = r.bits(16)
            r.skip(2 * 8)  # pre_defined
            r.skip(2 * 8)  # reserved
            self.sample_rate = r.bits(32) >> 16
        except BitReaderError as e:
            raise ASEntryError(e)

        assert r.is_aligned()

        try:
            extra = Atom(fileobj)
        except AtomError as e:
            raise ASEntryError(e)

        self.codec = atom.name.decode("latin-1")
        self.codec_description = None

        if atom.name == b"mp4a" and extra.name == b"esds":
            self._parse_esds(extra, fileobj)
        elif atom.name == b"alac" and extra.name == b"alac":
            self._parse_alac(extra, fileobj)
        elif atom.name == b"ac-3" and extra.name == b"dac3":
            self._parse_dac3(extra, fileobj)

        if self.codec_description is None:
            self.codec_description = self.codec.upper()
Example #11
0
    def __init__(self, xing, fileobj):
        """Raises LAMEError if parsing fails"""

        payload = fileobj.read(27)
        if len(payload) != 27:
            raise LAMEError("Not enough data")

        # extended lame header
        r = BitReader(cBytesIO(payload))
        revision = r.bits(4)
        if revision != 0:
            raise LAMEError("unsupported header revision %d" % revision)

        self.vbr_method = r.bits(4)
        self.lowpass_filter = r.bits(8) * 100

        # these have a different meaning for lame; expose them again here
        self.quality = (100 - xing.vbr_scale) % 10
        self.vbr_quality = (100 - xing.vbr_scale) // 10

        track_peak_data = r.bytes(4)
        if track_peak_data == b"\x00\x00\x00\x00":
            self.track_peak = None
        else:
            # see PutLameVBR() in LAME's VbrTag.c
            self.track_peak = (
                cdata.uint32_be(track_peak_data) - 0.5) / 2 ** 23
        track_gain_type = r.bits(3)
        self.track_gain_origin = r.bits(3)
        sign = r.bits(1)
        gain_adj = r.bits(9) / 10.0
        if sign:
            gain_adj *= -1
        if track_gain_type == 1:
            self.track_gain_adjustment = gain_adj
        else:
            self.track_gain_adjustment = None
        assert r.is_aligned()

        album_gain_type = r.bits(3)
        self.album_gain_origin = r.bits(3)
        sign = r.bits(1)
        album_gain_adj = r.bits(9) / 10.0
        if album_gain_type == 2:
            self.album_gain_adjustment = album_gain_adj
        else:
            self.album_gain_adjustment = None

        self.encoding_flags = r.bits(4)
        self.ath_type = r.bits(4)

        self.bitrate = r.bits(8)

        self.encoder_delay_start = r.bits(12)
        self.encoder_padding_end = r.bits(12)

        self.source_sample_frequency_enum = r.bits(2)
        self.unwise_setting_used = r.bits(1)
        self.stereo_mode = r.bits(3)
        self.noise_shaping = r.bits(2)

        sign = r.bits(1)
        mp3_gain = r.bits(7)
        if sign:
            mp3_gain *= -1
        self.mp3_gain = mp3_gain

        r.skip(2)
        self.surround_info = r.bits(3)
        self.preset_used = r.bits(11)
        self.music_length = r.bits(32)
        self.music_crc = r.bits(16)

        self.header_crc = r.bits(16)
        assert r.is_aligned()
Example #12
0
    def __init__(self, fileobj):
        """Raises HeaderNotFoundError"""

        self.frame_offset = fileobj.tell()

        r = BitReader(fileobj)
        try:
            if r.bits(11) != 0x7ff:
                raise HeaderNotFoundError("invalid sync")
            version = r.bits(2)
            layer = r.bits(2)
            protection = r.bits(1)
            bitrate = r.bits(4)
            sample_rate = r.bits(2)
            padding = r.bits(1)
            r.skip(1)  # private
            self.mode = r.bits(2)
            r.skip(6)
        except BitReaderError:
            raise HeaderNotFoundError("truncated header")

        assert r.get_position() == 32 and r.is_aligned()

        # try to be strict here to redice the chance of a false positive
        if version == 1 or layer == 0 or sample_rate == 0x3 or \
                bitrate == 0xf or bitrate == 0:
            raise HeaderNotFoundError("invalid header")

        self.channels = 1 if self.mode == MONO else 2

        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_size = 384
            slot = 4
        elif self.version >= 2 and self.layer == 3:
            frame_size = 576
            slot = 1
        else:
            frame_size = 1152
            slot = 1

        frame_length = (
            ((frame_size // 8 * self.bitrate) // self.sample_rate) +
            padding) * slot

        self.sketchy = True

        # Try to find/parse the Xing header, which trumps the above length
        # and bitrate calculation.
        if self.layer == 3:
            self._parse_vbr_header(fileobj, self.frame_offset, frame_size,
                                   frame_length)

        fileobj.seek(self.frame_offset + frame_length, 0)