Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions av/container/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,8 @@ def add_stream_from_template(
:param \\**kwargs: Set attributes for the stream.
:rtype: The new :class:`~av.stream.Stream`.
"""
template.container._assert_open()

if opaque is None:
opaque = template.type != "video"

Expand Down
14 changes: 7 additions & 7 deletions av/filter/context.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import weakref

import cython
import cython.cimports.libav as lib
from cython.cimports.av.audio.frame import alloc_audio_frame
Expand All @@ -23,7 +21,7 @@ def wrap_filter_context(
graph: Graph, filter: Filter, ptr: cython.pointer[lib.AVFilterContext]
) -> FilterContext:
self: FilterContext = FilterContext(_cinit_sentinel)
self._graph = weakref.ref(graph)
self._graph = graph
self.filter = filter
self.ptr = ptr

Expand Down Expand Up @@ -110,14 +108,16 @@ def link_to(

@property
def graph(self):
if graph := self._graph():
return graph
else:
raise RuntimeError("graph is unallocated")
return self._graph

def push(self, frame: Frame | None):
res: cython.int

# av_buffersrc_write_frame() dereferences graph internals that only
# exist after configuration; pushing first would segfault.
if self._kind == _KIND_SOURCE or frame is None:
self._graph.configure()

if frame is None:
with cython.nogil:
res = lib.av_buffersrc_write_frame(self.ptr, cython.NULL)
Expand Down
17 changes: 7 additions & 10 deletions av/filter/graph.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,18 @@ from av.filter.context cimport FilterContext


cdef class Graph:
# Fields are laid out in declaration order: pointers first, then the two
# ints paired up, so there are no padding holes between them.
cdef object __weakref__

cdef lib.AVFilterGraph *ptr

cdef dict _name_counts
cdef dict[size_t, FilterContext] _context_by_ptr
cdef dict[str, list[FilterContext]] _context_by_type
cdef readonly bint configured
cpdef configure(self, bint auto_buffer=*, bint force=*)
cdef int _nb_filters_seen

cdef dict _name_counts
cpdef configure(self, bint auto_buffer=*, bint force=*)
cdef str _get_unique_name(self, str name)
cdef list[FilterContext] _get_context_by_type(self, str type)

cdef void _register_context(self, FilterContext)
cdef void _auto_register(self)
cdef int _nb_filters_seen
cdef dict[size_t, FilterContext] _context_by_ptr
cdef dict[str, list[FilterContext]] _context_by_type
cdef list[FilterContext] _video_sources
cdef list[FilterContext] _audio_sources
16 changes: 6 additions & 10 deletions av/filter/graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ def __cinit__(self):
self._nb_filters_seen = 0
self._context_by_ptr = {}
self._context_by_type = {}
self._video_sources = []
self._audio_sources = []

def __dealloc__(self):
if self.ptr:
Expand Down Expand Up @@ -113,10 +111,6 @@ def _register_context(self, ctx: FilterContext) -> cython.void:
name: str = ctx.filter.ptr.name
self._context_by_ptr[cython.cast(cython.size_t, ctx.ptr)] = ctx
self._context_by_type.setdefault(name, []).append(ctx)
if name == "buffer":
self._video_sources.append(ctx)
elif name == "abuffer":
self._audio_sources.append(ctx)

@cython.cfunc
def _auto_register(self) -> cython.void:
Expand Down Expand Up @@ -250,11 +244,13 @@ def push(self, frame, at: cython.int = -1):
every buffer source matching the frame's type.
"""
if frame is None:
contexts = self._video_sources + self._audio_sources
contexts = self._get_context_by_type("buffer") + self._get_context_by_type(
"abuffer"
)
elif isinstance(frame, VideoFrame):
contexts = self._video_sources
contexts = self._get_context_by_type("buffer")
elif isinstance(frame, AudioFrame):
contexts = self._audio_sources
contexts = self._get_context_by_type("abuffer")
else:
raise ValueError(
f"can only AudioFrame, VideoFrame or None; got {type(frame)}"
Expand All @@ -273,7 +269,7 @@ def push(self, frame, at: cython.int = -1):

def vpush(self, frame: VideoFrame | None, at: cython.int = -1):
"""Like :meth:`push`, but only for :class:`.VideoFrame`."""
contexts = self._video_sources
contexts = self._get_context_by_type("buffer")
if at >= 0:
if at >= len(contexts):
raise IndexError(
Expand Down
7 changes: 7 additions & 0 deletions av/filter/link.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,13 @@ def is_output(self):
def name(self):
return lib.avfilter_pad_get_name(self.base_ptr, self.index)

@property
def type(self):
media_type = lib.av_get_media_type_string(
lib.avfilter_pad_get_type(self.base_ptr, self.index)
)
return "unknown" if media_type == cython.NULL else media_type


@cython.final
@cython.cclass
Expand Down