Example #1
0
    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.')
Example #2
0
    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)
Example #3
0
    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:])
Example #4
0
    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)
Example #5
0
    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()
Example #6
0
    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)
Example #7
0
    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)
Example #8
0
    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()
Example #9
0
    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)
Example #10
0
    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())
Example #11
0
    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()
Example #12
0
    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)
Example #13
0
 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:])