Skip to content

Commit

Permalink
convert Properties to enum.Flag, simplify codec property access
Browse files Browse the repository at this point in the history
  • Loading branch information
WyattBlue committed Nov 14, 2024
1 parent e1aaee0 commit 23a1cc4
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 65 deletions.
60 changes: 38 additions & 22 deletions av/codec/codec.pyi
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
77 changes: 34 additions & 43 deletions av/codec/codec.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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),
Expand Down Expand Up @@ -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):
Expand All @@ -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")
Expand Down

0 comments on commit 23a1cc4

Please sign in to comment.