From 7f05ad42539af6ef900d429efda4e45e19e5bb93 Mon Sep 17 00:00:00 2001 From: WyattBlue Date: Thu, 22 Jan 2026 23:34:07 -0500 Subject: [PATCH] Make av/format pure --- av/{format.pyx => format.py} | 76 ++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 33 deletions(-) rename av/{format.pyx => format.py} (74%) diff --git a/av/format.pyx b/av/format.py similarity index 74% rename from av/format.pyx rename to av/format.py index 2eb386649..a0bf0bd90 100644 --- a/av/format.pyx +++ b/av/format.py @@ -1,22 +1,28 @@ -cimport libav as lib - -from av.descriptor cimport wrap_avclass - from enum import Flag +import cython +import cython.cimports.libav as lib +from cython.cimports.av.descriptor import wrap_avclass -cdef object _cinit_bypass_sentinel = object() +_cinit_bypass_sentinel = cython.declare(object, object()) -cdef ContainerFormat build_container_format(lib.AVInputFormat* iptr, lib.AVOutputFormat* optr): + +@cython.cfunc +def build_container_format( + iptr: cython.pointer[lib.AVInputFormat], optr: cython.pointer[lib.AVOutputFormat] +) -> ContainerFormat: if not iptr and not optr: raise ValueError("needs input format or output format") - cdef ContainerFormat format = ContainerFormat.__new__(ContainerFormat, _cinit_bypass_sentinel) + format: ContainerFormat = ContainerFormat.__new__( + ContainerFormat, _cinit_bypass_sentinel + ) format.iptr = iptr format.optr = optr format.name = optr.name if optr else iptr.name return format +# fmt: off class Flags(Flag): no_file = lib.AVFMT_NOFILE need_number: "Needs '%d' in filename." = lib.AVFMT_NEEDNUMBER @@ -36,8 +42,11 @@ class Flags(Flag): # If not set the timestamp will be shifted in `av_write_frame()` and `av_interleaved_write_frame()` # so they start from 0. The user or muxer can override this through AVFormatContext.avoid_negative_ts seek_to_pts: "Seeking is based on PTS" = lib.AVFMT_SEEK_TO_PTS +# fmt: on + -cdef class ContainerFormat: +@cython.cclass +class ContainerFormat: """Descriptor of a container format. :param str name: The name of the format. @@ -59,7 +68,7 @@ def __cinit__(self, name, mode=None): self.iptr = lib.av_find_input_format(name) if mode is None or mode == "w": - self.optr = lib.av_guess_format(name, NULL, NULL) + self.optr = lib.av_guess_format(name, cython.NULL, cython.NULL) if not self.iptr and not self.optr: raise ValueError(f"no container format {name!r}") @@ -81,30 +90,30 @@ def options(self): @property def input(self): """An input-only view of this format.""" - if self.iptr == NULL: + if self.iptr == cython.NULL: return None - elif self.optr == NULL: + elif self.optr == cython.NULL: return self else: - return build_container_format(self.iptr, NULL) + return build_container_format(self.iptr, cython.NULL) @property def output(self): """An output-only view of this format.""" - if self.optr == NULL: + if self.optr == cython.NULL: return None - elif self.iptr == NULL: + elif self.iptr == cython.NULL: return self else: - return build_container_format(NULL, self.optr) + return build_container_format(cython.NULL, self.optr) @property def is_input(self): - return self.iptr != NULL + return self.iptr != cython.NULL @property def is_output(self): - return self.optr != NULL + return self.optr != cython.NULL @property def long_name(self): @@ -114,7 +123,7 @@ def long_name(self): @property def extensions(self): - cdef set exts = set() + exts: set = set() if self.iptr and self.iptr.extensions: exts.update(self.iptr.extensions.split(",")) if self.optr and self.optr.extensions: @@ -128,9 +137,8 @@ def flags(self): :rtype: int """ - return ( - (self.iptr.flags if self.iptr else 0) | - (self.optr.flags if self.optr else 0) + return (self.iptr.flags if self.iptr else 0) | ( + self.optr.flags if self.optr else 0 ) @property @@ -138,32 +146,34 @@ def no_file(self): return bool(self.flags & lib.AVFMT_NOFILE) -cdef get_output_format_names(): - names = set() - cdef const lib.AVOutputFormat *ptr - cdef void *opaque = NULL +@cython.cfunc +def get_output_format_names() -> set: + names: set = set() + ptr: cython.pointer[cython.const[lib.AVOutputFormat]] + opaque: cython.p_void = cython.NULL while True: - ptr = lib.av_muxer_iterate(&opaque) + ptr = lib.av_muxer_iterate(cython.address(opaque)) if ptr: names.add(ptr.name) else: break return names -cdef get_input_format_names(): - names = set() - cdef const lib.AVInputFormat *ptr - cdef void *opaque = NULL + +@cython.cfunc +def get_input_format_names() -> set: + names: set = set() + ptr: cython.pointer[cython.const[lib.AVInputFormat]] + opaque: cython.p_void = cython.NULL while True: - ptr = lib.av_demuxer_iterate(&opaque) + ptr = lib.av_demuxer_iterate(cython.address(opaque)) if ptr: names.add(ptr.name) else: break return names + formats_available = get_output_format_names() formats_available.update(get_input_format_names()) - - format_descriptor = wrap_avclass(lib.avformat_get_class())