Skip to content

Commit

Permalink
Use builtin Enum class more often
Browse files Browse the repository at this point in the history
  • Loading branch information
WyattBlue committed Nov 13, 2024
1 parent 7a97124 commit 16c2517
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 104 deletions.
33 changes: 17 additions & 16 deletions av/codec/context.pyi
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
from enum import Enum, Flag
from fractions import Fraction
from typing import Any, Literal
from typing import ClassVar, Literal

from av.enum import EnumFlag, EnumItem
from av.packet import Packet

from .codec import Codec

class ThreadType(EnumFlag):
NONE: int
FRAME: int
SLICE: int
AUTO: int
class ThreadType(Flag):
NONE: ClassVar[ThreadType]
FRAME: ClassVar[ThreadType]
SLICE: ClassVar[ThreadType]
AUTO: ClassVar[ThreadType]

class SkipType(EnumItem):
NONE: int
DEFAULT: int
NONREF: int
BIDIR: int
NONINTRA: int
NONKEY: int
ALL: int
class SkipType(Enum):
NONE: ClassVar[SkipType]
DEFAULT: ClassVar[SkipType]
NONREF: ClassVar[SkipType]
BIDIR: ClassVar[SkipType]
NONINTRA: ClassVar[SkipType]
NONKEY: ClassVar[SkipType]
ALL: ClassVar[SkipType]

class Flags(EnumFlag):
NONE: int
Expand Down Expand Up @@ -67,8 +68,8 @@ class CodecContext:
bit_rate: int | None
bit_rate_tolerance: int
thread_count: int
thread_type: Any
skip_frame: Any
thread_type: ThreadType
skip_frame: SkipType

# flags
unaligned: bool
Expand Down
38 changes: 19 additions & 19 deletions av/codec/context.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ from av.error cimport err_check
from av.packet cimport Packet
from av.utils cimport avrational_to_fraction, to_avrational

from enum import Enum, Flag

from av.dictionary import Dictionary


Expand Down Expand Up @@ -39,22 +41,20 @@ cdef CodecContext wrap_codec_context(lib.AVCodecContext *c_ctx, const lib.AVCode
return py_ctx


ThreadType = define_enum("ThreadType", __name__, (
("NONE", 0),
("FRAME", lib.FF_THREAD_FRAME, "Decode more than one frame at once"),
("SLICE", lib.FF_THREAD_SLICE, "Decode more than one part of a single frame at once"),
("AUTO", lib.FF_THREAD_SLICE | lib.FF_THREAD_FRAME, "Decode using both FRAME and SLICE methods."),
), is_flags=True)
class ThreadType(Flag):
NONE = 0
FRAME: "Decode more than one frame at once" = lib.FF_THREAD_FRAME
SLICE: "Decode more than one part of a single frame at once" = lib.FF_THREAD_SLICE
AUTO: "Decode using both FRAME and SLICE methods." = lib.FF_THREAD_SLICE | lib.FF_THREAD_FRAME

SkipType = define_enum("SkipType", __name__, (
("NONE", lib.AVDISCARD_NONE, "Discard nothing"),
("DEFAULT", lib.AVDISCARD_DEFAULT, "Discard useless packets like 0 size packets in AVI"),
("NONREF", lib.AVDISCARD_NONREF, "Discard all non reference"),
("BIDIR", lib.AVDISCARD_BIDIR, "Discard all bidirectional frames"),
("NONINTRA", lib.AVDISCARD_NONINTRA, "Discard all non intra frames"),
("NONKEY", lib.AVDISCARD_NONKEY, "Discard all frames except keyframes"),
("ALL", lib.AVDISCARD_ALL, "Discard all"),
))
class SkipType(Enum):
NONE: "Discard nothing" = lib.AVDISCARD_NONE
DEFAULT: "Discard useless packets like 0 size packets in AVI" = lib.AVDISCARD_DEFAULT
NONREF: "Discard all non reference" = lib.AVDISCARD_NONREF
BIDIR: "Discard all bidirectional frames" = lib.AVDISCARD_BIDIR
NONINTRA: "Discard all non intra frames" = lib.AVDISCARD_NONINTRA
NONKEY: "Discard all frames except keyframes" = lib.AVDISCARD_NONKEY
ALL: "Discard all" = lib.AVDISCARD_ALL

Flags = define_enum("Flags", __name__, (
("NONE", 0),
Expand Down Expand Up @@ -617,13 +617,13 @@ cdef class CodecContext:
Wraps :ffmpeg:`AVCodecContext.thread_type`.
"""
return ThreadType.get(self.ptr.thread_type, create=True)
return ThreadType(self.ptr.thread_type)

@thread_type.setter
def thread_type(self, value):
if self.is_open:
raise RuntimeError("Cannot change thread_type after codec is open.")
self.ptr.thread_type = ThreadType[value].value
self.ptr.thread_type = value.value

@property
def skip_frame(self):
Expand All @@ -632,11 +632,11 @@ cdef class CodecContext:
Wraps :ffmpeg:`AVCodecContext.skip_frame`.
"""
return SkipType._get(self.ptr.skip_frame, create=True)
return SkipType(self.ptr.skip_frame)

@skip_frame.setter
def skip_frame(self, value):
self.ptr.skip_frame = SkipType[value].value
self.ptr.skip_frame = value.value

@property
def delay(self):
Expand Down
35 changes: 2 additions & 33 deletions av/enum.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -126,37 +126,6 @@ copyreg.constructor(_unpickle)


cdef class EnumItem:
"""
Enumerations are when an attribute may only take on a single value at once, and
they are represented as integers in the FFmpeg API. We associate names with each
value that are easier to operate with.
Consider :data:`av.codec.context.SkipType`, which is the type of the :attr:`CodecContext.skip_frame` attribute::
>>> fh = av.open(video_path)
>>> cc = fh.streams.video[0].codec_context
>>> # The skip_frame attribute has a name and value:
>>> cc.skip_frame.name
'DEFAULT'
>>> cc.skip_frame.value
0
>>> # You can compare it to strings and ints:
>>> cc.skip_frame == 'DEFAULT'
True
>>> cc.skip_frame == 0
True
>>> # You can assign strings and ints:
>>> cc.skip_frame = 'NONKEY'
>>> cc.skip_frame == 'NONKEY'
True
>>> cc.skip_frame == 32
True
"""

cdef readonly str name
cdef readonly int value
cdef Py_hash_t _hash
Expand All @@ -167,7 +136,7 @@ cdef class EnumItem:

self.name = name
self.value = value
self.__doc__ = doc # This is not cdef because it doesn't work if it is.
self.__doc__ = doc

# We need to establish a hash that doesn't collide with anything that
# would return true from `__eq__`. This is because these enums (vs
Expand Down Expand Up @@ -196,7 +165,7 @@ cdef class EnumItem:

def __eq__(self, other):
if isinstance(other, str):
if self.name == other: # The quick method.
if self.name == other:
return True

try:
Expand Down
6 changes: 3 additions & 3 deletions av/option.pyi
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .enum import EnumFlag, EnumItem
from enum import Enum, Flag

class OptionType(EnumItem):
class OptionType(Enum):
FLAGS: int
INT: int
INT64: int
Expand All @@ -20,7 +20,7 @@ class OptionType(EnumItem):
CHANNEL_LAYOUT: int
BOOL: int

class OptionFlags(EnumFlag):
class OptionFlags(Flag):
ENCODING_PARAM: int
DECODING_PARAM: int
AUDIO_PARAM: int
Expand Down
66 changes: 33 additions & 33 deletions av/option.pyx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
cimport libav as lib

from av.enum cimport define_enum
from av.utils cimport flag_in_bitfield

from enum import Enum, Flag


cdef object _cinit_sentinel = object()

Expand All @@ -15,27 +16,26 @@ cdef Option wrap_option(tuple choices, const lib.AVOption *ptr):
return obj


OptionType = define_enum("OptionType", __name__, (
("FLAGS", lib.AV_OPT_TYPE_FLAGS),
("INT", lib.AV_OPT_TYPE_INT),
("INT64", lib.AV_OPT_TYPE_INT64),
("DOUBLE", lib.AV_OPT_TYPE_DOUBLE),
("FLOAT", lib.AV_OPT_TYPE_FLOAT),
("STRING", lib.AV_OPT_TYPE_STRING),
("RATIONAL", lib.AV_OPT_TYPE_RATIONAL),
("BINARY", lib.AV_OPT_TYPE_BINARY),
("DICT", lib.AV_OPT_TYPE_DICT),
("UINT64", lib.AV_OPT_TYPE_UINT64),
("CONST", lib.AV_OPT_TYPE_CONST),
("IMAGE_SIZE", lib.AV_OPT_TYPE_IMAGE_SIZE),
("PIXEL_FMT", lib.AV_OPT_TYPE_PIXEL_FMT),
("SAMPLE_FMT", lib.AV_OPT_TYPE_SAMPLE_FMT),
("VIDEO_RATE", lib.AV_OPT_TYPE_VIDEO_RATE),
("DURATION", lib.AV_OPT_TYPE_DURATION),
("COLOR", lib.AV_OPT_TYPE_COLOR),
("CHANNEL_LAYOUT", lib.AV_OPT_TYPE_CHLAYOUT),
("BOOL", lib.AV_OPT_TYPE_BOOL),
))
class OptionType(Enum):
FLAGS = lib.AV_OPT_TYPE_FLAGS
INT = lib.AV_OPT_TYPE_INT
INT64 = lib.AV_OPT_TYPE_INT64
DOUBLE = lib.AV_OPT_TYPE_DOUBLE
FLOAT = lib.AV_OPT_TYPE_FLOAT
STRING = lib.AV_OPT_TYPE_STRING
RATIONAL = lib.AV_OPT_TYPE_RATIONAL
BINARY = lib.AV_OPT_TYPE_BINARY
DICT = lib.AV_OPT_TYPE_DICT
UINT64 = lib.AV_OPT_TYPE_UINT64
CONST = lib.AV_OPT_TYPE_CONST
IMAGE_SIZE = lib.AV_OPT_TYPE_IMAGE_SIZE
PIXEL_FMT = lib.AV_OPT_TYPE_PIXEL_FMT
SAMPLE_FMT = lib.AV_OPT_TYPE_SAMPLE_FMT
VIDEO_RATE = lib.AV_OPT_TYPE_VIDEO_RATE
DURATION = lib.AV_OPT_TYPE_DURATION
COLOR = lib.AV_OPT_TYPE_COLOR
CHANNEL_LAYOUT = lib.AV_OPT_TYPE_CHLAYOUT
BOOL = lib.AV_OPT_TYPE_BOOL

cdef tuple _INT_TYPES = (
lib.AV_OPT_TYPE_FLAGS,
Expand All @@ -48,16 +48,16 @@ cdef tuple _INT_TYPES = (
lib.AV_OPT_TYPE_BOOL,
)

OptionFlags = define_enum("OptionFlags", __name__, (
("ENCODING_PARAM", lib.AV_OPT_FLAG_ENCODING_PARAM),
("DECODING_PARAM", lib.AV_OPT_FLAG_DECODING_PARAM),
("AUDIO_PARAM", lib.AV_OPT_FLAG_AUDIO_PARAM),
("VIDEO_PARAM", lib.AV_OPT_FLAG_VIDEO_PARAM),
("SUBTITLE_PARAM", lib.AV_OPT_FLAG_SUBTITLE_PARAM),
("EXPORT", lib.AV_OPT_FLAG_EXPORT),
("READONLY", lib.AV_OPT_FLAG_READONLY),
("FILTERING_PARAM", lib.AV_OPT_FLAG_FILTERING_PARAM),
), is_flags=True)
class OptionFlags(Flag):
ENCODING_PARAM = lib.AV_OPT_FLAG_ENCODING_PARAM
DECODING_PARAM = lib.AV_OPT_FLAG_DECODING_PARAM
AUDIO_PARAM = lib.AV_OPT_FLAG_AUDIO_PARAM
VIDEO_PARAM = lib.AV_OPT_FLAG_VIDEO_PARAM
SUBTITLE_PARAM = lib.AV_OPT_FLAG_SUBTITLE_PARAM
EXPORT = lib.AV_OPT_FLAG_EXPORT
READONLY = lib.AV_OPT_FLAG_READONLY
FILTERING_PARAM = lib.AV_OPT_FLAG_FILTERING_PARAM


cdef class BaseOption:
def __cinit__(self, sentinel):
Expand Down Expand Up @@ -106,7 +106,7 @@ cdef class BaseOption:
cdef class Option(BaseOption):
@property
def type(self):
return OptionType._get(self.ptr.type, create=True)
return OptionType(self.ptr.type)

@property
def offset(self):
Expand Down

0 comments on commit 16c2517

Please sign in to comment.