def test_almost_my_file(self): self.failUnlessRaises(MusepackHeaderError, MusepackInfo, cBytesIO(b"MP+" + b"\x00" * 32)) self.failUnlessRaises(MusepackHeaderError, MusepackInfo, cBytesIO(b"MP+" + b"\x00" * 100)) self.failUnlessRaises(MusepackHeaderError, MusepackInfo, cBytesIO(b"MPCK" + b"\x00" * 100))
def test_almost_my_file(self): self.failUnlessRaises( MusepackHeaderError, MusepackInfo, cBytesIO(b"MP+" + b"\x00" * 32)) self.failUnlessRaises( MusepackHeaderError, MusepackInfo, cBytesIO(b"MP+" + b"\x00" * 100)) self.failUnlessRaises( MusepackHeaderError, MusepackInfo, cBytesIO(b"MPCK" + b"\x00" * 100))
def test_read(self): payload = 8 * b"\xff" fileobj = cBytesIO(b"\x00\x00\x00\x10atom" + payload) atom = Atom(fileobj) ok, data = atom.read(fileobj) self.assertTrue(ok) self.assertEqual(data, payload) payload = 7 * b"\xff" fileobj = cBytesIO(b"\x00\x00\x00\x10atom" + payload) atom = Atom(fileobj) ok, data = atom.read(fileobj) self.assertFalse(ok) self.assertEqual(data, payload)
def test_fileobj(self): for filename in self.filenames: with open(filename, "rb") as h: self.assertTrue(File(h) is not None) with open(filename, "rb") as h: fileobj = cBytesIO(h.read()) self.assertTrue(File(fileobj, filename=filename) is not None)
def test_length_0_container(self): data = cBytesIO(struct.pack(">I4s", 0, b"moov") + Atom.render(b"data", b"whee")) atom = Atom(data) self.failUnlessEqual(len(atom.children), 1) self.failUnlessEqual(atom.length, 20) self.failUnlessEqual(atom.children[-1].length, 12)
def _parse_dac3(self, atom, fileobj): # ETSI TS 102 366 assert atom.name == b"dac3" ok, data = atom.read(fileobj) if not ok: raise ASEntryError("truncated %s atom" % atom.name) fileobj = cBytesIO(data) r = BitReader(fileobj) # sample_rate in AudioSampleEntry covers values in # fscod2 and not just fscod, so ignore fscod here. try: r.skip(2 + 5 + 3) # fscod, bsid, bsmod acmod = r.bits(3) lfeon = r.bits(1) bit_rate_code = r.bits(5) r.skip(5) # reserved except BitReaderError as e: raise ASEntryError(e) self.channels = [2, 1, 2, 3, 3, 4, 4, 5][acmod] + lfeon try: self.bitrate = [ 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 576, 640 ][bit_rate_code] * 1000 except IndexError: pass
def test_id3_indicates_mp3_not_tta(self): header = b"ID3 the rest of this is garbage" fileobj = cBytesIO(header) filename = "not-identifiable.ext" self.failUnless( TrueAudio.score(filename, fileobj, header) < MP3.score( filename, fileobj, header))
def test_theora_bad_version(self): page = OggPage(open(self.filename, "rb")) packet = page.packets[0] packet = packet[:7] + b"\x03\x00" + packet[9:] page.packets = [packet] fileobj = cBytesIO(page.write()) self.failUnlessRaises(IOError, OggTheoraInfo, fileobj)
def _parse_dac3(self, atom, fileobj): # ETSI TS 102 366 assert atom.name == b"dac3" ok, data = atom.read(fileobj) if not ok: raise ASEntryError("truncated %s atom" % atom.name) fileobj = cBytesIO(data) r = BitReader(fileobj) # sample_rate in AudioSampleEntry covers values in # fscod2 and not just fscod, so ignore fscod here. try: r.skip(2 + 5 + 3) # fscod, bsid, bsmod acmod = r.bits(3) lfeon = r.bits(1) bit_rate_code = r.bits(5) r.skip(5) # reserved except BitReaderError as e: raise ASEntryError(e) self.channels = [2, 1, 2, 3, 3, 4, 4, 5][acmod] + lfeon try: self.bitrate = [ 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 576, 640][bit_rate_code] * 1000 except IndexError: pass
def test_invalid_header(self): asf = ASF() fileobj = cBytesIO( b"0&\xb2u\x8ef\xcf\x11\xa6\xd9\x00\xaa\x00b\xcel\x19\xbf\x01\x00" b"\x00\x00\x00\x00\x07\x00\x00\x00\x01\x02") self.assertRaises( ASFHeaderError, HeaderObject.parse_full, asf, fileobj)
def test_negative_bitrate(self): page = OggPage(open(self.filename, "rb")) packet = page.packets[0] packet = (packet[:16] + b"\xff\xff\xff\xff" + b"\xff\xff\xff\xff" + b"\xff\xff\xff\xff" + packet[28:]) page.packets[0] = packet info = OggVorbisInfo(cBytesIO(page.write())) self.failUnlessEqual(info.bitrate, 0)
def test_underestimated_bitrate(self): page = OggPage(open(self.filename, "rb")) packet = page.packets[0] packet = (packet[:16] + b"\x00\x00\x01\x00" + b"\x01\x00\x00\x00" + b"\x00\x00\x01\x00" + packet[28:]) page.packets[0] = packet info = OggVorbisInfo(cBytesIO(page.write())) self.failUnlessEqual(info.bitrate, 65536)
def test_zero_padded_sh_packet(self): # https://bitbucket.org/lazka/mutagen/issue/198 data = (b"MPCKSH\x10\x95 Q\xa2\x08\x81\xb8\xc9T\x00\x1e\x1b" b"\x00RG\x0c\x01A\xcdY\x06?\x80Z\x06EI") fileobj = cBytesIO(data) info = MusepackInfo(fileobj) self.assertEqual(info.channels, 2) self.assertEqual(info.samples, 3024084)
def test_zero_padded_sh_packet(self): # https://github.com/quodlibet/mutagen/issues/198 data = (b"MPCKSH\x10\x95 Q\xa2\x08\x81\xb8\xc9T\x00\x1e\x1b" b"\x00RG\x0c\x01A\xcdY\x06?\x80Z\x06EI") fileobj = cBytesIO(data) info = MusepackInfo(fileobj) self.assertEqual(info.channels, 2) self.assertEqual(info.samples, 3024084)
def test_invalid_header(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") asf = ASF() fileobj = cBytesIO( b"0&\xb2u\x8ef\xcf\x11\xa6\xd9\x00\xaa\x00b\xcel\x19\xbf\x01\x00" b"\x00\x00\x00\x00\x07\x00\x00\x00\x01\x02") self.assertRaises(ASFHeaderError, HeaderObject.parse_full, asf, fileobj)
def test_bits(self): data = b"\x12\x34\x56\x78\x89\xAB\xCD\xEF" ref = cdata.uint64_be(data) for i in xrange(64): fo = cBytesIO(data) r = BitReader(fo) v = r.bits(i) << (64 - i) | r.bits(64 - i) self.assertEqual(v, ref)
def test_get_position(self): r = BitReader(cBytesIO(b"\xAB\xCD")) self.assertEqual(r.get_position(), 0) r.bits(3) self.assertEqual(r.get_position(), 3) r.skip(9) self.assertEqual(r.get_position(), 3 + 9) r.align() self.assertEqual(r.get_position(), 16)
def test_avg_bitrate(self): with open(self.filename, "rb") as h: page = OggPage(h) packet = page.packets[0] packet = (packet[:16] + b"\x00\x00\x01\x00" + b"\x00\x00\x00\x00" + b"\x00\x00\x00\x00" + packet[28:]) page.packets[0] = packet info = OggVorbisInfo(cBytesIO(page.write())) self.failUnlessEqual(info.bitrate, 32768)
def test_invalid_header(self): with warnings.catch_warnings(): warnings.simplefilter("ignore") asf = ASF() fileobj = cBytesIO( b"0&\xb2u\x8ef\xcf\x11\xa6\xd9\x00\xaa\x00b\xcel\x19\xbf\x01\x00" b"\x00\x00\x00\x00\x07\x00\x00\x00\x01\x02") self.assertRaises( ASFHeaderError, HeaderObject.parse_full, asf, fileobj)
def test_xing_unknown_framecount(self): frame = ( b'\xff\xfb\xe4\x0c\x00\x0f\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00Info\x00\x00\x00\x02\x00\xb4V@\x00\xb4R\x80\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') fileobj = cBytesIO(frame) info = MPEGInfo(fileobj) assert info.bitrate == 320000 assert info.length > 0
def test_valid_info_header(self): data = (b'Info\x00\x00\x00\x0f\x00\x00:>\x00\xed\xbd8\x00\x03\x05\x07' b'\n\r\x0f\x12\x14\x17\x1a\x1c\x1e"$&)+.1359;=@CEGJLORTVZ\\^ac' b'fikmqsux{}\x80\x82\x84\x87\x8a\x8c\x8e\x92\x94\x96\x99\x9c' b'\x9e\xa1\xa3\xa5\xa9\xab\xad\xb0\xb3\xb5\xb8\xba\xbd\xc0\xc2' b'\xc4\xc6\xca\xcc\xce\xd1\xd4\xd6\xd9\xdb\xdd\xe1\xe3\xe5\xe8' b'\xeb\xed\xf0\xf2\xf5\xf8\xfa\xfc\x00\x00\x009') fileobj = cBytesIO(data) xing = XingHeader(fileobj) self.assertEqual(xing.bytes, 15580472) self.assertEqual(xing.frames, 14910) self.assertEqual(xing.vbr_scale, 57) self.assertTrue(xing.toc) self.assertEqual(len(xing.toc), 100) self.assertEqual(sum(xing.toc), 12625) # only for coverage.. self.assertEqual(xing.is_info, True) XingHeader(cBytesIO(data.replace(b'Info', b'Xing')))
def test_seek_end(self): f = cBytesIO(b"foo") seek_end(f, 2) self.assertEqual(f.tell(), 1) seek_end(f, 3) self.assertEqual(f.tell(), 0) seek_end(f, 4) self.assertEqual(f.tell(), 0) seek_end(f, 0) self.assertEqual(f.tell(), 3) self.assertRaises(ValueError, seek_end, f, -1)
def test_xing_unknown_framecount(self): frame = ( b'\xff\xfb\xe4\x0c\x00\x0f\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00Info\x00\x00\x00\x02\x00\xb4V@\x00\xb4R\x80\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' ) fileobj = cBytesIO(frame) info = MPEGInfo(fileobj) assert info.bitrate == 320000 assert info.length > 0
def test_mdhd_version_1(self, soun=b"soun"): mdhd = Atom.render(b"mdhd", (b"\x01\x00\x00\x00" + b"\x00" * 16 + b"\x00\x00\x00\x02" + # 2 Hz b"\x00\x00\x00\x00\x00\x00\x00\x10")) hdlr = Atom.render(b"hdlr", b"\x00" * 8 + soun) mdia = Atom.render(b"mdia", mdhd + hdlr) trak = Atom.render(b"trak", mdia) moov = Atom.render(b"moov", trak) fileobj = cBytesIO(moov) atoms = Atoms(fileobj) info = MP4Info(atoms, fileobj) self.failUnlessEqual(info.length, 8)
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 test_prefer_theora_over_vorbis(self): header = ( b"OggS\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\xe1x\x06\x0f" b"\x00\x00\x00\x00)S'\xf4\x01*\x80theora\x03\x02\x01\x006\x00\x1e" b"\x00\x03V\x00\x01\xe0\x00\x00\x00\x00\x00\x18\x00\x00\x00\x01" b"\x00\x00\x00\x00\x00\x00\x00&%\xa0\x00\xc0OggS\x00\x02\x00\x00" b"\x00\x00\x00\x00\x00\x00d#\xa8\x1f\x00\x00\x00\x00]Y\xc0\xc0" b"\x01\x1e\x01vorbis\x00\x00\x00\x00\x02\x80\xbb\x00\x00\x00\x00" b"\x00\x00\x00\xee\x02\x00\x00\x00\x00\x00\xb8\x01") fileobj = cBytesIO(header) filename = "not-identifiable.ext" self.failUnless(OggVorbis.score(filename, fileobj, header) < OggTheora.score(filename, fileobj, header))
def test_no_audio_tracks(self): data = Atom.render(b"moov", Atom.render(b"udta", b"")) fileobj = cBytesIO(data) audio = MP4(fileobj) assert audio.info assert audio.pprint() info = audio.info assert isinstance(info.bitrate, int) assert isinstance(info.length, float) assert isinstance(info.channels, int) assert isinstance(info.sample_rate, int) assert isinstance(info.bits_per_sample, int) assert isinstance(info.codec, text_type) assert isinstance(info.codec_description, text_type)
def test_multiple_tracks(self): hdlr = Atom.render(b"hdlr", b"\x00" * 8 + b"whee") mdia = Atom.render(b"mdia", hdlr) trak1 = Atom.render(b"trak", mdia) mdhd = Atom.render(b"mdhd", (b"\x01\x00\x00\x00" + b"\x00" * 16 + b"\x00\x00\x00\x02" + # 2 Hz b"\x00\x00\x00\x00\x00\x00\x00\x10")) hdlr = Atom.render(b"hdlr", b"\x00" * 8 + b"soun") mdia = Atom.render(b"mdia", mdhd + hdlr) trak2 = Atom.render(b"trak", mdia) moov = Atom.render(b"moov", trak1 + trak2) fileobj = cBytesIO(moov) atoms = Atoms(fileobj) info = MP4Info(atoms, fileobj) self.failUnlessEqual(info.length, 8)
def test_valid(self): # parts of the trailing toc zeroed... data = (b'VBRI\x00\x01\t1\x00d\x00\x0c\xb05\x00\x00\x049\x00\x87\x00' b'\x01\x00\x02\x00\x08\n0\x19H\x18\xe0\x18x\x18\xe0\x18x\x19H' b'\x18\xe0\x19H\x18\xe0\x18\xe0\x18x' + b'\x00' * 300) fileobj = cBytesIO(data) vbri = VBRIHeader(fileobj) self.assertEqual(vbri.bytes, 831541) self.assertEqual(vbri.frames, 1081) self.assertEqual(vbri.quality, 100) self.assertEqual(vbri.version, 1) self.assertEqual(vbri.toc_frames, 8) self.assertTrue(vbri.toc) self.assertEqual(len(vbri.toc), 135) self.assertEqual(sum(vbri.toc), 72656)
def test_alac_2(self): # an example where the samplerate is only correct in the cookie, # also contains a bitrate atom_data = ( b'\x00\x00\x00Halac\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x02\x00\x18\x00\x00\x00\x00X\x88\x00' b'\x00\x00\x00\x00$alac\x00\x00\x00\x00\x00\x00\x10\x00\x00\x18' b'(\n\x0e\x02\x00\xff\x00\x00F/\x00%2\xd5\x00\x01X\x88') fileobj = cBytesIO(atom_data) atom = Atom(fileobj) entry = AudioSampleEntry(atom, fileobj) self.assertEqual(entry.bitrate, 2437845) self.assertEqual(entry.channels, 2) self.assertEqual(entry.codec, "alac") self.assertEqual(entry.codec_description, "ALAC") self.assertEqual(entry.sample_rate, 88200)
def test_alac(self): # an exampe where the channel count in the alac cookie is right # but the SampleEntry is wrong atom_data = ( b'\x00\x00\x00Halac\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x02\x00\x10\x00\x00\x00\x00\x1f@\x00' b'\x00\x00\x00\x00$alac\x00\x00\x00\x00\x00\x00\x10\x00\x00\x10' b'(\n\x0e\x01\x00\xff\x00\x00P\x01\x00\x00\x00\x00\x00\x00\x1f@') fileobj = cBytesIO(atom_data) atom = Atom(fileobj) entry = AudioSampleEntry(atom, fileobj) self.assertEqual(entry.bitrate, 0) self.assertEqual(entry.channels, 1) self.assertEqual(entry.codec, "alac") self.assertEqual(entry.codec_description, "ALAC") self.assertEqual(entry.sample_rate, 8000)
def test_short_year(self): data = ( b'XTAGhello world\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x001\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\xff') tag = ParseID3v1(data) self.failUnlessEqual(tag["TIT2"], "hello world") self.failUnlessEqual(tag["TDRC"], "0001") frames, offset = find_id3v1(cBytesIO(data)) self.assertEqual(offset, -125) self.assertEqual(frames, tag)
def _parse_stsd(self, atom, fileobj): """Sets channels, bits_per_sample, sample_rate and optionally bitrate. Can raise MP4StreamInfoError. """ assert atom.name == b"stsd" ok, data = atom.read(fileobj) if not ok: raise MP4StreamInfoError("Invalid stsd") try: version, flags, data = parse_full_atom(data) except ValueError as e: raise MP4StreamInfoError(e) if version != 0: raise MP4StreamInfoError("Unsupported stsd version") try: num_entries, offset = cdata.uint32_be_from(data, 0) except cdata.error as e: raise MP4StreamInfoError(e) if num_entries == 0: return # look at the first entry if there is one entry_fileobj = cBytesIO(data[offset:]) try: entry_atom = Atom(entry_fileobj) except AtomError as e: raise MP4StreamInfoError(e) try: entry = AudioSampleEntry(entry_atom, entry_fileobj) except ASEntryError as e: raise MP4StreamInfoError(e) else: self.channels = entry.channels self.bits_per_sample = entry.sample_size self.sample_rate = entry.sample_rate self.bitrate = entry.bitrate self.codec = entry.codec self.codec_description = entry.codec_description
def test_short_year(self): data = ( b'XTAGhello world\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x001\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\xff' ) tag = ParseID3v1(data) self.failUnlessEqual(tag["TIT2"], "hello world") self.failUnlessEqual(tag["TDRC"], "0001") frames, offset = find_id3v1(cBytesIO(data)) self.assertEqual(offset, -125) self.assertEqual(frames, tag)
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 test_pce(self): atom_data = ( b'\x00\x00\x00dmp4a\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x02\x00\x10\x00\x00\x00\x00\xbb\x80' b'\x00\x00\x00\x00\x00@esds\x00\x00\x00\x00\x03\x80\x80\x80/\x00' b'\x00\x00\x04\x80\x80\x80!@\x15\x00\x15\x00\x00\x03\xed\xaa\x00' b'\x03k\x00\x05\x80\x80\x80\x0f+\x01\x88\x02\xc4\x04\x90,\x10\x8c' b'\x80\x00\x00\xed@\x06\x80\x80\x80\x01\x02') fileobj = cBytesIO(atom_data) atom = Atom(fileobj) entry = AudioSampleEntry(atom, fileobj) self.assertEqual(entry.bitrate, 224000) self.assertEqual(entry.channels, 8) self.assertEqual(entry.codec_description, "AAC LC+SBR") self.assertEqual(entry.codec, "mp4a.40.2") self.assertEqual(entry.sample_rate, 48000) self.assertEqual(entry.sample_size, 16)
def test_ac3(self): atom_data = ( b'\x00\x00\x00/ac-3\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x02\x00\x10\x00\x00\x00\x00V"\x00\x00' b'\x00\x00\x00\x0bdac3R\t\x00') fileobj = cBytesIO(atom_data) atom = Atom(fileobj) entry = AudioSampleEntry(atom, fileobj) self.assertEqual(entry.bitrate, 128000) self.assertEqual(entry.channels, 1) self.assertEqual(entry.codec_description, "AC-3") self.assertEqual(entry.codec, "ac-3") self.assertEqual(entry.sample_rate, 22050) self.assertEqual(entry.sample_size, 16) self.assertTrue(isinstance(entry.codec, text_type)) self.assertTrue(isinstance(entry.codec_description, text_type))
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()
def test_samr(self): # parsing not implemented, values are wrong but at least it loads. # should be Mono 7.95kbps 8KHz atom_data = ( b'\x00\x00\x005samr\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00' b'\x00\x00\x00\x00\x00\x00\x02\x00\x10\x00\x00\x00\x00\x1f@\x00' b'\x00\x00\x00\x00\x11damrFFMP\x00\x81\xff\x00\x01') fileobj = cBytesIO(atom_data) atom = Atom(fileobj) entry = AudioSampleEntry(atom, fileobj) self.assertEqual(entry.bitrate, 0) self.assertEqual(entry.channels, 2) self.assertEqual(entry.codec_description, "SAMR") self.assertEqual(entry.codec, "samr") self.assertEqual(entry.sample_rate, 8000) self.assertEqual(entry.sample_size, 16) self.assertTrue(isinstance(entry.codec, text_type)) self.assertTrue(isinstance(entry.codec_description, text_type))