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
1 change: 0 additions & 1 deletion av/opaque.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ cdef void noop_free(void *opaque, uint8_t *data) noexcept nogil

cdef class OpaqueContainer:
cdef dict _objects

cdef lib.AVBufferRef *add(self, object v)
cdef object get(self, char *name)
cdef object pop(self, char *name)
Expand Down
7 changes: 0 additions & 7 deletions av/option.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,13 @@ cimport libav as lib


cdef class BaseOption:

cdef const lib.AVOption *ptr


cdef class Option(BaseOption):

cdef readonly tuple choices


cdef class OptionChoice(BaseOption):

cdef readonly bint is_default


cdef Option wrap_option(tuple choices, const lib.AVOption *ptr)

cdef OptionChoice wrap_option_choice(const lib.AVOption *ptr, bint is_default)
107 changes: 65 additions & 42 deletions av/option.pyx → av/option.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
cimport libav as lib
from libc.stdint cimport uint64_t

from enum import Enum, Flag

import cython
import cython.cimports.libav as lib
from cython import NULL, bint
from cython.cimports.libc.stdint import uint64_t

_cinit_sentinel = cython.declare(object, object())

cdef object _cinit_sentinel = object()

cdef Option wrap_option(tuple choices, const lib.AVOption *ptr):
@cython.cfunc
def wrap_option(
choices: tuple, ptr: cython.pointer[cython.const[lib.AVOption]]
) -> Option:
if ptr == NULL:
return None
cdef Option obj = Option(_cinit_sentinel)
obj: Option = Option(_cinit_sentinel)
obj.ptr = ptr
obj.choices = choices
return obj


cdef flag_in_bitfield(uint64_t bitfield, uint64_t flag):
# Not every flag exists in every version of FFMpeg, so we define them to 0.
if not flag:
return None
@cython.cfunc
def flag_in_bitfield(bitfield: uint64_t, flag: uint64_t) -> bool:
return bool(bitfield & flag)


Expand All @@ -43,16 +46,6 @@ class OptionType(Enum):
CHANNEL_LAYOUT = lib.AV_OPT_TYPE_CHLAYOUT
BOOL = lib.AV_OPT_TYPE_BOOL

cdef tuple _INT_TYPES = (
lib.AV_OPT_TYPE_FLAGS,
lib.AV_OPT_TYPE_INT,
lib.AV_OPT_TYPE_INT64,
lib.AV_OPT_TYPE_PIXEL_FMT,
lib.AV_OPT_TYPE_SAMPLE_FMT,
lib.AV_OPT_TYPE_DURATION,
lib.AV_OPT_TYPE_CHLAYOUT,
lib.AV_OPT_TYPE_BOOL,
)

class OptionFlags(Flag):
ENCODING_PARAM = lib.AV_OPT_FLAG_ENCODING_PARAM
Expand All @@ -65,7 +58,23 @@ class OptionFlags(Flag):
FILTERING_PARAM = lib.AV_OPT_FLAG_FILTERING_PARAM


cdef class BaseOption:
_INT_TYPES = cython.declare(
tuple,
(
lib.AV_OPT_TYPE_FLAGS,
lib.AV_OPT_TYPE_INT,
lib.AV_OPT_TYPE_INT64,
lib.AV_OPT_TYPE_PIXEL_FMT,
lib.AV_OPT_TYPE_SAMPLE_FMT,
lib.AV_OPT_TYPE_DURATION,
lib.AV_OPT_TYPE_CHLAYOUT,
lib.AV_OPT_TYPE_BOOL,
),
)


@cython.cclass
class BaseOption:
def __cinit__(self, sentinel):
if sentinel is not _cinit_sentinel:
raise RuntimeError(f"Cannot construct av.{self.__class__.__name__}")
Expand All @@ -82,34 +91,41 @@ def help(self):
def flags(self):
return self.ptr.flags

# Option flags
@property
def is_encoding_param(self):
return flag_in_bitfield(self.ptr.flags, lib.AV_OPT_FLAG_ENCODING_PARAM)

@property
def is_decoding_param(self):
return flag_in_bitfield(self.ptr.flags, lib.AV_OPT_FLAG_DECODING_PARAM)

@property
def is_audio_param(self):
return flag_in_bitfield(self.ptr.flags, lib.AV_OPT_FLAG_AUDIO_PARAM)

@property
def is_video_param(self):
return flag_in_bitfield(self.ptr.flags, lib.AV_OPT_FLAG_VIDEO_PARAM)

@property
def is_subtitle_param(self):
return flag_in_bitfield(self.ptr.flags, lib.AV_OPT_FLAG_SUBTITLE_PARAM)

@property
def is_export(self):
return flag_in_bitfield(self.ptr.flags, lib.AV_OPT_FLAG_EXPORT)

@property
def is_readonly(self):
return flag_in_bitfield(self.ptr.flags, lib.AV_OPT_FLAG_READONLY)

@property
def is_filtering_param(self):
return flag_in_bitfield(self.ptr.flags, lib.AV_OPT_FLAG_FILTERING_PARAM)


cdef class Option(BaseOption):
@cython.cclass
class Option(BaseOption):
@property
def type(self):
return OptionType(self.ptr.type)
Expand All @@ -126,45 +142,52 @@ def offset(self):
def default(self):
if self.ptr.type in _INT_TYPES:
return self.ptr.default_val.i64
if self.ptr.type in (lib.AV_OPT_TYPE_DOUBLE, lib.AV_OPT_TYPE_FLOAT,
lib.AV_OPT_TYPE_RATIONAL):
if self.ptr.type in (
lib.AV_OPT_TYPE_DOUBLE,
lib.AV_OPT_TYPE_FLOAT,
lib.AV_OPT_TYPE_RATIONAL,
):
return self.ptr.default_val.dbl
if self.ptr.type in (lib.AV_OPT_TYPE_STRING, lib.AV_OPT_TYPE_BINARY,
lib.AV_OPT_TYPE_IMAGE_SIZE, lib.AV_OPT_TYPE_VIDEO_RATE,
lib.AV_OPT_TYPE_COLOR):
if self.ptr.type in (
lib.AV_OPT_TYPE_STRING,
lib.AV_OPT_TYPE_BINARY,
lib.AV_OPT_TYPE_IMAGE_SIZE,
lib.AV_OPT_TYPE_VIDEO_RATE,
lib.AV_OPT_TYPE_COLOR,
):
return self.ptr.default_val.str if self.ptr.default_val.str != NULL else ""

def _norm_range(self, value):
if self.ptr.type in _INT_TYPES:
return int(value)
return value

@property
def min(self):
return self._norm_range(self.ptr.min)
if self.ptr.type in _INT_TYPES:
return int(self.ptr.min)
return self.ptr.min

@property
def max(self):
return self._norm_range(self.ptr.max)
if self.ptr.type in _INT_TYPES:
return int(self.ptr.max)
return self.ptr.max

def __repr__(self):
return (
f"<av.{self.__class__.__name__} {self.name}"
f" ({self.type} at *0x{self.offset:x}) at 0x{id(self):x}>"
)
return f"<av.{self.__class__.__name__} {self.name} ({self.type} at *0x{self.offset:x}) at 0x{id(self):x}>"


cdef OptionChoice wrap_option_choice(const lib.AVOption *ptr, bint is_default):
@cython.cfunc
def wrap_option_choice(
ptr: cython.pointer[cython.const[lib.AVOption]], is_default: bint
) -> OptionChoice | None:
if ptr == NULL:
return None

cdef OptionChoice obj = OptionChoice(_cinit_sentinel)
obj: OptionChoice = OptionChoice(_cinit_sentinel)
obj.ptr = ptr
obj.is_default = is_default
return obj


cdef class OptionChoice(BaseOption):
@cython.cclass
class OptionChoice(BaseOption):
"""
Represents AV_OPT_TYPE_CONST options which are essentially
choices of non-const option with same unit.
Expand Down
Loading