Skip to content

Commit

Permalink
Rethink container flags design
Browse files Browse the repository at this point in the history
  • Loading branch information
WyattBlue committed Nov 13, 2024
1 parent 850f115 commit 1e57c10
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 92 deletions.
37 changes: 19 additions & 18 deletions av/container/core.pyi
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from enum import Flag
from fractions import Fraction
from pathlib import Path
from types import TracebackType
from typing import Any, Callable, Literal, Type, overload
from typing import Any, Callable, ClassVar, Literal, Type, overload

from av.enum import EnumFlag
from av.format import ContainerFormat

from .input import InputContainer
Expand All @@ -12,22 +12,22 @@ from .streams import StreamContainer

Real = int | float | Fraction

class Flags(EnumFlag):
GENPTS: int
IGNIDX: int
NONBLOCK: int
IGNDTS: int
NOFILLIN: int
NOPARSE: int
NOBUFFER: int
CUSTOM_IO: int
DISCARD_CORRUPT: int
FLUSH_PACKETS: int
BITEXACT: int
SORT_DTS: int
FAST_SEEK: int
SHORTEST: int
AUTO_BSF: int
class Flags(Flag):
gen_pts: ClassVar[Flags]
ign_idx: ClassVar[Flags]
non_block: ClassVar[Flags]
ign_dts: ClassVar[Flags]
no_fillin: ClassVar[Flags]
no_parse: ClassVar[Flags]
no_buffer: ClassVar[Flags]
custom_io: ClassVar[Flags]
discard_corrupt: ClassVar[Flags]
flush_packets: ClassVar[Flags]
bitexact: ClassVar[Flags]
sort_dts: ClassVar[Flags]
fast_seek: ClassVar[Flags]
shortest: ClassVar[Flags]
auto_bsf: ClassVar[Flags]

class Container:
writeable: bool
Expand All @@ -47,6 +47,7 @@ class Container:
metadata: dict[str, str]
open_timeout: Real | None
read_timeout: Real | None
flags: int

def __enter__(self) -> Container: ...
def __exit__(
Expand Down
97 changes: 23 additions & 74 deletions av/container/core.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ from libc.stdint cimport int64_t

import os
import time
from enum import Flag
from pathlib import Path

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

cdef int interrupt_cb (void *p) noexcept nogil:

cdef timeout_info info = dereference(<timeout_info*> p)
if info.timeout < 0: # timeout < 0 means no timeout
return 0

cdef double current_time
with gil:

current_time = clock()

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

return result

Flags = define_enum("Flags", __name__, (
("GENPTS", lib.AVFMT_FLAG_GENPTS,
"Generate missing pts even if it requires parsing future frames."),
("IGNIDX", lib.AVFMT_FLAG_IGNIDX,
"Ignore index."),
("NONBLOCK", lib.AVFMT_FLAG_NONBLOCK,
"Do not block when reading packets from input."),
("IGNDTS", lib.AVFMT_FLAG_IGNDTS,
"Ignore DTS on frames that contain both DTS & PTS."),
("NOFILLIN", lib.AVFMT_FLAG_NOFILLIN,
"Do not infer any values from other values, just return what is stored in the container."),
("NOPARSE", lib.AVFMT_FLAG_NOPARSE,
"""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."""),
("NOBUFFER", lib.AVFMT_FLAG_NOBUFFER,
"Do not buffer frames when possible."),
("CUSTOM_IO", lib.AVFMT_FLAG_CUSTOM_IO,
"The caller has supplied a custom AVIOContext, don't avio_close() it."),
("DISCARD_CORRUPT", lib.AVFMT_FLAG_DISCARD_CORRUPT,
"Discard frames marked corrupted."),
("FLUSH_PACKETS", lib.AVFMT_FLAG_FLUSH_PACKETS,
"Flush the AVIOContext every packet."),
("BITEXACT", lib.AVFMT_FLAG_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."""),
("SORT_DTS", lib.AVFMT_FLAG_SORT_DTS,
"Try to interleave outputted packets by dts (using this flag can slow demuxing down)."),
("FAST_SEEK", lib.AVFMT_FLAG_FAST_SEEK,
"Enable fast, but inaccurate seeks for some formats."),
("SHORTEST", lib.AVFMT_FLAG_SHORTEST,
"Stop muxing when the shortest stream stops."),
("AUTO_BSF", lib.AVFMT_FLAG_AUTO_BSF,
"Add bitstream filters as requested by the muxer."),
), is_flags=True)

class Flags(Flag):
gen_pts: "Generate missing pts even if it requires parsing future frames." = lib.AVFMT_FLAG_GENPTS
ign_idx: "Ignore index." = lib.AVFMT_FLAG_IGNIDX
non_block: "Do not block when reading packets from input." = lib.AVFMT_FLAG_NONBLOCK
ign_dts: "Ignore DTS on frames that contain both DTS & PTS." = lib.AVFMT_FLAG_IGNDTS
no_fillin: "Do not infer any values from other values, just return what is stored in the container." = lib.AVFMT_FLAG_NOFILLIN
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
no_buffer: "Do not buffer frames when possible." = lib.AVFMT_FLAG_NOBUFFER
custom_io: "The caller has supplied a custom AVIOContext, don't avio_close() it." = lib.AVFMT_FLAG_CUSTOM_IO
discard_corrupt: "Discard frames marked corrupted." = lib.AVFMT_FLAG_DISCARD_CORRUPT
flush_packets: "Flush the AVIOContext every packet." = lib.AVFMT_FLAG_FLUSH_PACKETS
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
sort_dts: "Try to interleave outputted packets by dts (using this flag can slow demuxing down)." = lib.AVFMT_FLAG_SORT_DTS
fast_seek: "Enable fast, but inaccurate seeks for some formats." = lib.AVFMT_FLAG_FAST_SEEK
shortest: "Stop muxing when the shortest stream stops." = lib.AVFMT_FLAG_SHORTEST
auto_bsf: "Add bitstream filters as requested by the muxer." = lib.AVFMT_FLAG_AUTO_BSF

cdef class Container:

cdef class Container:
def __cinit__(self, sentinel, file_, format_name, options,
container_options, stream_options,
metadata_encoding, metadata_errors,
Expand Down Expand Up @@ -248,20 +225,13 @@ cdef class Container:
cdef lib.AVInputFormat *ifmt
cdef _Dictionary c_options
if not self.writeable:

ifmt = self.format.iptr if self.format else NULL

c_options = Dictionary(self.options, self.container_options)

self.set_timeout(self.open_timeout)
self.start_timeout()
with nogil:
res = lib.avformat_open_input(
&self.ptr,
name,
ifmt,
&c_options.ptr
)
res = lib.avformat_open_input(&self.ptr, name, ifmt, &c_options.ptr)
self.set_timeout(None)
self.err_check(res)
self.input_was_opened = True
Expand Down Expand Up @@ -304,37 +274,16 @@ cdef class Container:
if self.ptr == NULL:
raise AssertionError("Container is not open")

def _get_flags(self):
@property
def flags(self):
self._assert_open()
return self.ptr.flags

def _set_flags(self, value):
@flags.setter
def flags(self, int value):
self._assert_open()
self.ptr.flags = value

flags = Flags.property(
_get_flags,
_set_flags,
"""Flags property of :class:`.Flags`"""
)

gen_pts = flags.flag_property("GENPTS")
ign_idx = flags.flag_property("IGNIDX")
non_block = flags.flag_property("NONBLOCK")
ign_dts = flags.flag_property("IGNDTS")
no_fill_in = flags.flag_property("NOFILLIN")
no_parse = flags.flag_property("NOPARSE")
no_buffer = flags.flag_property("NOBUFFER")
custom_io = flags.flag_property("CUSTOM_IO")
discard_corrupt = flags.flag_property("DISCARD_CORRUPT")
flush_packets = flags.flag_property("FLUSH_PACKETS")
bit_exact = flags.flag_property("BITEXACT")
sort_dts = flags.flag_property("SORT_DTS")
fast_seek = flags.flag_property("FAST_SEEK")
shortest = flags.flag_property("SHORTEST")
auto_bsf = flags.flag_property("AUTO_BSF")


def open(
file,
mode=None,
Expand Down

0 comments on commit 1e57c10

Please sign in to comment.