diff --git a/av/container/input.py b/av/container/input.py index 97037457f..c7e82a84b 100644 --- a/av/container/input.py +++ b/av/container/input.py @@ -153,6 +153,7 @@ def demux(self, *args, **kwargs): i: cython.uint packet: Packet + read_packet: cython.pointer[lib.AVPacket] ret: cython.int self.set_timeout(self.read_timeout) @@ -165,22 +166,35 @@ def demux(self, *args, **kwargs): raise ValueError(f"stream index {i} out of range") include_stream[i] = True + # Pre-allocate a AVPacket that is reused as the read buffer. + with cython.nogil: + read_packet = lib.av_packet_alloc() + if read_packet == cython.NULL: + raise MemoryError("Could not allocate packet") + while True: - packet = Packet() + # Reset the read buffer + with cython.nogil: + lib.av_packet_unref(read_packet) try: self.start_timeout() with cython.nogil: - ret = lib.av_read_frame(self.ptr, packet.ptr) + ret = lib.av_read_frame(self.ptr, read_packet) self.err_check(ret) except EOFError: break - if include_stream[packet.ptr.stream_index]: + if include_stream[read_packet.stream_index]: # If AVFMTCTX_NOHEADER is set in ctx_flags, then new streams # may also appear in av_read_frame(). # http://ffmpeg.org/doxygen/trunk/structAVFormatContext.html # TODO: find better way to handle this - if packet.ptr.stream_index < len(self.streams): + if read_packet.stream_index < len(self.streams): + # Move the encoded data out of the read buffer into a + # fresh Packet for the caller. + packet = Packet() + with cython.nogil: + lib.av_packet_move_ref(packet.ptr, read_packet) packet._stream = self.streams[packet.ptr.stream_index] # Keep track of this so that remuxing is easier. packet.ptr.time_base = packet._stream.ptr.time_base @@ -197,6 +211,8 @@ def demux(self, *args, **kwargs): finally: self.set_timeout(None) free(include_stream) + if read_packet != cython.NULL: + lib.av_packet_free(cython.address(read_packet)) def decode(self, *args, **kwargs): """decode(streams=None, video=None, audio=None, subtitles=None, data=None) diff --git a/include/avcodec.pxd b/include/avcodec.pxd index 8c610ea67..28dfcfed9 100644 --- a/include/avcodec.pxd +++ b/include/avcodec.pxd @@ -407,6 +407,8 @@ cdef extern from "libavcodec/avcodec.h" nogil: cdef void av_packet_free(AVPacket **) cdef int av_new_packet(AVPacket*, int) cdef int av_packet_ref(AVPacket *dst, const AVPacket *src) + cdef void av_packet_unref(AVPacket *pkt) + cdef void av_packet_move_ref(AVPacket *dst, AVPacket *src) cdef void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb) cdef enum AVSubtitleType: