def _parse_esds(self, esds, fileobj): assert esds.name == b"esds" ok, data = esds.read(fileobj) if not ok: raise ValueError("truncated %s atom" % esds.name) version, flags, data = _parse_full_atom(data) if version != 0: # unsupported version, ignore return try: tag, off = cdata.uint8_from(data, 0) ES_DescrTag = 0x03 if tag != ES_DescrTag: raise ValueError("unexpected descriptor: %d" % tag) base_size, off = _parse_desc_length(data, off) es_id, off = cdata.uint16_be_from(data, off) es_flags, off = cdata.uint8_from(data, off) streamDependenceFlag = cdata.test_bit(es_flags, 7) URL_Flag = cdata.test_bit(es_flags, 6) OCRstreamFlag = cdata.test_bit(es_flags, 5) # streamPriority = es_flags & 0x1f if streamDependenceFlag: off += 2 # dependsOn_ES_ID if URL_Flag: url_len, off = cdata.uint8_from(data, off) off += url_len # URLstring if OCRstreamFlag: off += 2 # OCR_ES_Id DecoderConfigDescrTag = 4 tag, off = cdata.uint8_from(data, off) if tag != DecoderConfigDescrTag: raise ValueError("unexpected DecoderConfigDescrTag %d" % tag) dec_conf_size, off = _parse_desc_length(data, off) off += 9 # skip some stuff # average bitrate self.bitrate, off = cdata.uint32_be_from(data, off) except cdata.error as e: raise ValueError(e)
def _parse_desc_length(data, offset): """Returns the decoded value and the new offset in data after the value. Can raise ValueError in case the value is too long or data too short. """ value = 0 for i in xrange(4): try: b, offset = cdata.uint8_from(data, offset) 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, offset
def _parse_alac(self, atom, fileobj): # https://alac.macosforge.org/trac/browser/trunk/ # ALACMagicCookieDescription.txt assert atom.name == b"alac" ok, data = atom.read(fileobj) if not ok: raise ValueError("truncated %s atom" % atom.name) version, flags, data = _parse_full_atom(data) if version != 0: # unsupported version, ignore return # for some files the AudioSampleEntry values default to 44100/2chan # and the real info is in the alac cookie, so prefer it try: self.channels, off = cdata.uint8_from(data, 9) off += 6 # skip some stuff self.bitrate, off = cdata.uint32_be_from(data, off) self.sample_rate, off = cdata.uint32_be_from(data, off) except cdata.error as e: raise ValueError(e)