cimport libav as lib from cpython.bytes cimport PyBytes_FromStringAndSize from dataclasses import dataclass @dataclass class AudioChannel: name: str description: str def __repr__(self): return f"<av.AudioChannel '{self.name}' ({self.description})>" cdef object _cinit_bypass_sentinel cdef AudioLayout get_audio_layout(lib.AVChannelLayout c_layout): """Get an AudioLayout from Cython land.""" cdef AudioLayout layout = AudioLayout.__new__(AudioLayout, _cinit_bypass_sentinel) layout._init(c_layout) return layout cdef class AudioLayout: def __init__(self, layout): if layout is _cinit_bypass_sentinel: return if type(layout) is str: ret = lib.av_channel_layout_from_string(&c_layout, layout) if ret != 0: raise ValueError(f"Invalid layout: {layout}") elif isinstance(layout, AudioLayout): c_layout = (<AudioLayout>layout).layout else: raise TypeError(f"layout must be of type: string | av.AudioLayout, got {type(layout)}") self._init(c_layout) cdef _init(self, lib.AVChannelLayout layout): self.layout = layout def __repr__(self): return f"<av.{self.__class__.__name__} {self.name!r}>" def __eq__(self, other): return isinstance(other, AudioLayout) and self.name == other.name and self.nb_channels == other.nb_channels @property def nb_channels(self): return self.layout.nb_channels @property def channels(self): cdef lib.AVChannel channel cdef char buf[16] cdef char buf2[128] results = [] for index in range(self.layout.nb_channels): channel = lib.av_channel_layout_channel_from_index(&self.layout, index); size = lib.av_channel_name(buf, sizeof(buf), channel) - 1 size2 = lib.av_channel_description(buf2, sizeof(buf2), channel) - 1 results.append( AudioChannel( PyBytes_FromStringAndSize(buf, size).decode("utf-8"), PyBytes_FromStringAndSize(buf2, size2).decode("utf-8"), ) ) return tuple(results) @property def name(self) -> str: """The canonical name of the audio layout.""" cdef char layout_name[128] cdef int ret ret = lib.av_channel_layout_describe(&self.layout, layout_name, sizeof(layout_name)) if ret < 0: raise RuntimeError(f"Failed to get layout name: {ret}") return layout_name
Memory