def __init__(self, file_or_filename): self.__file = file_or_filename if not hasattr(self.__file, 'read'): self.__file = open(file_or_filename, 'rb') if self.__file.read(4).decode('ASCII') != 'RIFF': raise ValueError('Non-RIFF file detected.') self.length = unpack('<i', self.__file.read(4))[0] if self.__file.read(4).decode('ASCII') != 'AVI ': raise ValueError('Non-AVI file detected.') with closing(RIFFChunk(self.__file)) as hdrl_chunk: self.avi_header = AviFileHeader.load(file_like=hdrl_chunk) self.stream_definitions = [] for i in range(self.avi_header.streams): self.stream_definitions.append( AviStreamDefinition.load(stream_id=len(self.stream_definitions), file_like=hdrl_chunk)) self.stream_content = None while not self.stream_content: try: self.stream_content = AviMoviList.load(self.__file) except ChunkTypeException: pass self.index_v1 = None try: self.index_v1 = AviV1Index.load(self.__file) self.stream_content.apply_index(self.index_v1) except ChunkTypeException: if AVIF.MUSTUSEINDEX in self.avi_header.flags: raise ValueError('AVI header requires use of index and index is missing.')
def load(cls, file_like): """Create an `AviV1Index` structure. This method creates an :py:class:`AviV1Index` from the contents of an AVI 'idx1' list. Parameters ---------- file_like : file-like A file-like object positioned at the start of a index structure. Returns ------- :py:class:`AviV1Index` An `AviV1Index` that may be used to read the data for this chunk. """ with closing(RIFFChunk(file_like)) as idx1_chunk: if idx1_chunk.getname() != b'idx1': raise ChunkTypeException() index = [] while idx1_chunk.tell() < idx1_chunk.getsize(): index.append(AviV1IndexEntry.load(idx1_chunk)) return cls(index=index)
def load(cls, file_like): """Create an `AviStreamHeader` This method creates a new :py:class:`AviStreamHeader` from the contents of an AVI 'strh' list. Parameters ---------- file_like : file-like A file-like object positioned at the start of a 'strh' list. Returns ------- :py:class:`AviStreamHeader` """ with closing(RIFFChunk(file_like)) as strh_chunk: size = strh_chunk.getsize() if size not in (48, 56, 64): raise ChunkFormatException( 'Invalid Stream Header Size ({})'.format( strh_chunk.getsize())) if size == 48: return cls(*unpack('<4s4sI2H8I', strh_chunk.read()), tuple()) unpack_format = '<4s4sI2H8I4h' if strh_chunk.getsize() == 64: unpack_format = '<4s4sI2H8I4l' strh_values = unpack(unpack_format, strh_chunk.read()) return cls(*strh_values[:-4], strh_values[-4:])
def load(cls, file_like): """Create an AviRecList structure. This method creates an :py:class:`AviRecList` from the contents of an AVI 'rec ' list. Note that this does not actually load the data associated with the contained stream chunks. Parameters ---------- file_like : file-like A file-like object positioned at the start of a 'rec ' list. Returns ------- :py:class:`AviRecList` An `AviRecList` containing :py:class:`AviStreamChunk` objects. """ with closing(RIFFChunk(file_like)) as rec_list: if not rec_list.islist() or rec_list.getname() != b'rec ': raise ChunkTypeException() data_chunks = [] while rec_list.tell() < rec_list.getsize() - 1: data_chunks.append(AviStreamChunk.load(rec_list)) return cls(data_chunks=data_chunks)
def load(cls, file_like): """Consumes a junk chunk. Parameters ---------- file_like : file-like A file-like object containing a 'JUNK' chunk. """ with closing(RIFFChunk(file_like)) as junk_chunk: if junk_chunk.getname() != b'JUNK': raise ChunkTypeException()
def load(cls, file_like): """Create an AviStreamChunk structure. This method creates an :py:class:`AviStreamChunk` from the contents of an AVI 'movi' or 'rec ' list. Note that this does not actually load the data associated with the stream chunk. Parameters ---------- file_like : file-like A file-like object positioned at the start of a stream data chunk. Returns ------- :py:class:`AviStreamChunk` An `AviStreamChunk` that may be used to read the data for this chunk. """ with closing(RIFFChunk(file_like, align=True)) as strm_chunk: chunk_id = strm_chunk.getname().decode('ASCII') try: stream_id = int(chunk_id[:2]) except ValueError: strm_chunk.seek(0) raise ChunkFormatException('Could not decode stream index: ' '{} @ offset 0x{:08x}'.format( chunk_id[:2], file_like.tell())) try: data_type = STREAM_DATA_TYPES(chunk_id[2:]) except ValueError: strm_chunk.seek(0) raise ChunkFormatException( 'Could not determine stream data type: ' '{} @ offset 0x{:08x}'.format(chunk_id[2:], file_like.tell())) base_file = file_like while isinstance(base_file, RIFFChunk): base_file = base_file.file absolute_offset = base_file.tell() size = strm_chunk.getsize() return cls(stream_id=stream_id, data_type=data_type, base_file=base_file, absolute_offset=absolute_offset, size=size)
def load(cls, stream_id, file_like): """Create an `AviStreamDefinition` This method creates a new :py:class:`AviStreamDefinition` from the contents of an AVI 'strl' list. Parameters ---------- stream_id : int The id number of the stream. file_like : file-like A file-like object positioned at the start of a 'strl' list. Returns ------- :py:class:`AviStreamDefinition` """ with closing(RIFFChunk(file_like)) as strl_chunk: if not strl_chunk.islist() or strl_chunk.getlisttype() != 'strl': raise ChunkTypeException('Non-"strl" Chunk: {}, {}, {}'.format( strl_chunk.getname().decode('ASCII'), strl_chunk.getsize(), strl_chunk.getlisttype())) strh = AviStreamHeader.load(strl_chunk) strf = AviStreamFormat.load(stream_header=strh, file_like=strl_chunk) strd = None strn = None try: with rollback(strl_chunk): strd = AviStreamData.load(file_like=strl_chunk) with rollback(strl_chunk): strn = AviStreamName.load(file_like=strl_chunk) with rollback(strl_chunk): _ = AviJunkChunk.load(file_like=strl_chunk) except EOFError: pass return cls(stream_id=stream_id, stream_header=strh, stream_format=strf, stream_data=strd, stream_name=strn)
def load(cls, file_like): """Create a new :py:class:`AviStreamData` instance. Creates a new instance from a file-like object positioned at the start of a 'strd' chunk. Parameters ---------- file_like : file-like A file-like object containing a 'strd' chunk. Returns ------- :py:class:`AviStreamData` Stream data instance for this stream. """ with closing(RIFFChunk(file_like)) as strd_chunk: if strd_chunk.getname() == b'strd': return cls(strd_chunk.read()) raise ChunkTypeException()
def load(cls, stream_header, file_like, force_color_table=False): """Create a new :py:class:`BitmapInfoHeaders` instance from a RIFF file. Parameters ---------- stream_header : :py:class:`AviStreamHeader` Stream header structure for the stream file_like : file-like A file-like object positioned at the start of 'strf' chunk. force_color_table : bool Force an attempt to load a color table. Returns ------- :py:class:`BitmapInfoHeaders` The stream format instance for this stream. """ with closing(RIFFChunk(file_like)) as strf_chunk: return cls.load_from_file(strf_chunk, force_color_table=force_color_table)
def load(cls, stream_header, file_like): """Create an `UnparsedStreamFormat` instance This method creates a new instance of :py:class:`UnparsedStreamFormat` from the contents of an AVI 'strf' list. Parameters ---------- stream_header : :py:class:`AviStreamHeader` Header associated with the stream. file_like : file-like A file-like object positioned at the start of a 'strh' list. Returns ------- object Instance of :py:class:`UnparsedStreamFormat`. """ with closing(RIFFChunk(file_like)) as strf_chunk: return cls(strf_chunk.read())
def load(cls, file_like): """Create a new :py:class:`AviStreamName` instance. Creates a new instance from a file-like object positioned at the start of a 'strn' chunk. Parameters ---------- file_like : file-like A file-like object containing a 'strn' chunk. Returns ------- :py:class:`AviStreamName` Stream data instance for this stream. """ with closing(RIFFChunk(file_like)) as strn_chunk: if strn_chunk.getname() == b'strn': raw_bytes = strn_chunk.read() name = raw_bytes[:raw_bytes.index(b'\0')].decode('ASCII') return cls(name=name) raise ChunkTypeException()
def load(cls, file_like): """Create an AviMoviList structure. This method creates an :py:class:`AviMoviList` from the contents of an AVI 'movi' list. Note that this does not actually load the data associated with the contained stream chunks. Parameters ---------- file_like : file-like A file-like object positioned at the start of a 'movi' list. Returns ------- :py:class:`AviMoviList` An `AviMoviList` containing :py:class:`AviStreamChunk` objects. """ with closing(RIFFChunk(file=file_like)) as movi_list: if not movi_list.islist() or movi_list.getlisttype() != 'movi': raise ChunkTypeException('Chunk: {}, {}, {}'.format( movi_list.getname().decode('ASCII'), movi_list.getsize(), movi_list.getlisttype())) base_file = file_like while isinstance(base_file, RIFFChunk): base_file = base_file.file absolute_offset = base_file.tell() data_chunks = [] while movi_list.tell() < movi_list.getsize() - 1: try: with rollback(movi_list, reraise=True): rec_list = AviRecList.load(file_like=movi_list) data_chunks.extend(rec_list.data_chunks) except ChunkTypeException: data_chunks.append(AviStreamChunk.load(movi_list)) return cls(absolute_offset=absolute_offset, data_chunks=data_chunks)
def load(cls, file_like): with closing(RIFFChunk(file_like)) as avih_chunk: avih_values = unpack('14I', avih_chunk.read(56)) return cls(*avih_values[:10], avih_values[10:])