# RozK from . import libav from .codec import Codec from .stream import NullStream, Stream from .packet import Packet class Demuxer: __slots__ = '_context', 'video_stream', 'audio_stream' def __init__(self, path): self._context = libav.format_alloc_context() if not self._context: raise MemoryError errcode = libav.format_open_input(self._context, "file:" + path) if errcode < 0: raise Exception(f"Failed to open: {path}") errcode = libav.format_find_stream_info(self._context) if errcode < 0: libav.format_close_input(self._context) raise Exception("Failed to find stream info") self.video_stream = self._find_stream(libav.AVMEDIA_TYPE_VIDEO) self.audio_stream = self._find_stream(libav.AVMEDIA_TYPE_AUDIO) @property def nb_streams(self): if not self._context: return 0 return self._context.contents.nb_streams def _find_stream(self, type): index, codec_ref = libav.format_find_best_stream(self._context, type) if index < 0 or not codec_ref: return NullStream() parameters = self._context.contents.streams[index].contents.codecpar return Stream(index, Codec(codec_ref), parameters) def read_packet(self): if not self._context: return None packet = Packet() errcode = libav.read_frame(self._context, packet) if errcode < 0: return None return packet def close(self): if self._context: libav.format_close_input(self._context)