From 23a1cc40b3c11ba0cb958d660de0764b81155f9e Mon Sep 17 00:00:00 2001 From: WyattBlue Date: Wed, 13 Nov 2024 19:57:56 -0500 Subject: [PATCH] convert Properties to enum.Flag, simplify codec property access --- av/codec/codec.pyi | 60 +++++++++++++++++++++++------------- av/codec/codec.pyx | 77 ++++++++++++++++++++-------------------------- 2 files changed, 72 insertions(+), 65 deletions(-) diff --git a/av/codec/codec.pyi b/av/codec/codec.pyi index 6cb421430..fe2d2fd41 100644 --- a/av/codec/codec.pyi +++ b/av/codec/codec.pyi @@ -1,5 +1,6 @@ +from enum import Flag from fractions import Fraction -from typing import Literal, overload +from typing import ClassVar, Literal, overload from av.audio.codeccontext import AudioCodecContext from av.audio.format import AudioFormat @@ -11,14 +12,14 @@ from av.video.format import VideoFormat from .context import CodecContext -class Properties(EnumFlag): - NONE: int - INTRA_ONLY: int - LOSSY: int - LOSSLESS: int - REORDER: int - BITMAP_SUB: int - TEXT_SUB: int +class Properties(Flag): + NONE: ClassVar[Properties] + INTRA_ONLY: ClassVar[Properties] + LOSSY: ClassVar[Properties] + LOSSLESS: ClassVar[Properties] + REORDER: ClassVar[Properties] + BITMAP_SUB: ClassVar[Properties] + TEXT_SUB: ClassVar[Properties] class Capabilities(EnumFlag): NONE: int @@ -46,25 +47,40 @@ class Capabilities(EnumFlag): class UnknownCodecError(ValueError): ... class Codec: - is_encoder: bool - is_decoder: bool + @property + def is_encoder(self) -> bool: ... + @property + def is_decoder(self) -> bool: ... descriptor: Descriptor - name: str - long_name: str - type: Literal["video", "audio", "data", "subtitle", "attachment"] - id: int + @property + def name(self) -> str: ... + @property + def long_name(self) -> str: ... + @property + def type(self) -> Literal["video", "audio", "data", "subtitle", "attachment"]: ... + @property + def id(self) -> int: ... frame_rates: list[Fraction] | None audio_rates: list[int] | None video_formats: list[VideoFormat] | None audio_formats: list[AudioFormat] | None - properties: Properties + + @property + def properties(self) -> int: ... + @property + def intra_only(self) -> bool: ... + @property + def lossy(self) -> bool: ... + @property + def lossless(self) -> bool: ... + @property + def reorder(self) -> bool: ... + @property + def bitmap_sub(self) -> bool: ... + @property + def text_sub(self) -> bool: ... + capabilities: Capabilities - intra_only: bool - lossy: bool - lossless: bool - reorder: bool - bitmap_sub: bool - text_sub: bool draw_horiz_band: bool dr1: bool hwaccel: bool diff --git a/av/codec/codec.pyx b/av/codec/codec.pyx index da66d7184..9b29cb178 100644 --- a/av/codec/codec.pyx +++ b/av/codec/codec.pyx @@ -4,9 +4,10 @@ from av.enum cimport define_enum from av.utils cimport avrational_to_fraction from av.video.format cimport get_video_format +from enum import Flag -cdef object _cinit_sentinel = object() +cdef object _cinit_sentinel = object() cdef Codec wrap_codec(const lib.AVCodec *ptr): cdef Codec codec = Codec(_cinit_sentinel) @@ -15,34 +16,14 @@ cdef Codec wrap_codec(const lib.AVCodec *ptr): codec._init() return codec - -Properties = define_enum("Properties", "av.codec", ( - ("NONE", 0), - ("INTRA_ONLY", lib.AV_CODEC_PROP_INTRA_ONLY, - """Codec uses only intra compression. - Video and audio codecs only."""), - ("LOSSY", lib.AV_CODEC_PROP_LOSSY, - """Codec supports lossy compression. Audio and video codecs only. - - Note: A codec may support both lossy and lossless - compression modes."""), - ("LOSSLESS", lib.AV_CODEC_PROP_LOSSLESS, - """Codec supports lossless compression. Audio and video codecs only."""), - ("REORDER", lib.AV_CODEC_PROP_REORDER, - """Codec supports frame reordering. That is, the coded order (the order in which - the encoded packets are output by the encoders / stored / input to the - decoders) may be different from the presentation order of the corresponding - frames. - - For codecs that do not have this property set, PTS and DTS should always be - equal."""), - ("BITMAP_SUB", lib.AV_CODEC_PROP_BITMAP_SUB, - """Subtitle codec is bitmap based - Decoded AVSubtitle data can be read from the AVSubtitleRect->pict field."""), - ("TEXT_SUB", lib.AV_CODEC_PROP_TEXT_SUB, - """Subtitle codec is text based. - Decoded AVSubtitle data can be read from the AVSubtitleRect->ass field."""), -), is_flags=True) +class Properties(Flag): + NONE = 0 + INTRA_ONLY = lib.AV_CODEC_PROP_INTRA_ONLY + LOSSY = lib.AV_CODEC_PROP_LOSSY + LOSSLESS = lib.AV_CODEC_PROP_LOSSLESS + REORDER = lib.AV_CODEC_PROP_REORDER + BITMAP_SUB = lib.AV_CODEC_PROP_BITMAP_SUB + TEXT_SUB = lib.AV_CODEC_PROP_TEXT_SUB Capabilities = define_enum("Capabilities", "av.codec", ( ("NONE", 0), @@ -287,21 +268,33 @@ cdef class Codec: i += 1 return ret - # NOTE: there are some overlaps, which we defer to how `ffmpeg -codecs` - # handles them (by prefering the capablity to the property). - # Also, LOSSLESS and LOSSY don't have to agree. - - @Properties.property + @property def properties(self): - """Flag property of :class:`.Properties`""" return self.desc.props - intra_only = properties.flag_property("INTRA_ONLY") - lossy = properties.flag_property("LOSSY") # Defer to capability. - lossless = properties.flag_property("LOSSLESS") # Defer to capability. - reorder = properties.flag_property("REORDER") - bitmap_sub = properties.flag_property("BITMAP_SUB") - text_sub = properties.flag_property("TEXT_SUB") + @property + def intra_only(self): + return bool(self.desc.props & lib.AV_CODEC_PROP_INTRA_ONLY) + + @property + def lossy(self): + return bool(self.desc.props & lib.AV_CODEC_PROP_LOSSY) + + @property + def lossless(self): + return bool(self.desc.props & lib.AV_CODEC_PROP_LOSSLESS) + + @property + def reorder(self): + return bool(self.desc.props & lib.AV_CODEC_PROP_REORDER) + + @property + def bitmap_sub(self): + return bool(self.desc.props & lib.AV_CODEC_PROP_BITMAP_SUB) + + @property + def text_sub(self): + return bool(self.desc.props & lib.AV_CODEC_PROP_TEXT_SUB) @Capabilities.property def capabilities(self): @@ -324,8 +317,6 @@ cdef class Codec: auto_threads = capabilities.flag_property("AUTO_THREADS") variable_frame_size = capabilities.flag_property("VARIABLE_FRAME_SIZE") avoid_probing = capabilities.flag_property("AVOID_PROBING") - # intra_only = capabilities.flag_property("INTRA_ONLY") # Dupes. - # lossless = capabilities.flag_property("LOSSLESS") # Dupes. hardware = capabilities.flag_property("HARDWARE") hybrid = capabilities.flag_property("HYBRID") encoder_reordered_opaque = capabilities.flag_property("ENCODER_REORDERED_OPAQUE")