diff --git a/av/format.pyi b/av/format.pyi index c3506ed51..b30a84bf6 100644 --- a/av/format.pyi +++ b/av/format.pyi @@ -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] diff --git a/av/format.pyx b/av/format.pyx index 06b533cf4..464e34f49 100644 --- a/av/format.pyx +++ b/av/format.pyx @@ -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() @@ -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. @@ -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) @@ -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():