Skip to content

Commit 7a97124

Browse files
committed
Rethink container flags design
1 parent 850f115 commit 7a97124

File tree

2 files changed

+42
-92
lines changed

2 files changed

+42
-92
lines changed

av/container/core.pyi

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1+
from enum import Flag
12
from fractions import Fraction
23
from pathlib import Path
34
from types import TracebackType
4-
from typing import Any, Callable, Literal, Type, overload
5+
from typing import Any, Callable, ClassVar, Literal, Type, overload
56

6-
from av.enum import EnumFlag
77
from av.format import ContainerFormat
88

99
from .input import InputContainer
@@ -12,22 +12,22 @@ from .streams import StreamContainer
1212

1313
Real = int | float | Fraction
1414

15-
class Flags(EnumFlag):
16-
GENPTS: int
17-
IGNIDX: int
18-
NONBLOCK: int
19-
IGNDTS: int
20-
NOFILLIN: int
21-
NOPARSE: int
22-
NOBUFFER: int
23-
CUSTOM_IO: int
24-
DISCARD_CORRUPT: int
25-
FLUSH_PACKETS: int
26-
BITEXACT: int
27-
SORT_DTS: int
28-
FAST_SEEK: int
29-
SHORTEST: int
30-
AUTO_BSF: int
15+
class Flags(Flag):
16+
gen_pts: ClassVar[Flags]
17+
ign_idx: ClassVar[Flags]
18+
non_block: ClassVar[Flags]
19+
ign_dts: ClassVar[Flags]
20+
no_fillin: ClassVar[Flags]
21+
no_parse: ClassVar[Flags]
22+
no_buffer: ClassVar[Flags]
23+
custom_io: ClassVar[Flags]
24+
discard_corrupt: ClassVar[Flags]
25+
flush_packets: ClassVar[Flags]
26+
bitexact: ClassVar[Flags]
27+
sort_dts: ClassVar[Flags]
28+
fast_seek: ClassVar[Flags]
29+
shortest: ClassVar[Flags]
30+
auto_bsf: ClassVar[Flags]
3131

3232
class Container:
3333
writeable: bool
@@ -47,6 +47,7 @@ class Container:
4747
metadata: dict[str, str]
4848
open_timeout: Real | None
4949
read_timeout: Real | None
50+
flags: int
5051

5152
def __enter__(self) -> Container: ...
5253
def __exit__(

av/container/core.pyx

Lines changed: 23 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ from libc.stdint cimport int64_t
33

44
import os
55
import time
6+
from enum import Flag
67
from pathlib import Path
78

89
cimport libav as lib
@@ -11,7 +12,6 @@ from av.container.core cimport timeout_info
1112
from av.container.input cimport InputContainer
1213
from av.container.output cimport OutputContainer
1314
from av.container.pyio cimport pyio_close_custom_gil, pyio_close_gil
14-
from av.enum cimport define_enum
1515
from av.error cimport err_check, stash_exception
1616
from av.format cimport build_container_format
1717
from av.utils cimport avdict_to_dict
@@ -27,14 +27,12 @@ cdef object _cinit_sentinel = object()
2727
cdef object clock = getattr(time, "monotonic", time.time)
2828

2929
cdef int interrupt_cb (void *p) noexcept nogil:
30-
3130
cdef timeout_info info = dereference(<timeout_info*> p)
3231
if info.timeout < 0: # timeout < 0 means no timeout
3332
return 0
3433

3534
cdef double current_time
3635
with gil:
37-
3836
current_time = clock()
3937

4038
# Check if the clock has been changed.
@@ -124,47 +122,26 @@ cdef int pyav_io_close_gil(lib.AVFormatContext *s, lib.AVIOContext *pb) noexcept
124122

125123
return result
126124

127-
Flags = define_enum("Flags", __name__, (
128-
("GENPTS", lib.AVFMT_FLAG_GENPTS,
129-
"Generate missing pts even if it requires parsing future frames."),
130-
("IGNIDX", lib.AVFMT_FLAG_IGNIDX,
131-
"Ignore index."),
132-
("NONBLOCK", lib.AVFMT_FLAG_NONBLOCK,
133-
"Do not block when reading packets from input."),
134-
("IGNDTS", lib.AVFMT_FLAG_IGNDTS,
135-
"Ignore DTS on frames that contain both DTS & PTS."),
136-
("NOFILLIN", lib.AVFMT_FLAG_NOFILLIN,
137-
"Do not infer any values from other values, just return what is stored in the container."),
138-
("NOPARSE", lib.AVFMT_FLAG_NOPARSE,
139-
"""Do not use AVParsers, you also must set AVFMT_FLAG_NOFILLIN as the fillin code works on frames and no parsing -> no frames.
140-
141-
Also seeking to frames can not work if parsing to find frame boundaries has been disabled."""),
142-
("NOBUFFER", lib.AVFMT_FLAG_NOBUFFER,
143-
"Do not buffer frames when possible."),
144-
("CUSTOM_IO", lib.AVFMT_FLAG_CUSTOM_IO,
145-
"The caller has supplied a custom AVIOContext, don't avio_close() it."),
146-
("DISCARD_CORRUPT", lib.AVFMT_FLAG_DISCARD_CORRUPT,
147-
"Discard frames marked corrupted."),
148-
("FLUSH_PACKETS", lib.AVFMT_FLAG_FLUSH_PACKETS,
149-
"Flush the AVIOContext every packet."),
150-
("BITEXACT", lib.AVFMT_FLAG_BITEXACT,
151-
"""When muxing, try to avoid writing any random/volatile data to the output.
152-
153-
This includes any random IDs, real-time timestamps/dates, muxer version, etc.
154-
This flag is mainly intended for testing."""),
155-
("SORT_DTS", lib.AVFMT_FLAG_SORT_DTS,
156-
"Try to interleave outputted packets by dts (using this flag can slow demuxing down)."),
157-
("FAST_SEEK", lib.AVFMT_FLAG_FAST_SEEK,
158-
"Enable fast, but inaccurate seeks for some formats."),
159-
("SHORTEST", lib.AVFMT_FLAG_SHORTEST,
160-
"Stop muxing when the shortest stream stops."),
161-
("AUTO_BSF", lib.AVFMT_FLAG_AUTO_BSF,
162-
"Add bitstream filters as requested by the muxer."),
163-
), is_flags=True)
164125

126+
class Flags(Flag):
127+
gen_pts: "Generate missing pts even if it requires parsing future frames." = lib.AVFMT_FLAG_GENPTS
128+
ign_idx: "Ignore index." = lib.AVFMT_FLAG_IGNIDX
129+
non_block: "Do not block when reading packets from input." = lib.AVFMT_FLAG_NONBLOCK
130+
ign_dts: "Ignore DTS on frames that contain both DTS & PTS." = lib.AVFMT_FLAG_IGNDTS
131+
no_fillin: "Do not infer any values from other values, just return what is stored in the container." = lib.AVFMT_FLAG_NOFILLIN
132+
no_parse: "Do not use AVParsers, you also must set AVFMT_FLAG_NOFILLIN as the fillin code works on frames and no parsing -> no frames. Also seeking to frames can not work if parsing to find frame boundaries has been disabled." = lib.AVFMT_FLAG_NOPARSE
133+
no_buffer: "Do not buffer frames when possible." = lib.AVFMT_FLAG_NOBUFFER
134+
custom_io: "The caller has supplied a custom AVIOContext, don't avio_close() it." = lib.AVFMT_FLAG_CUSTOM_IO
135+
discard_corrupt: "Discard frames marked corrupted." = lib.AVFMT_FLAG_DISCARD_CORRUPT
136+
flush_packets: "Flush the AVIOContext every packet." = lib.AVFMT_FLAG_FLUSH_PACKETS
137+
bitexact: "When muxing, try to avoid writing any random/volatile data to the output. This includes any random IDs, real-time timestamps/dates, muxer version, etc. This flag is mainly intended for testing." = lib.AVFMT_FLAG_BITEXACT
138+
sort_dts: "Try to interleave outputted packets by dts (using this flag can slow demuxing down)." = lib.AVFMT_FLAG_SORT_DTS
139+
fast_seek: "Enable fast, but inaccurate seeks for some formats." = lib.AVFMT_FLAG_FAST_SEEK
140+
shortest: "Stop muxing when the shortest stream stops." = lib.AVFMT_FLAG_SHORTEST
141+
auto_bsf: "Add bitstream filters as requested by the muxer." = lib.AVFMT_FLAG_AUTO_BSF
165142

166-
cdef class Container:
167143

144+
cdef class Container:
168145
def __cinit__(self, sentinel, file_, format_name, options,
169146
container_options, stream_options,
170147
metadata_encoding, metadata_errors,
@@ -248,20 +225,13 @@ cdef class Container:
248225
cdef lib.AVInputFormat *ifmt
249226
cdef _Dictionary c_options
250227
if not self.writeable:
251-
252228
ifmt = self.format.iptr if self.format else NULL
253-
254229
c_options = Dictionary(self.options, self.container_options)
255230

256231
self.set_timeout(self.open_timeout)
257232
self.start_timeout()
258233
with nogil:
259-
res = lib.avformat_open_input(
260-
&self.ptr,
261-
name,
262-
ifmt,
263-
&c_options.ptr
264-
)
234+
res = lib.avformat_open_input(&self.ptr, name, ifmt, &c_options.ptr)
265235
self.set_timeout(None)
266236
self.err_check(res)
267237
self.input_was_opened = True
@@ -304,37 +274,16 @@ cdef class Container:
304274
if self.ptr == NULL:
305275
raise AssertionError("Container is not open")
306276

307-
def _get_flags(self):
277+
@property
278+
def flags(self):
308279
self._assert_open()
309280
return self.ptr.flags
310281

311-
def _set_flags(self, value):
282+
@flags.setter
283+
def flags(self, int value):
312284
self._assert_open()
313285
self.ptr.flags = value
314286

315-
flags = Flags.property(
316-
_get_flags,
317-
_set_flags,
318-
"""Flags property of :class:`.Flags`"""
319-
)
320-
321-
gen_pts = flags.flag_property("GENPTS")
322-
ign_idx = flags.flag_property("IGNIDX")
323-
non_block = flags.flag_property("NONBLOCK")
324-
ign_dts = flags.flag_property("IGNDTS")
325-
no_fill_in = flags.flag_property("NOFILLIN")
326-
no_parse = flags.flag_property("NOPARSE")
327-
no_buffer = flags.flag_property("NOBUFFER")
328-
custom_io = flags.flag_property("CUSTOM_IO")
329-
discard_corrupt = flags.flag_property("DISCARD_CORRUPT")
330-
flush_packets = flags.flag_property("FLUSH_PACKETS")
331-
bit_exact = flags.flag_property("BITEXACT")
332-
sort_dts = flags.flag_property("SORT_DTS")
333-
fast_seek = flags.flag_property("FAST_SEEK")
334-
shortest = flags.flag_property("SHORTEST")
335-
auto_bsf = flags.flag_property("AUTO_BSF")
336-
337-
338287
def open(
339288
file,
340289
mode=None,

0 commit comments

Comments
 (0)