54 lines
1.8 KiB
Python
54 lines
1.8 KiB
Python
# RozK
|
|
|
|
from . import libav
|
|
from .codec import Codec
|
|
from .stream import 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)
|
|
if self.video_stream is None:
|
|
raise Exception("Failed to find a video stream")
|
|
self.audio_stream = self._find_stream(libav.AVMEDIA_TYPE_AUDIO)
|
|
if self.audio_stream is None:
|
|
raise Exception("Failed to find an audio stream")
|
|
|
|
@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 None
|
|
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)
|