def test_create_container(): container_name = "container_name.bzna" try: create_container(container_name) assert os.path.exists(container_name) bstr = ConstBitStream(filename=container_name) boxes = list(Parser.parse(bstr)) for box in boxes: box.load(bstr) assert len(boxes) == 2 ftyp = boxes.pop(0) isinstance(ftyp, bx_def.FTYP) assert ftyp.header.type == b"ftyp" assert ftyp.major_brand == 1769172845 # b"isom" assert ftyp.minor_version == 0 assert ftyp.compatible_brands == [1652190817, # b"bzna" 1769172845] # b"isom" mdat = boxes.pop(0) isinstance(mdat, bx_def.MDAT) assert mdat.header.type == b"mdat" # mdat should be using the box extended size field to prevent having to # shift data if it is bigger than the limit of the regular box size field assert mdat.header.box_ext_size is not None assert mdat.header.box_ext_size > 0 assert mdat.data == b'' finally: shutil.rmtree(".", ignore_errors=True)
def test_mett_box(): bs = pack("uintbe:32, bytes:4, " "uintbe:8, uintbe:8, uintbe:8, uintbe:8, uintbe:8, uintbe:8, " "uintbe:16, " "bytes:1, bytes:11", 28, b"mett", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 1, b'\0', b'image/heif\0') box_header = BoxHeader() mett = bx_def.METT(box_header) mett.header.type = b"mett" mett.data_reference_index = 1 mett.content_encoding = b'\0' mett.mime_format = b'image/heif\0' mett.refresh_box_size() box = mett assert box.header.type == b"mett" assert box.header.box_size == 28 assert box.data_reference_index == 1 assert box.content_encoding == b'\0' assert box.mime_format == b'image/heif\0' assert len(box.boxes) == 0 assert bytes(next(Parser.parse(bs))) == bs.bytes assert bytes(box) == bs.bytes
def test_stsz_box(): bs = pack("uintbe:32, bytes:4, uintbe:8, bits:24, " "uintbe:32, uintbe:32, uintbe:32", 24, b"stsz", 0, b"\x00\x00\x00", 0, 1, 1) box_header = FullBoxHeader() stsz = bx_def.STSZ(box_header) stsz.header.type = b"stsz" stsz.header.version = 0 stsz.header.flags = b"\x00\x00\x00" stsz.sample_size = 0 sample = stsz.append_and_return() sample.entry_size = 1 stsz.refresh_box_size() box = stsz assert box.header.type == b"stsz" assert box.header.box_size == 24 assert box.header.version == 0 assert box.header.flags == b"\x00\x00\x00" assert box.sample_size == 0 assert box.sample_count == 1 assert len(box.samples) == 1 assert box.samples[0].entry_size == 1 parsed_box = next(Parser.parse(bs)) parsed_box.load(bs) assert bytes(parsed_box) == bs.bytes assert bytes(box) == bs.bytes
def test_mvhd_box_v1(): bs = pack("uintbe:32, bytes:4, uintbe:8, bits:24, " "uintbe:64, uintbe:64, uintbe:32, uintbe:64, " "uintbe:16, uintbe:16, uintbe:8, uintbe:8, " "bits:16, bits:32, bits:32, " "uintbe:32, uintbe:32, uintbe:32, uintbe:32, uintbe:32, uintbe:32, uintbe:32, uintbe:32, uintbe:32, " "bits:32, bits:32, bits:32, bits:32, bits:32, bits:32, " "uintbe:32", 120, b"mvhd", 1, b"\x00\x00\x00", 3596199850, 3596199850, 48000, 6720608, 1, 0, 1, 0, b"\x00" * 2, b"\x00" * 4, b"\x00" * 4, 65536, 0, 0, 0, 65536, 0, 0, 0, 1073741824, b"\x00" * 4, b"\x00" * 4, b"\x00" * 4, b"\x00" * 4, b"\x00" * 4, b"\x00" * 4, 3) box_header = FullBoxHeader() mvhd = bx_def.MVHD(box_header) mvhd.header.type = b"mvhd" mvhd.header.version = 1 mvhd.header.flags = b"\x00\x00\x00" mvhd.creation_time = 3596199850 mvhd.modification_time = 3596199850 mvhd.timescale = 48000 mvhd.duration = 6720608 mvhd.rate = [1, 0] mvhd.volume = [1, 0] mvhd.matrix = [65536, 0, 0, 0, 65536, 0, 0, 0, 1073741824] mvhd.pre_defined = [b"\x00" * 4] * 6 mvhd.next_track_id = 3 mvhd.refresh_box_size() box = mvhd assert box.header.type == b"mvhd" assert box.header.box_size == 120 assert box.header.version == 1 assert box.header.flags == b"\x00\x00\x00" assert box.creation_time == 3596199850 assert box.modification_time == 3596199850 assert box.timescale == 48000 assert box.duration == 6720608 assert box.rate == [1, 0] assert box.volume == [1, 0] assert box.matrix == [65536, 0, 0, 0, 65536, 0, 0, 0, 1073741824] assert box.pre_defined == [b"\x00" * 4] * 6 assert box.next_track_id == 3 assert bytes(next(Parser.parse(bs))) == bs.bytes assert bytes(box) == bs.bytes
def test_hdlr_box(): bs = pack("uintbe:32, bytes:4, uintbe:8, bits:24, " "uintbe:32, bytes:4, bits:32, bits:32, bits:32, bytes:19", 51, b"hdlr", 0, b"\x00\x00\x00", 0, b"vide", b"\x00" * 4, b"\x00" * 4, b"\x00" * 4, b"Vireo Eyes v2.4.22\0") box_header = FullBoxHeader() hdlr = bx_def.HDLR(box_header) hdlr.header.type = b"hdlr" hdlr.header.version = 0 hdlr.header.flags = b"\x00\x00\x00" hdlr.pre_defined = 0 hdlr.handler_type = b"vide" hdlr.name = b"Vireo Eyes v2.4.22\0" hdlr.refresh_box_size() box = hdlr assert box.header.type == b"hdlr" assert box.header.box_size == 51 assert box.header.version == 0 assert box.header.flags == b"\x00\x00\x00" assert box.pre_defined == 0 assert box.handler_type == b"vide" assert box.name == b"Vireo Eyes v2.4.22\0" assert bytes(next(Parser.parse(bs))) == bs.bytes assert bytes(box) == bs.bytes
def test_vmhd_box(): bs = pack("uintbe:32, bytes:4, uintbe:8, bits:24, " "uintbe:16, uintbe:16, uintbe:16, uintbe:16", 20, b"vmhd", 0, b"\x00\x00\x01", 0, 0, 0, 0) box_header = FullBoxHeader() vmhd = bx_def.VMHD(box_header) vmhd.header.type = b"vmhd" vmhd.header.version = 0 vmhd.header.flags = b"\x00\x00\x01" vmhd.graphicsmode = 0 vmhd.opcolor = [0, 0, 0] vmhd.refresh_box_size() box = vmhd assert box.header.type == b"vmhd" assert box.header.box_size == 20 assert box.header.version == 0 assert box.header.flags == b"\x00\x00\x01" assert box.graphicsmode == 0 assert box.opcolor == [0, 0, 0] assert bytes(next(Parser.parse(bs))) == bs.bytes assert bytes(box) == bs.bytes
def test_stts_box(): bs = pack("uintbe:32, bytes:4, uintbe:8, bits:24, " "uintbe:32, uintbe:32, uintbe:32", 24, b"stts", 0, b"\x00\x00\x00", 1, 1, 1) box_header = FullBoxHeader() stts = bx_def.STTS(box_header) stts.header.type = b"stts" stts.header.version = 0 stts.header.flags = b"\x00\x00\x00" entry = stts.append_and_return() entry.sample_count = 1 entry.sample_delta = 1 stts.refresh_box_size() box = stts assert box.header.type == b"stts" assert box.header.box_size == 24 assert box.header.version == 0 assert box.header.flags == b"\x00\x00\x00" assert box.entry_count == 1 assert len(box.entries) == 1 assert box.entries[0].sample_count == 1 assert box.entries[0].sample_delta == 1 parsed_box = next(Parser.parse(bs)) parsed_box.load(bs) assert bytes(parsed_box) == bs.bytes assert bytes(box) == bs.bytes
def test_ctts_box_v1(): bs = pack("uintbe:32, bytes:4, uintbe:8, bits:24, " "uintbe:32, uintbe:32, intbe:32", 24, b"ctts", 1, b"\x00\x00\x00", 1, 1, -1) box_header = FullBoxHeader() ctts = bx_def.CTTS(box_header) ctts.header.type = b"ctts" ctts.header.version = 1 ctts.header.flags = b"\x00\x00\x00" entry = ctts.append_and_return() entry.sample_count = 1 entry.sample_offset = (-1, "intbe:32") ctts.refresh_box_size() box = ctts assert box.header.type == b"ctts" assert box.header.box_size == 24 assert box.header.version == 1 assert box.header.flags == b"\x00\x00\x00" assert box.entry_count == 1 assert len(box.entries) == 1 assert box.entries[0].sample_count == 1 assert box.entries[0].sample_offset == -1 parsed_box = next(Parser.parse(bs)) parsed_box.load(bs) assert bytes(parsed_box) == bs.bytes assert bytes(box) == bs.bytes
def test_ftyp_box_w_no_type(): bs = pack("uintbe:32, bytes:4, " "bytes:4, uintbe:32, bytes:8", 24, b"ftyp", b"bzna", 10, b"mp42mp41") box_header = BoxHeader() ftyp = bx_def.FTYP(box_header) ftyp.header.type = b"ftyp" ftyp.major_brand = (1652190817,) # b"bzna" ftyp.minor_version = (10,) ftyp.compatible_brands = ([1836069938, # b"mp42" 1836069937],) # b"mp41" ftyp.refresh_box_size() box = ftyp assert box.header.type == b"ftyp" assert box.header.box_size == 24 assert box.major_brand == 1652190817 # b"bzna" assert box.minor_version == 10 assert box.compatible_brands == [1836069938, # b"mp42" 1836069937] # b"mp41" assert bytes(next(Parser.parse(bs))) == bs.bytes assert bytes(box) == bs.bytes
def test_sbtt_box(): bs = pack("uintbe:32, bytes:4, " "uintbe:8, uintbe:8, uintbe:8, uintbe:8, uintbe:8, uintbe:8, " "uintbe:16, " "bytes:1, bytes:11", 28, b"sbtt", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 1, b'\0', b'text/plain\0') box_header = BoxHeader() stxt = bx_def.STXT(box_header) stxt.header.type = b"sbtt" stxt.data_reference_index = 1 stxt.content_encoding = b'\0' stxt.mime_format = b'text/plain\0' stxt.refresh_box_size() box = stxt assert box.header.type == b"sbtt" assert box.header.box_size == 28 assert box.data_reference_index == 1 assert box.content_encoding == b'\0' assert box.mime_format == b'text/plain\0' assert len(box.boxes) == 0 assert bytes(next(Parser.parse(bs))) == bs.bytes assert bytes(box) == bs.bytes
def test_clap_traks(): src = os.path.join(DATA_DIR, "transcode_steps/n02100735_8211.mp4") width = 600 height = 535 thumb_width = 512 thumb_height = 456 bstr = ConstBitStream(filename=src) boxes = [box for box in Parser.parse(bstr)] for box in boxes: box.load(bstr) _clean_boxes(boxes) moov = boxes[2] traks = [box for box in moov.boxes if box.header.type == b"trak"] clap_traks(traks, width, height, thumb_width, thumb_height) trak_input, trak_thumb = traks # moov.trak.tkhd tkhd = trak_input.boxes[0] assert tkhd.width == 600 assert tkhd.height == 535 # moov.trak.mdia.minf.stbl.stsd.hvc1.clap clap = trak_input.boxes[-1].boxes[-1].boxes[-1].boxes[0].boxes[0].boxes[-2] assert clap.header.type == b"clap" assert clap.clean_aperture_width_n == 600 assert clap.clean_aperture_width_d == 1 assert clap.clean_aperture_height_n == 535 assert clap.clean_aperture_height_d == 1 assert clap.horiz_off_n == -424 assert clap.horiz_off_d == 2 assert clap.vert_off_n == -489 assert clap.vert_off_d == 2 # moov.trak.tkhd tkhd = trak_thumb.boxes[0] assert tkhd.width == 512 assert tkhd.height == 456 # moov.trak.mdia.minf.stbl.stsd.hvc1.clap clap = trak_thumb.boxes[-1].boxes[-1].boxes[-1].boxes[0].boxes[0].boxes[-2] assert clap.header.type == b"clap" assert clap.clean_aperture_width_n == 512 assert clap.clean_aperture_width_d == 1 assert clap.clean_aperture_height_n == 456 assert clap.clean_aperture_height_d == 1 assert clap.horiz_off_n == 0 assert clap.horiz_off_d == 2 assert clap.vert_off_n == -56 assert clap.vert_off_d == 2
def test_image2mp4(): dir = os.path.join(DATA_DIR, "mini_dataset_to_transcode/0001") name = "n02100735_8211.JPEG" out = "n02100735_8211.mp4" try: args = parse_args([ "--codec=h265", "--tile=512:512:yuv420", "--crf=10", "--output={}".format(out), "--primary", "--thumb", "--name={}".format(name), "--item=path={}/{}".format(dir, name), "--hidden", "--name=target", "--mime=application/octet-stream", "--item=type=mime,path={}/{}.target".format(dir, name) ]) image2mp4(**vars(args)) bstr = ConstBitStream(filename=out) ftyp, mdat, moov = list(Parser.parse(bstr)) for box in [ftyp, mdat, moov]: box.load(bstr) del bstr assert ftyp.header.type == b"ftyp" assert mdat.header.type == b"mdat" assert moov.header.type == b"moov" # MOOV.TRAK.MDIA.HDLR trak = moov.boxes[1] assert trak.boxes[-1].boxes[1].name == b"bzna_input\0" trak = moov.boxes[2] assert trak.boxes[-1].boxes[1].name == b"bzna_fname\0" # MOOV.TRAK.MDIA.MINF.STBL stbl = trak.boxes[-1].boxes[-1].boxes[-1] # MOOV.TRAK.MDIA.MINF.STBL.STSZ size = stbl.boxes[2].samples[0].entry_size # MOOV.TRAK.MDIA.MINF.STBL.STCO offset = stbl.boxes[4].entries[0].chunk_offset - \ mdat.header.start_pos - mdat.header.header_size assert mdat.data[offset:offset + size] == bytes(name, "utf-8") + b'\0' trak = moov.boxes[3] assert trak.boxes[-1].boxes[1].name == b"bzna_target\0" # MOOV.TRAK.MDIA.MINF.STBL stbl = trak.boxes[-1].boxes[-1].boxes[-1] # MOOV.TRAK.MDIA.MINF.STBL.STSZ size = stbl.boxes[2].samples[0].entry_size # MOOV.TRAK.MDIA.MINF.STBL.STCO offset = stbl.boxes[4].entries[0].chunk_offset - \ mdat.header.start_pos - mdat.header.header_size assert mdat.data[offset:offset + size] == int.to_bytes(1, 8, "little") trak = moov.boxes[4] assert trak.boxes[-1].boxes[1].name == b"bzna_thumb\0" finally: shutil.rmtree(".", ignore_errors=True)
def test_photo_heic_bytes(): bstr = ConstBitStream(filename="tests/data/photo.heic") boxes = [box for box in Parser.parse(bstr)] assert b''.join([bytes(box) for box in boxes]) != bstr.bytes for box in boxes: box.load(bstr) assert b''.join([bytes(box) for box in boxes]) == bstr.bytes
def test_video_bytes(): bstr = ConstBitStream(filename="tests/data/small_vid.mp4") boxes = [box for box in Parser.parse(bstr)] assert b''.join([bytes(box) for box in boxes]) != bstr.bytes for box in boxes: box.load(bstr) assert b''.join([bytes(box) for box in boxes]) == bstr.bytes
def _append_index_bzna_target(filename, moov_filename, mdat_targets_offset): moov = _load_moov(moov_filename) mvhd = next(find_boxes(moov.boxes, [b"mvhd"])) samples_trak = next(find_traks(moov.boxes, [b"bzna_input\0"])) # TRAK.MDIA.MINF.STBL stbl = samples_trak.boxes[-1].boxes[-1].boxes[-1] samples_offsets = next(find_boxes(stbl.boxes, [b"stco", b"co64"])) samples_sizes = next(find_boxes(stbl.boxes, [b"stsz"])) # bzna_target trak if next(find_traks(moov.boxes, [b"bzna_target\0"]), None) is not None: trak = next(find_traks(moov.boxes, [b"bzna_target\0"])) moov.boxes = [box for box in moov.boxes if box is not trak] targets_size = 0 targets = [] sizes = [] with open(filename, "rb") as container_file: for offset, size in zip( (o.chunk_offset for o in samples_offsets.entries), (s.entry_size for s in samples_sizes.samples)): container_file.seek(offset) sample_bstr = ConstBitStream(container_file.read(size)) # Create a new tmp object to hold the content sample_moov = next(find_boxes(Parser.parse(sample_bstr), [b"moov"])) sample_moov.load(sample_bstr) target = get_trak_sample_bytes(sample_bstr, sample_moov.boxes, b"bzna_target\0", 0) # Test subset is reached meaning that remaining entries will # not contain a target if target is None: break targets.append(target) sizes.append(len(target)) targets_size += len(target) # MOOV.TRAK trak = _make_bzna_target_trak(sizes, mdat_targets_offset, mvhd.next_track_id) moov.append(trak) mvhd.next_track_id += 1 moov.refresh_box_size() with open(filename, "rb+") as container_file, \ open(moov_filename, "wb") as moov_file: moov_file.write(bytes(moov)) container_file.seek(mdat_targets_offset) container_file.write(b''.join(targets)) return mdat_targets_offset + targets_size
def _index_bzna_thumb(filename, moov_filename, mdat_data_end): moov = _load_moov(moov_filename) mvhd = next(find_boxes(moov.boxes, [b"mvhd"])) samples_trak = next(find_traks(moov.boxes, [b"bzna_input\0"])) # TRAK.MDIA.MINF.STBL stbl = samples_trak.boxes[-1].boxes[-1].boxes[-1] samples_offsets = next(find_boxes(stbl.boxes, [b"stco", b"co64"])) samples_sizes = next(find_boxes(stbl.boxes, [b"stsz"])) # bzna_target trak if next(find_traks(moov.boxes, [b"bzna_thumb\0"]), None) is not None: trak = next(find_traks(moov.boxes, [b"bzna_thumb\0"])) moov.boxes = [box for box in moov.boxes if box is not trak] hvc1 = None offsets = [] sizes = [] with open(filename, "rb") as container_file: for offset, size in zip( (o.chunk_offset for o in samples_offsets.entries), (s.entry_size for s in samples_sizes.samples)): container_file.seek(offset) sample_bstr = ConstBitStream(container_file.read(size)) # Create a new tmp object to hold the content sample_moov = next(find_boxes(Parser.parse(sample_bstr), [b"moov"])) sample_moov.load(sample_bstr) # MOOV.TRAK trak = next(find_traks(sample_moov.boxes, [b"bzna_thumb\0"])) # MOOV.TRAK.MDIA.MINF.STBL stbl = trak.boxes[-1].boxes[-1].boxes[-1] co = next(find_boxes(stbl.boxes, [b"stco", b"co64"])) stsz = next(find_boxes(stbl.boxes, [b"stsz"])) if hvc1 is None: # MOOV.TRAK.MDIA.MINF.STBL.STSD._VC1 hvc1 = stbl.boxes[0].boxes[-1] offsets.append(offset + co.entries[0].chunk_offset) sizes.append(stsz.sample_size) # MOOV.TRAK trak = _make_bzna_thumb_trak(hvc1, sizes, offsets, mvhd.next_track_id) moov.append(trak) mvhd.next_track_id += 1 moov.refresh_box_size() with open(moov_filename, "wb") as moov_file: moov_file.write(bytes(moov)) return mdat_data_end
def _update_mdat_size(filename, mdat_data_end): bstr = ConstBitStream(filename=filename) mdat = next(find_boxes(Parser.parse(bstr, recursive=False), [b"mdat"])) del bstr mdat.header.box_ext_size = mdat_data_end - mdat.header.start_pos # Update mdat header with open(filename, "rb+") as container_file: container_file.seek(mdat.header.start_pos) container_file.write(bytes(mdat.header)) return mdat_data_end
def test_avc1_box(): bs = pack("uintbe:32, bytes:4, " "uintbe:8, uintbe:8, uintbe:8, uintbe:8, uintbe:8, uintbe:8, " "uintbe:16, " "uintbe:16, uintbe:16, uintbe:32, uintbe:32, uintbe:32, " "uintbe:16, uintbe:16, uintbe:16, uintbe:16, uintbe:16, uintbe:16, " "uintbe:32, " "uintbe:16, bytes:32, uintbe:16, " "intbe:16", 86, b"avc1", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 1, 0x0, 0x0, 0x0, 0x0, 0x0, 512, 512, 72, 0, 72, 0, 0x0, 1, b'\0' * 32, 24, -1) box_header = BoxHeader() avc1 = bx_def.AVC1(box_header) avc1.header.type = b"avc1" avc1.data_reference_index = 1 avc1.width = 512 avc1.height = 512 avc1.horizresolution = [72, 0] avc1.vertresolution = [72, 0] avc1.frame_count = 1 avc1.compressorname = b'\0' * 32 avc1.depth = 24 avc1.refresh_box_size() box = avc1 assert box.header.type == b"avc1" assert box.header.box_size == 86 assert box.data_reference_index == 1 assert box.width == 512 assert box.height == 512 assert box.horizresolution == [72, 0] assert box.vertresolution == [72, 0] assert box.frame_count == 1 assert box.compressorname == b'\0' * 32 assert box.depth == 24 assert len(box.boxes) == 0 assert bytes(next(Parser.parse(bs))) == bs.bytes assert bytes(box) == bs.bytes
def test__clean_boxes(): src = os.path.join(DATA_DIR, "transcode_steps/n02100735_8211.mp4") bstr = ConstBitStream(filename=src) boxes = [box for box in Parser.parse(bstr)] for box in boxes: box.load(bstr) _clean_boxes(boxes) assert len(boxes) == 3 ftyp = boxes[0] moov = boxes[2] ftyp.refresh_box_size() moov.refresh_box_size() assert ftyp.major_brand == 1769172845 # b"isom" assert ftyp.header.box_size == 20 assert ftyp.minor_version == 0 assert ftyp.compatible_brands == [1769172845] # b"isom" assert moov.header.box_size == 5493 assert len(moov.boxes) == 3 traks = [box for box in moov.boxes if box.header.type == b"trak"] assert len(traks) == 2 assert len(traks[0].boxes) == 2 # moov.trak.tkhd assert traks[0].boxes[0].header.flags == b"\x00\x00\x00" # moov.trak.mdia.hdlr assert traks[0].boxes[1].boxes[1].name == b"bzna_input\0" # moov.trak.mdia.minf.stbl.stco stco = traks[0].boxes[-1].boxes[-1].boxes[-1].boxes[-1] assert stco.entries[0].chunk_offset == 28 # moov.trak.tkhd assert traks[1].boxes[0].header.flags == b"\x00\x00\x03" # moov.trak.mdia.hdlr assert traks[1].boxes[1].boxes[1].name == b"bzna_thumb\0" # moov.trak.mdia.minf.stbl.stco stco = traks[1].boxes[-1].boxes[-1].boxes[-1].boxes[-1] assert stco.entries[0].chunk_offset == 221612
def test_mdhd_box_v1(): bs = pack("uintbe:32, bytes:4, uintbe:8, bits:24, " "uintbe:64, uintbe:64, uintbe:32, uintbe:64, " "bits:1, uint:5, uint:5, uint:5, " "bits:16", 44, b"mdhd", 1, b"\x00\x00\x00", 3596199850, 3596199850, 30000, 4200196, 0x1, 21, 14, 4, b"\x00" * 2) box_header = FullBoxHeader() mdhd = bx_def.MDHD(box_header) mdhd.header.type = b"mdhd" mdhd.header.version = 1 mdhd.header.flags = b"\x00\x00\x00" mdhd.creation_time = 3596199850 mdhd.modification_time = 3596199850 mdhd.timescale = 30000 mdhd.duration = 4200196 mdhd.language = [21, 14, 4] mdhd.pre_defined = 0 mdhd.refresh_box_size() box = mdhd assert box.header.type == b"mdhd" assert box.header.box_size == 44 assert box.header.version == 1 assert box.header.flags == b"\x00\x00\x00" assert box.creation_time == 3596199850 assert box.modification_time == 3596199850 assert box.timescale == 30000 assert box.duration == 4200196 assert box.language == [21, 14, 4] assert box.pre_defined == 0 assert bytes(next(Parser.parse(bs))) == bs.bytes assert bytes(box) == bs.bytes
def _parse(self): self._disk_file.seek(self._offset) pos = self._offset headers = (Parser.parse_header(ConstBitStream(chunk)) for chunk in iter(lambda: self._disk_file.read(32), b'')) for header in headers: if header.type != b"moov": pos += header.box_size self._disk_file.seek(pos) continue # Parse MOOV self._disk_file.seek(pos) moov_bstr = ConstBitStream(self._disk_file.read(header.box_size)) self._moov = next(Parser.parse(moov_bstr)) self._moov_pos = pos break
def test_nmhd_box(): bs = pack("uintbe:32, bytes:4, uintbe:8, bits:24", 12, b"nmhd", 0, b"\x00\x00\x00") box_header = FullBoxHeader() nmhd = bx_def.NMHD(box_header) nmhd.header.type = b"nmhd" nmhd.header.version = 0 nmhd.header.flags = b"\x00\x00\x00" nmhd.refresh_box_size() box = nmhd assert box.header.type == b"nmhd" assert box.header.box_size == 12 assert box.header.version == 0 assert box.header.flags == b"\x00\x00\x00" assert bytes(next(Parser.parse(bs))) == bs.bytes assert bytes(box) == bs.bytes
def test_co64_box(): bs = pack("uintbe:32, bytes:4, uintbe:8, bits:24, " "uintbe:32, uintbe:64, uintbe:64, uintbe:64", 40, b"co64", 0, b"\x00\x00\x00", 3, 0, 1, 2) box_header = FullBoxHeader() stco = bx_def.CO64(box_header) stco.header.type = b"co64" stco.header.version = 0 stco.header.flags = b"\x00\x00\x00" entry = stco.append_and_return() entry.chunk_offset = 0 entry = stco.append_and_return() entry.chunk_offset = 1 entry = stco.append_and_return() entry.chunk_offset = 2 stco.refresh_box_size() box = stco assert box.header.type == b"co64" assert box.header.box_size == 40 assert box.header.version == 0 assert box.header.flags == b"\x00\x00\x00" assert box.entry_count == 3 assert len(box.entries) == 3 assert box.entries[0].chunk_offset == 0 assert box.entries[1].chunk_offset == 1 assert box.entries[2].chunk_offset == 2 parsed_box = next(Parser.parse(bs)) parsed_box.load(bs) assert bytes(parsed_box) == bs.bytes assert bytes(box) == bs.bytes
def test_pasp_box(): bs = pack("uintbe:32, bytes:4, uintbe:32, uintbe:32", 16, b"pasp", 150, 157) box_header = BoxHeader() pasp = bx_def.PASP(box_header) pasp.header.type = b"pasp" pasp.h_spacing = 150 pasp.v_spacing = 157 pasp.refresh_box_size() box = pasp assert box.header.type == b"pasp" assert box.header.box_size == 16 assert box.h_spacing == 150 assert box.v_spacing == 157 assert bytes(next(Parser.parse(bs))) == bs.bytes assert bytes(box) == bs.bytes
def test_elst_box_v1(): bs = pack("uintbe:32, bytes:4, uintbe:8, bits:24, " "uintbe:32, uintbe:64, uintbe:64, uintbe:16, uintbe:16", 36, b"elst", 1, b"\x00\x00\x00", 1, 3000, 0, 1, 0) box_header = FullBoxHeader() elst = bx_def.ELST(box_header) elst.header.type = b"elst" elst.header.version = 1 elst.header.flags = b"\x00\x00\x00" entry = elst.append_and_return() entry.segment_duration = 3000 entry.media_time = 0 entry.media_rate_integer = 1 entry.media_rate_fraction = 0 elst.refresh_box_size() box = elst assert box.header.type == b"elst" assert box.header.box_size == 36 assert box.header.version == 1 assert box.header.flags == b"\x00\x00\x00" assert box.entry_count == 1 assert len(box.entries) == 1 assert box.entries[0].segment_duration == 3000 assert box.entries[0].media_time == 0 assert box.entries[0].media_rate_integer == 1 assert box.entries[0].media_rate_fraction == 0 parsed_box = next(Parser.parse(bs)) parsed_box.load(bs) assert bytes(parsed_box) == bs.bytes assert bytes(box) == bs.bytes
def test_clap_box(): bs = pack("uintbe:32, bytes:4, " "uintbe:32, uintbe:32, uintbe:32, uintbe:32, " "intbe:32, uintbe:32, intbe:32, uintbe:32", 40, b"clap", 500, 1, 333, 1, -12, 2, -179, 2) box_header = BoxHeader() clap = bx_def.CLAP(box_header) clap.header.type = b"clap" clap.clean_aperture_width_n = 500 clap.clean_aperture_width_d = 1 clap.clean_aperture_height_n = 333 clap.clean_aperture_height_d = 1 clap.horiz_off_n = -12 clap.horiz_off_d = 2 clap.vert_off_n = -179 clap.vert_off_d = 2 clap.refresh_box_size() box = clap assert box.header.type == b"clap" assert box.header.box_size == 40 assert box.clean_aperture_width_n == 500 assert box.clean_aperture_width_d == 1 assert box.clean_aperture_height_n == 333 assert box.clean_aperture_height_d == 1 assert box.horiz_off_n == -12 assert box.horiz_off_d == 2 assert box.vert_off_n == -179 assert box.vert_off_d == 2 assert bytes(next(Parser.parse(bs))) == bs.bytes assert bytes(box) == bs.bytes
def __init__(self, src, ar_format="mp4"): super().__init__(src, ar_format) bstr = ConstBitStream(filename=self._src) moov = next(find_boxes(Parser.parse(bstr, recursive=False), [b"moov"])) moov.parse_boxes(bstr, recursive=False) for trak in find_boxes(moov.boxes, [b"trak"]): trak.parse_boxes(bstr, recursive=False) mdia = next(find_boxes(trak.boxes, [b"mdia"])) mdia.parse_boxes(bstr, recursive=False) trak = next(find_traks(moov.boxes, [b"bzna_input\0"])) mdia = next(find_boxes(trak.boxes, [b"mdia"])) minf = next(find_boxes(mdia.boxes, [b"minf"])) minf.parse_boxes(bstr, recursive=False) stbl = next(find_boxes(minf.boxes, [b"stbl"])) stbl.parse_boxes(bstr, recursive=False) co = next(find_boxes(stbl.boxes, {b"stco", b"co64"})) sz = next(find_boxes(stbl.boxes, [b"stsz"])) self._input_co = co self._input_sz = sz trak = next(find_traks(moov.boxes, [b"bzna_fname\0"])) mdia = next(find_boxes(trak.boxes, [b"mdia"])) minf = next(find_boxes(mdia.boxes, [b"minf"])) minf.parse_boxes(bstr, recursive=False) stbl = next(find_boxes(minf.boxes, [b"stbl"])) stbl.parse_boxes(bstr, recursive=False) co = next(find_boxes(stbl.boxes, {b"stco", b"co64"})) sz = next(find_boxes(stbl.boxes, [b"stsz"])) self._fname_co = co self._fname_sz = sz self._len = max(self._input_co.entry_count, self._input_sz.sample_count)
def test_stsc_box(): bs = pack("uintbe:32, bytes:4, uintbe:8, bits:24, " "uintbe:32, uintbe:32, uintbe:32, uintbe:32", 28, b"stsc", 0, b"\x00\x00\x00", 1, 1, 1, 1) box_header = FullBoxHeader() stsc = bx_def.STSC(box_header) stsc.header.type = b"stsc" stsc.header.version = 0 stsc.header.flags = b"\x00\x00\x00" entry = stsc.append_and_return() entry.first_chunk = 1 entry.samples_per_chunk = 1 entry.sample_description_index = 1 stsc.refresh_box_size() box = stsc assert box.header.type == b"stsc" assert box.header.box_size == 28 assert box.header.version == 0 assert box.header.flags == b"\x00\x00\x00" assert box.entry_count == 1 assert len(box.entries) == 1 assert box.entries[0].first_chunk == 1 assert box.entries[0].samples_per_chunk == 1 assert box.entries[0].sample_description_index == 1 parsed_box = next(Parser.parse(bs)) parsed_box.load(bs) assert bytes(parsed_box) == bs.bytes assert bytes(box) == bs.bytes
def test_url__box(): bs = pack("uintbe:32, bytes:4, uintbe:8, bits:24", 12, b"url ", 0, b"\x00\x00\x01") box_header = FullBoxHeader() url_ = bx_def.URL_(box_header) url_.header.type = b"url " url_.header.version = 0 url_.header.flags = b"\x00\x00\x01" url_.refresh_box_size() box = url_ assert box.header.type == b"url " assert box.header.box_size == 12 assert box.header.version == 0 assert box.header.flags == b"\x00\x00\x01" assert box.location is None assert bytes(next(Parser.parse(bs))) == bs.bytes assert bytes(box) == bs.bytes
def _make_bzna_thumb_trak(hvc1, samples_sizes, samples_offsets, track_id): creation_time = 0 modification_time = 0 # MOOV.TRAK trak = make_vide_trak(creation_time, modification_time, b"bzna_thumb\0", samples_sizes, samples_offsets) # MOOV.TRAK.TKHD tkhd = trak.boxes[0] # "\x00\x00\x01" trak is enabled # "\x00\x00\x02" trak is used in the presentation # "\x00\x00\x04" trak is used in the preview # "\x00\x00\x08" trak size in not in pixel but in aspect ratio tkhd.header.flags = b"\x00\x00\x03" tkhd.track_id = track_id tkhd.width = [512, 512] tkhd.height = [512, 512] # MOOV.TRAK.MDIA.MINF.STBL.STSD stsd = trak.boxes[-1].boxes[-1].boxes[-1].boxes[0] # pop _VC1 stsd.pop() hvc1_bstr = ConstBitStream(bytes(hvc1)) hvc1 = next(Parser.parse(hvc1_bstr)) hvc1.load(hvc1_bstr) # pop CLAP and PASP hvc1.pop() hvc1.pop() stsd.append(hvc1) return trak