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
示例#10
0
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
示例#11
0
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
示例#12
0
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)
示例#13
0
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
示例#14
0
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
示例#15
0
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
示例#16
0
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
示例#17
0
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
示例#18
0
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
示例#19
0
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
示例#20
0
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
示例#21
0
文件: file.py 项目: 5l1v3r1/Benzina
    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
示例#22
0
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
示例#23
0
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
示例#24
0
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
示例#25
0
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
示例#26
0
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
示例#27
0
    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)
示例#28
0
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
示例#29
0
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
示例#30
0
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