Files
rk_pve/mp4/demuxer.py
2025-10-03 18:08:00 +02:00

67 lines
2.5 KiB
Python

# People's Video Editor: high quality, GPU accelerated mp4 editor
# Copyright (C) 2025 Roz K <roz@rozk.net>
#
# This file is part of People's Video Editor.
#
# People's Video Editor is free software: you can redistribute it and/or modify it under the terms of the
# GNU General Public License as published by the Free Software Foundation, either version 3 of the License,
# or (at your option) any later version.
#
# Foobar is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with Foobar.
# If not, see <https://www.gnu.org/licenses/>.
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)