Files
rk_pve/mp4/decoder.py

61 lines
2.3 KiB
Python
Raw Normal View History

2025-10-03 18:08:00 +02:00
# 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/>.
2025-10-03 15:10:49 +02:00
from . import libav
2025-10-03 16:55:38 +02:00
from .packet import Packet
2025-10-03 15:10:49 +02:00
from .frame import Frame
class Decoder:
2025-10-03 17:07:17 +02:00
__slots__ = '_context'
2025-10-03 15:10:49 +02:00
2025-10-03 16:55:38 +02:00
def __init__(self, stream):
self._context = libav.codec_alloc_context(stream.codec)
if not self._context:
2025-10-03 15:10:49 +02:00
raise MemoryError
2025-10-03 16:55:38 +02:00
errcode = libav.codec_parameters_to_context(self._context, stream.parameters)
if errcode < 0:
libav.codec_free_context(self._context)
raise Exception("Failed to set context parameters")
errcode = libav.codec_open(self._context, stream.codec)
2025-10-03 15:10:49 +02:00
if errcode < 0:
2025-10-03 16:55:38 +02:00
libav.codec_free_context(self._context)
2025-10-03 15:10:49 +02:00
raise Exception("Failed to open codec context")
def __del__(self):
2025-10-03 16:55:38 +02:00
if self._context:
libav.codec_free_context(self._context)
2025-10-03 15:10:49 +02:00
2025-10-03 16:55:38 +02:00
def _receive(self):
frames = []
2025-10-03 15:10:49 +02:00
while True:
frame = Frame()
2025-10-03 16:55:38 +02:00
errcode = libav.codec_receive_frame(self._context, frame)
if errcode in (libav.AVERROR_EOF, libav.AVERROR_EAGAIN):
2025-10-03 15:10:49 +02:00
break
2025-10-03 16:55:38 +02:00
elif errcode < 0:
errstring = libav.strerror(errcode)
2025-10-03 17:16:14 +02:00
raise Exception(f"Failed to receive frame: {errstring}")
2025-10-03 16:55:38 +02:00
frames.append(frame)
return frames
2025-10-03 15:10:49 +02:00
def decode(self, packet):
2025-10-03 16:55:38 +02:00
if not self._context:
2025-10-03 15:10:49 +02:00
return None
2025-10-03 16:55:38 +02:00
errcode = libav.codec_send_packet(self._context, packet)
if errcode < 0:
errstring = libav.strerror(errcode)
raise Exception(f"Failed to send packet: {errstring}")
return self._receive()