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.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								#
							 | 
						
					
						
							
								
									
										
										
										
											2025-10-03 18:15:25 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								# People's Video Editor 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.
							 | 
						
					
						
							
								
									
										
										
										
											2025-10-03 18:08:00 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								#
							 | 
						
					
						
							
								
									
										
										
										
											2025-10-03 18:15:25 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								# You should have received a copy of the GNU General Public License along with People's Video Editor.
							 | 
						
					
						
							
								
									
										
										
										
											2025-10-03 18:08:00 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								# If not, see <https://www.gnu.org/licenses/>.
							 | 
						
					
						
							
								
									
										
										
										
											2025-10-03 13:25:14 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								from . import libav
							 | 
						
					
						
							
								
									
										
										
										
											2025-10-03 15:10:49 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from .codec import Codec
							 | 
						
					
						
							
								
									
										
										
										
											2025-10-03 17:16:14 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								from .stream import Stream
							 | 
						
					
						
							
								
									
										
										
										
											2025-10-03 15:10:49 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								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)
							 | 
						
					
						
							
								
									
										
										
										
											2025-10-03 17:16:14 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if self.video_stream is None:
							 | 
						
					
						
							
								
									
										
										
										
											2025-10-03 18:08:09 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            libav.format_close_input(self._context)
							 | 
						
					
						
							
								
									
										
										
										
											2025-10-03 17:16:14 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            raise Exception("Failed to find a video stream")
							 | 
						
					
						
							
								
									
										
										
										
											2025-10-03 15:10:49 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        self.audio_stream = self._find_stream(libav.AVMEDIA_TYPE_AUDIO)
							 | 
						
					
						
							
								
									
										
										
										
											2025-10-03 17:16:14 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								        if self.audio_stream is None:
							 | 
						
					
						
							
								
									
										
										
										
											2025-10-03 18:08:09 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            libav.format_close_input(self._context)
							 | 
						
					
						
							
								
									
										
										
										
											2025-10-03 17:16:14 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            raise Exception("Failed to find an audio stream")
							 | 
						
					
						
							
								
									
										
										
										
											2025-10-03 15:10:49 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2025-10-03 18:08:09 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    def __del__(self):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if self._context:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            libav.format_close_input(self._context)
							 | 
						
					
						
							
								
									
										
										
										
											2025-10-03 17:07:17 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											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:
							 | 
						
					
						
							
								
									
										
										
										
											2025-10-03 17:16:14 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								            return None
							 | 
						
					
						
							
								
									
										
										
										
											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
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2025-10-03 18:08:09 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								    @property
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								    def nb_streams(self):
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        if not self._context:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								            return 0
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								        return self._context.contents.nb_streams
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											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
							 |