Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Flag enum for format flags #1657

Merged
merged 1 commit into from
Dec 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading