Files
rk_pve/mp4/demuxer.py

50 lines
1.6 KiB
Python
Raw Normal View History

2025-10-03 13:25:14 +02:00
# RozK
from . import libav
2025-10-03 15:10:49 +02:00
from .codec import Codec
from .stream import NullStream, Stream
from .packet import Packet
2025-10-03 13:25:14 +02:00
class Demuxer:
2025-10-03 16:55:38 +02:00
__slots__ = '_context', 'video_stream', 'audio_stream'
2025-10-03 13:25:14 +02:00
def __init__(self, path):
2025-10-03 16:55:38 +02:00
self._context = libav.format_alloc_context()
if not self._context:
2025-10-03 15:10:49 +02:00
raise MemoryError
2025-10-03 16:55:38 +02:00
errcode = libav.format_open_input(self._context, "file:" + path)
2025-10-03 15:10:49 +02:00
if errcode < 0:
raise Exception(f"Failed to open: {path}")
2025-10-03 16:55:38 +02:00
errcode = libav.format_find_stream_info(self._context)
2025-10-03 15:10:49 +02:00
if errcode < 0:
2025-10-03 16:55:38 +02:00
libav.format_close_input(self._context)
2025-10-03 15:10:49 +02:00
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)
2025-10-03 17:07:17 +02:00
@property
def nb_streams(self):
if not self._context:
return 0
return self._context.contents.nb_streams
2025-10-03 15:10:49 +02:00
def _find_stream(self, type):
2025-10-03 16:55:38 +02:00
index, codec_ref = libav.format_find_best_stream(self._context, type)
2025-10-03 15:10:49 +02:00
if index < 0 or not codec_ref:
return NullStream()
2025-10-03 16:55:38 +02:00
parameters = self._context.contents.streams[index].contents.codecpar
return Stream(index, Codec(codec_ref), parameters)
2025-10-03 13:25:14 +02:00
def read_packet(self):
2025-10-03 16:55:38 +02:00
if not self._context:
2025-10-03 15:10:49 +02:00
return None
packet = Packet()
2025-10-03 16:55:38 +02:00
errcode = libav.read_frame(self._context, packet)
2025-10-03 15:10:49 +02:00
if errcode < 0:
return None
return packet
2025-10-03 13:25:14 +02:00
def close(self):
2025-10-03 16:55:38 +02:00
if self._context:
libav.format_close_input(self._context)