예제 #1
0
    def find_media_segments(self, reader: ByteReader) -> List[MediaSegment]:
        try:
            ebml_id, size = read_element_header(reader)
            assert ebml_id == 0x1A45DFA3
            reader.skip(size)

            segment_id, _ = read_element_header(reader)
            assert segment_id == 0x18538067

            segment_reader = RegionByteReader(reader,
                                              reader.position,
                                              size=None)

            segment_info = next(element
                                for element in iter_elements(segment_reader)
                                if element.element_id == 0x1549A966)
            timestamp_scale = next(
                (element for element in iter_elements(segment_info.reader)
                 if element.element_id == 0x2AD7B1), None)
            timestamp_scale_value = read_uint(
                timestamp_scale.reader
            ) if timestamp_scale is not None else 1000000

            clusters = [
                Cluster(element, timestamp_scale_value)
                for element in iter_elements(segment_reader)
                if element.element_id == 0x1F43B675
            ]
            return [
                MediaSegment(offset=cluster.element.offset,
                             size=cluster.element.full_size,
                             time=cluster.timestamp) for cluster in clusters
            ]
        finally:
            reader.close()
예제 #2
0
    def find_media_segments(self, reader: ByteReader) -> List[MediaSegment]:
        try:
            moov = MovieBox(
                next(box for box in iter_boxes(reader) if box.kind == b"moov"))
            moofs = [
                MovieFragmentBox(box) for box in iter_boxes(reader)
                if box.kind == b"moof"
            ]

            def fragment_size(fragment_index):
                if fragment_index < len(moofs) - 1:
                    return moofs[
                        fragment_index +
                        1].box.offset - moofs[fragment_index].box.offset
                else:
                    movie_size = reader.size
                    return movie_size - moofs[fragment_index].box.offset

            return [
                MediaSegment(moof.box.offset, fragment_size(i),
                             self._moof_start_time(moov, moof))
                for i, moof in enumerate(moofs)
            ]
        finally:
            reader.close()
예제 #3
0
def read_vint(reader: ByteReader, raw: bool = False):
    header_byte = ord(reader.read(1))
    if header_byte == 0:
        raise WrongFile("VINT with zero header byte")
    tail_length = 0
    mask = 0x80
    while header_byte & mask == 0:
        tail_length += 1
        mask >>= 1

    header_number_part = header_byte & ~mask if not raw else header_byte
    return parse_big_endian_number(
        bytes([header_number_part]) + reader.read(tail_length))
예제 #4
0
    def __init__(self, reader: ByteReader):
        self.offset = reader.position
        size = parse_big_endian_number(reader.read(4))
        kind = reader.read(4)
        if size == 1:
            size = parse_big_endian_number(reader.read(8))
        elif size == 0:
            size = reader.end - reader.position
        if kind == b"uuid":
            kind += reader.read(16)
        content_offset = reader.position
        content_size = size - (content_offset - self.offset)

        self.kind = kind
        self.full_size = size
        self.reader = RegionByteReader(reader, content_offset, content_size)
        reader.skip(content_size)
예제 #5
0
def read_uint(reader: ByteReader, default: int = 0) -> int:
    if reader.ended:
        return default
    return parse_big_endian_number(reader.read())
예제 #6
0
def iter_elements(reader: ByteReader):
    while not reader.ended:
        element = read_element(reader)
        yield element
        reader.skip(element.reader.size)
예제 #7
0
def iter_boxes(reader: ByteReader, rewind: bool = False):
    if rewind:
        reader.position = reader.start
    while not reader.ended:
        yield Box(reader)