From 16c25172d3b97a37f545f73c147de77885de2638 Mon Sep 17 00:00:00 2001 From: WyattBlue Date: Wed, 13 Nov 2024 05:14:21 -0500 Subject: [PATCH] Use builtin Enum class more often --- av/codec/context.pyi | 33 +++++++++++----------- av/codec/context.pyx | 38 ++++++++++++------------- av/enum.pyx | 35 ++--------------------- av/option.pyi | 6 ++-- av/option.pyx | 66 ++++++++++++++++++++++---------------------- 5 files changed, 74 insertions(+), 104 deletions(-) diff --git a/av/codec/context.pyi b/av/codec/context.pyi index 8c50ba456..8600deaaa 100644 --- a/av/codec/context.pyi +++ b/av/codec/context.pyi @@ -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 @@ -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 diff --git a/av/codec/context.pyx b/av/codec/context.pyx index a1e95048c..528a73872 100644 --- a/av/codec/context.pyx +++ b/av/codec/context.pyx @@ -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 @@ -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), @@ -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): @@ -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): diff --git a/av/enum.pyx b/av/enum.pyx index a21d66e81..9217e67d6 100644 --- a/av/enum.pyx +++ b/av/enum.pyx @@ -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 @@ -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 @@ -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: diff --git a/av/option.pyi b/av/option.pyi index b7ba670f2..3132f4a02 100644 --- a/av/option.pyi +++ b/av/option.pyi @@ -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 @@ -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 diff --git a/av/option.pyx b/av/option.pyx index 0c7b5fb28..e58c4c13f 100644 --- a/av/option.pyx +++ b/av/option.pyx @@ -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() @@ -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, @@ -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): @@ -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):