Skip to content

Commit

Permalink
Use Flag enum for format flags
Browse files Browse the repository at this point in the history
  • Loading branch information
WyattBlue committed Dec 1, 2024
1 parent 49c0605 commit eb8428d
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 102 deletions.
81 changes: 35 additions & 46 deletions av/format.pyi
Original file line number Diff line number Diff line change
@@ -1,53 +1,42 @@
__all__ = ("ContainerFormat", "formats_available")
__all__ = ("Flags", "ContainerFormat", "formats_available")

from typing import Literal
from enum import Flag
from typing import ClassVar, Literal

from .enum import EnumFlag

class Flags(EnumFlag):
NOFILE: int
NEEDNUMBER: int
SHOW_IDS: int
GLOBALHEADER: int
NOTIMESTAMPS: int
GENERIC_INDEX: int
TS_DISCONT: int
VARIABLE_FPS: int
NODIMENSIONS: int
NOSTREAMS: int
NOBINSEARCH: int
NOGENSEARCH: int
NO_BYTE_SEEK: int
ALLOW_FLUSH: int
TS_NONSTRICT: int
TS_NEGATIVE: int
SEEK_TO_PTS: int
class Flags(Flag):
no_file: ClassVar[Flags]
need_number: ClassVar[Flags]
show_ids: ClassVar[Flags]
global_header: ClassVar[Flags]
no_timestamps: ClassVar[Flags]
generic_index: ClassVar[Flags]
ts_discont: ClassVar[Flags]
variable_fps: ClassVar[Flags]
no_dimensions: ClassVar[Flags]
no_streams: ClassVar[Flags]
no_bin_search: ClassVar[Flags]
no_gen_search: ClassVar[Flags]
no_byte_seek: ClassVar[Flags]
allow_flush: ClassVar[Flags]
ts_nonstrict: ClassVar[Flags]
ts_negative: ClassVar[Flags]
seek_to_pts: ClassVar[Flags]

class ContainerFormat:
def __init__(self, name: str, mode: Literal["r", "w"] | None = None) -> None: ...
name: str
long_name: str
is_input: bool
is_output: bool
extensions: set[str]

# flags
no_file: int
need_number: int
show_ids: int
global_header: int
no_timestamps: int
generic_index: int
ts_discont: int
variable_fps: int
no_dimensions: int
no_streams: int
no_bin_search: int
no_gen_search: int
no_byte_seek: int
allow_flush: int
ts_nonstrict: int
ts_negative: int
seek_to_pts: int
@property
def name(self) -> str: ...
@property
def long_name(self) -> str: ...
@property
def is_input(self) -> bool: ...
@property
def is_output(self) -> bool: ...
@property
def extensions(self) -> set[str]: ...
@property
def flags(self) -> int: ...
@property
def no_file(self) -> bool: ...

formats_available: set[str]
90 changes: 34 additions & 56 deletions av/format.pyx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
cimport libav as lib

from av.descriptor cimport wrap_avclass
from av.enum cimport define_enum

from enum import Flag


cdef object _cinit_bypass_sentinel = object()
Expand All @@ -16,41 +17,28 @@ cdef ContainerFormat build_container_format(lib.AVInputFormat* iptr, lib.AVOutpu
return format


Flags = define_enum("Flags", __name__, (
("NOFILE", lib.AVFMT_NOFILE),
("NEEDNUMBER", lib.AVFMT_NEEDNUMBER, "Needs '%d' in filename."),
("SHOW_IDS", lib.AVFMT_SHOW_IDS, "Show format stream IDs numbers."),
("GLOBALHEADER", lib.AVFMT_GLOBALHEADER, "Format wants global header."),
("NOTIMESTAMPS", lib.AVFMT_NOTIMESTAMPS, "Format does not need / have any timestamps."),
("GENERIC_INDEX", lib.AVFMT_GENERIC_INDEX, "Use generic index building code."),
("TS_DISCONT", lib.AVFMT_TS_DISCONT,
"""Format allows timestamp discontinuities.
Note, muxers always require valid (monotone) timestamps"""),
("VARIABLE_FPS", lib.AVFMT_VARIABLE_FPS, "Format allows variable fps."),
("NODIMENSIONS", lib.AVFMT_NODIMENSIONS, "Format does not need width/height"),
("NOSTREAMS", lib.AVFMT_NOSTREAMS, "Format does not require any streams"),
("NOBINSEARCH", lib.AVFMT_NOBINSEARCH,
"Format does not allow to fall back on binary search via read_timestamp"),
("NOGENSEARCH", lib.AVFMT_NOGENSEARCH,
"Format does not allow to fall back on generic search"),
("NO_BYTE_SEEK", lib.AVFMT_NO_BYTE_SEEK, "Format does not allow seeking by bytes"),
("ALLOW_FLUSH", lib.AVFMT_ALLOW_FLUSH,
"""Format allows flushing. If not set, the muxer will not receive a NULL
packet in the write_packet function."""),
("TS_NONSTRICT", lib.AVFMT_TS_NONSTRICT,
"""Format does not require strictly increasing timestamps, but they must
still be monotonic."""),
("TS_NEGATIVE", lib.AVFMT_TS_NEGATIVE,
"""Format allows muxing negative timestamps. If not set the timestamp
will be shifted in av_write_frame and av_interleaved_write_frame so they
start from 0. The user or muxer can override this through
AVFormatContext.avoid_negative_ts"""),
("SEEK_TO_PTS", lib.AVFMT_SEEK_TO_PTS, "Seeking is based on PTS"),
), is_flags=True)

class Flags(Flag):
no_file = lib.AVFMT_NOFILE
need_number: "Needs '%d' in filename." = lib.AVFMT_NEEDNUMBER
show_ids: "Show format stream IDs numbers." = lib.AVFMT_SHOW_IDS
global_header: "Format wants global header." = lib.AVFMT_GLOBALHEADER
no_timestamps: "Format does not need / have any timestamps." = lib.AVFMT_NOTIMESTAMPS
generic_index: "Use generic index building code." = lib.AVFMT_GENERIC_INDEX
ts_discont: "Format allows timestamp discontinuities" = lib.AVFMT_TS_DISCONT
variable_fps: "Format allows variable fps." = lib.AVFMT_VARIABLE_FPS
no_dimensions: "Format does not need width/height" = lib.AVFMT_NODIMENSIONS
no_streams: "Format does not require any streams" = lib.AVFMT_NOSTREAMS
no_bin_search: "Format does not allow to fall back on binary search via read_timestamp" = lib.AVFMT_NOBINSEARCH
no_gen_search: "Format does not allow to fall back on generic search" = lib.AVFMT_NOGENSEARCH
no_byte_seek: "Format does not allow seeking by bytes" = lib.AVFMT_NO_BYTE_SEEK
allow_flush: "Format allows flushing. If not set, the muxer will not receive a NULL packet in the write_packet function." = lib.AVFMT_ALLOW_FLUSH
ts_nonstrict: "Format does not require strictly increasing timestamps, but they must still be monotonic." = lib.AVFMT_TS_NONSTRICT
ts_negative: "Format allows muxing negative timestamps." = lib.AVFMT_TS_NEGATIVE
# If not set the timestamp will be shifted in `av_write_frame()` and `av_interleaved_write_frame()`
# so they start from 0. The user or muxer can override this through AVFormatContext.avoid_negative_ts
seek_to_pts: "Seeking is based on PTS" = lib.AVFMT_SEEK_TO_PTS

cdef class ContainerFormat:

"""Descriptor of a container format.
:param str name: The name of the format.
Expand All @@ -63,12 +51,11 @@ cdef class ContainerFormat:
if name is _cinit_bypass_sentinel:
return

# We need to hold onto the original name because AVInputFormat.name
# is actually comma-seperated, and so we need to remember which one
# this was.
# We need to hold onto the original name because AVInputFormat.name is
# actually comma-separated, and so we need to remember which one this was.
self.name = name

# Searches comma-seperated names.
# Searches comma-separated names.
if mode is None or mode == "r":
self.iptr = lib.av_find_input_format(name)

Expand Down Expand Up @@ -135,30 +122,21 @@ cdef class ContainerFormat:
exts.update(self.optr.extensions.split(","))
return exts

@Flags.property
@property
def flags(self):
"""
Get the flags bitmask for the format.
:rtype: int
"""
return (
(self.iptr.flags if self.iptr else 0) |
(self.optr.flags if self.optr else 0)
)

no_file = flags.flag_property("NOFILE")
need_number = flags.flag_property("NEEDNUMBER")
show_ids = flags.flag_property("SHOW_IDS")
global_header = flags.flag_property("GLOBALHEADER")
no_timestamps = flags.flag_property("NOTIMESTAMPS")
generic_index = flags.flag_property("GENERIC_INDEX")
ts_discont = flags.flag_property("TS_DISCONT")
variable_fps = flags.flag_property("VARIABLE_FPS")
no_dimensions = flags.flag_property("NODIMENSIONS")
no_streams = flags.flag_property("NOSTREAMS")
no_bin_search = flags.flag_property("NOBINSEARCH")
no_gen_search = flags.flag_property("NOGENSEARCH")
no_byte_seek = flags.flag_property("NO_BYTE_SEEK")
allow_flush = flags.flag_property("ALLOW_FLUSH")
ts_nonstrict = flags.flag_property("TS_NONSTRICT")
ts_negative = flags.flag_property("TS_NEGATIVE")
seek_to_pts = flags.flag_property("SEEK_TO_PTS")
@property
def no_file(self):
return bool(self.flags & lib.AVFMT_NOFILE)


cdef get_output_format_names():
Expand Down

0 comments on commit eb8428d

Please sign in to comment.