Skip to content
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
101 changes: 73 additions & 28 deletions av/codec/codec.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class Properties(Flag):
LOSSY = lib.AV_CODEC_PROP_LOSSY
LOSSLESS = lib.AV_CODEC_PROP_LOSSLESS
REORDER = lib.AV_CODEC_PROP_REORDER
FIELDS = lib.AV_CODEC_PROP_FIELDS
ENHANCEMENT = lib.AV_CODEC_PROP_ENHANCEMENT
BITMAP_SUB = lib.AV_CODEC_PROP_BITMAP_SUB
TEXT_SUB = lib.AV_CODEC_PROP_TEXT_SUB

Expand All @@ -34,13 +36,10 @@ class Capabilities(IntEnum):
none = 0
draw_horiz_band = lib.AV_CODEC_CAP_DRAW_HORIZ_BAND
dr1 = lib.AV_CODEC_CAP_DR1
hwaccel = 1 << 4
delay = lib.AV_CODEC_CAP_DELAY
small_last_frame = lib.AV_CODEC_CAP_SMALL_LAST_FRAME
hwaccel_vdpau = 1 << 7
experimental = lib.AV_CODEC_CAP_EXPERIMENTAL
channel_conf = lib.AV_CODEC_CAP_CHANNEL_CONF
neg_linesizes = 1 << 11
frame_threads = lib.AV_CODEC_CAP_FRAME_THREADS
slice_threads = lib.AV_CODEC_CAP_SLICE_THREADS
param_change = lib.AV_CODEC_CAP_PARAM_CHANGE
Expand All @@ -49,9 +48,9 @@ class Capabilities(IntEnum):
avoid_probing = lib.AV_CODEC_CAP_AVOID_PROBING
hardware = lib.AV_CODEC_CAP_HARDWARE
hybrid = lib.AV_CODEC_CAP_HYBRID
encoder_reordered_opaque = 1 << 20
encoder_flush = 1 << 21
encoder_recon_frame = 1 << 22
encoder_reordered_opaque = lib.AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
encoder_flush = lib.AV_CODEC_CAP_ENCODER_FLUSH
encoder_recon_frame = lib.AV_CODEC_CAP_ENCODER_RECON_FRAME


class PixFmtLoss(IntFlag):
Expand All @@ -68,6 +67,8 @@ class PixFmtLoss(IntFlag):
ALPHA = 0x0008 # loss of alpha bit
COLORQUANT = 0x0010 # loss due to color quantization
CHROMA = 0x0020 # loss of chroma (e.g. RGB to gray conversion)
EXCESS_RESOLUTION = 0x0040 # loss due to unneeded extra resolution
EXCESS_DEPTH = 0x0080 # loss due to unneeded extra color depth


class UnknownCodecError(ValueError):
Expand Down Expand Up @@ -367,47 +368,91 @@ def get_codec_names():
return names


@cython.cfunc
def get_media_type_name(media_type: lib.AVMediaType) -> str:
name = lib.av_get_media_type_string(media_type)
return "unknown" if name == cython.NULL else name


@cython.cfunc
def get_codec_summaries():
summaries: dict = {}
desc = cython.declare(
cython.pointer[cython.const[lib.AVCodecDescriptor]], cython.NULL
)
while True:
desc = lib.avcodec_descriptor_next(desc)
if not desc:
break
summaries[desc.name] = [
desc.long_name or "",
get_media_type_name(desc.type),
desc.props,
lib.avcodec_find_decoder(desc.id) != cython.NULL,
lib.avcodec_find_encoder(desc.id) != cython.NULL,
]

canonical_names: set = set(summaries)

ptr = cython.declare(cython.pointer[cython.const[lib.AVCodec]])
opaque: cython.p_void = cython.NULL
while True:
ptr = lib.av_codec_iterate(cython.address(opaque))
if not ptr:
break
if ptr.name in canonical_names:
continue

desc = lib.avcodec_descriptor_get(ptr.id)
summary = summaries.setdefault(
ptr.name,
[
ptr.long_name or "",
get_media_type_name(ptr.type),
desc.props if desc else 0,
False,
False,
],
)
summary[3 if lib.av_codec_is_decoder(ptr) else 4] = True

return summaries


codecs_available = get_codec_names()


def dump_codecs():
"""Print information about available codecs."""

def _type_char(media_type: str) -> str:
return "T" if media_type == "attachment" else media_type[0].upper()

print(
"""Codecs:
D..... = Decoding supported
.E.... = Encoding supported
..V... = Video codec
..A... = Audio codec
..S... = Subtitle codec
..D... = Data codec
..T... = Attachment codec
...I.. = Intra frame-only codec
....L. = Lossy compression
.....S = Lossless compression
------"""
)

for name in sorted(codecs_available):
try:
e_codec = Codec(name, "w")
except ValueError:
e_codec = None

try:
d_codec = Codec(name, "r")
except ValueError:
d_codec = None

# TODO: Assert these always have the same properties.
codec = e_codec or d_codec

try:
print(
f" {'.D'[bool(d_codec)]}{'.E'[bool(e_codec)]}{codec.type[0].upper()}"
f"{'.I'[codec.intra_only]}{'.L'[codec.lossy]}{'.S'[codec.lossless]}"
f" {codec.name:<18} {codec.long_name}"
)
except Exception as e:
print(f"...... {codec.name:<18} ERROR: {e}")
for name, (long_name, media_type, props, can_decode, can_encode) in sorted(
get_codec_summaries().items()
):
print(
f" {'.D'[can_decode]}{'.E'[can_encode]}{_type_char(media_type)}"
f"{'.I'[bool(props & lib.AV_CODEC_PROP_INTRA_ONLY)]}"
f"{'.L'[bool(props & lib.AV_CODEC_PROP_LOSSY)]}"
f"{'.S'[bool(props & lib.AV_CODEC_PROP_LOSSLESS)]}"
f" {name:<18} {long_name}"
)


def dump_hwconfigs():
Expand Down
8 changes: 4 additions & 4 deletions av/codec/codec.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,19 @@ class Properties(Flag):
LOSSY = cast(ClassVar[Properties], ...)
LOSSLESS = cast(ClassVar[Properties], ...)
REORDER = cast(ClassVar[Properties], ...)
FIELDS = cast(ClassVar[Properties], ...)
ENHANCEMENT = cast(ClassVar[Properties], ...)
BITMAP_SUB = cast(ClassVar[Properties], ...)
TEXT_SUB = cast(ClassVar[Properties], ...)

class Capabilities(IntEnum):
none = cast(int, ...)
draw_horiz_band = cast(int, ...)
dr1 = cast(int, ...)
hwaccel = cast(int, ...)
delay = cast(int, ...)
small_last_frame = cast(int, ...)
hwaccel_vdpau = cast(int, ...)
subframes = cast(int, ...)
experimental = cast(int, ...)
channel_conf = cast(int, ...)
neg_linesizes = cast(int, ...)
frame_threads = cast(int, ...)
slice_threads = cast(int, ...)
param_change = cast(int, ...)
Expand All @@ -53,6 +51,8 @@ class PixFmtLoss(IntFlag):
ALPHA = cast(ClassVar[PixFmtLoss], ...)
COLORQUANT = cast(ClassVar[PixFmtLoss], ...)
CHROMA = cast(ClassVar[PixFmtLoss], ...)
EXCESS_RESOLUTION = cast(ClassVar[PixFmtLoss], ...)
EXCESS_DEPTH = cast(ClassVar[PixFmtLoss], ...)

class UnknownCodecError(ValueError): ...

Expand Down
1 change: 1 addition & 0 deletions av/codec/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class Flags2(IntEnum):
export_mvs = lib.AV_CODEC_FLAG2_EXPORT_MVS
skip_manual = lib.AV_CODEC_FLAG2_SKIP_MANUAL
ro_flush_noop = lib.AV_CODEC_FLAG2_RO_FLUSH_NOOP
icc_profiles = lib.AV_CODEC_FLAG2_ICC_PROFILES


class OptionType(IntEnum):
Expand Down
1 change: 1 addition & 0 deletions av/codec/context.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class Flags2(IntEnum):
export_mvs = cast(int, ...)
skip_manual = cast(int, ...)
ro_flush_noop = cast(int, ...)
icc_profiles = cast(int, ...)

class OptionType(IntEnum):
FLAGS = cast(int, ...)
Expand Down
5 changes: 2 additions & 3 deletions av/codec/hwaccel.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ class HWDeviceType(IntEnum):
mediacodec = lib.AV_HWDEVICE_TYPE_MEDIACODEC
vulkan = lib.AV_HWDEVICE_TYPE_VULKAN
d3d12va = lib.AV_HWDEVICE_TYPE_D3D12VA
amf = 13 # FFmpeg >=8
ohcodec = 14
# TODO: When ffmpeg major is changed, check this enum.
amf = lib.AV_HWDEVICE_TYPE_AMF
ohcodec = lib.AV_HWDEVICE_TYPE_OHCODEC


class HWConfigMethod(IntEnum):
Expand Down
6 changes: 6 additions & 0 deletions av/format.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def build_container_format(
class Flags(Flag):
no_file = lib.AVFMT_NOFILE
need_number: "Needs '%d' in filename." = lib.AVFMT_NEEDNUMBER
experimental: "Format is not selected automatically, it must be requested by name." = lib.AVFMT_EXPERIMENTAL
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
Expand Down Expand Up @@ -135,6 +136,11 @@ def flags(self):
def no_file(self):
return bool(self.flags & lib.AVFMT_NOFILE)

@property
def fixed_framesize(self):
"""Whether the format wants fixed size audio frames. FFmpeg 9 and up."""
return bool(self.flags & 0x80000) # AVFMT_FIXED_FRAMESIZE


@cython.cfunc
def get_output_format_names() -> set[str]:
Expand Down
4 changes: 3 additions & 1 deletion av/format.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ from typing import ClassVar, Literal, cast
class Flags(Flag):
no_file = cast(ClassVar[Flags], ...)
need_number = cast(ClassVar[Flags], ...)
experimental = cast(ClassVar[Flags], ...)
show_ids = cast(ClassVar[Flags], ...)
global_header = cast(ClassVar[Flags], ...)
no_timestamps = cast(ClassVar[Flags], ...)
Expand All @@ -17,7 +18,6 @@ class Flags(Flag):
no_bin_search = cast(ClassVar[Flags], ...)
no_gen_search = cast(ClassVar[Flags], ...)
no_byte_seek = cast(ClassVar[Flags], ...)
allow_flush = cast(ClassVar[Flags], ...)
ts_nonstrict = cast(ClassVar[Flags], ...)
ts_negative = cast(ClassVar[Flags], ...)
seek_to_pts = cast(ClassVar[Flags], ...)
Expand All @@ -38,5 +38,7 @@ class ContainerFormat:
def flags(self) -> int: ...
@property
def no_file(self) -> bool: ...
@property
def fixed_framesize(self) -> bool: ...

formats_available: set[str]
4 changes: 4 additions & 0 deletions av/sidedata/sidedata.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ class Type(Enum):
DYNAMIC_HDR_VIVID = lib.AV_FRAME_DATA_DYNAMIC_HDR_VIVID
AMBIENT_VIEWING_ENVIRONMENT = lib.AV_FRAME_DATA_AMBIENT_VIEWING_ENVIRONMENT
VIDEO_HINT = lib.AV_FRAME_DATA_VIDEO_HINT
LCEVC = lib.AV_FRAME_DATA_LCEVC
VIEW_ID = lib.AV_FRAME_DATA_VIEW_ID
THREE_D_REFERENCE_DISPLAYS = lib.AV_FRAME_DATA_3D_REFERENCE_DISPLAYS
EXIF = lib.AV_FRAME_DATA_EXIF


@cython.cfunc
Expand Down
4 changes: 4 additions & 0 deletions av/sidedata/sidedata.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ class Type(Enum):
DYNAMIC_HDR_VIVID = cast(ClassVar[Type], ...)
AMBIENT_VIEWING_ENVIRONMENT = cast(ClassVar[Type], ...)
VIDEO_HINT = cast(ClassVar[Type], ...)
LCEVC = cast(ClassVar[Type], ...)
VIEW_ID = cast(ClassVar[Type], ...)
THREE_D_REFERENCE_DISPLAYS = cast(ClassVar[Type], ...)
EXIF = cast(ClassVar[Type], ...)

class SideData(Buffer):
type: Type
Expand Down
2 changes: 2 additions & 0 deletions av/video/reformatter.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ cdef extern from "libswscale/swscale.h" nogil:
cdef int SWS_SINC
cdef int SWS_LANCZOS
cdef int SWS_SPLINE
cdef int SWS_STRICT
cdef int SWS_PRINT_INFO
cdef int SWS_FULL_CHR_H_INT
cdef int SWS_FULL_CHR_H_INP
cdef int SWS_DIRECT_BGR
cdef int SWS_ACCURATE_RND
cdef int SWS_BITEXACT
cdef int SWS_UNSTABLE
cdef int SWS_ERROR_DIFFUSION
cdef int SWS_CS_ITU709
cdef int SWS_CS_FCC
Expand Down
4 changes: 4 additions & 0 deletions av/video/reformatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ class Interpolation(IntFlag):
SINC: "Unwindowed Sinc" = SWS_SINC
LANCZOS: "3-tap sinc/sinc" = SWS_LANCZOS
SPLINE: "Unwindowed natural cubic spline" = SWS_SPLINE
STRICT: "Error out on underspecified conversions" = SWS_STRICT
PRINT_INFO: "Emit verbose scaler info to the log" = SWS_PRINT_INFO
FULL_CHR_H_INT: "Full chroma interpolation" = SWS_FULL_CHR_H_INT
FULL_CHR_H_INP: "Full chroma input" = SWS_FULL_CHR_H_INP
DIRECT_BGR: "Direct BGR" = SWS_DIRECT_BGR
ACCURATE_RND: "Accurate rounding" = SWS_ACCURATE_RND
BITEXACT: "Bit-exact output" = SWS_BITEXACT
UNSTABLE: "Prefer experimental code paths (testing only)" = SWS_UNSTABLE
ERROR_DIFFUSION: "Error diffusion dither" = SWS_ERROR_DIFFUSION


Expand Down Expand Up @@ -78,6 +80,7 @@ class ColorTrc(IntEnum):
SMPTE2084: "SMPTE 2084 (PQ, HDR10)" = lib.AVCOL_TRC_SMPTE2084
SMPTE428: "SMPTE 428-1" = lib.AVCOL_TRC_SMPTE428
ARIB_STD_B67: "ARIB STD-B67 (HLG)" = lib.AVCOL_TRC_ARIB_STD_B67
V_LOG: "Panasonic V-Log (not part of H.273)" = lib.AVCOL_TRC_V_LOG


class ColorPrimaries(IntEnum):
Expand All @@ -98,6 +101,7 @@ class ColorPrimaries(IntEnum):
SMPTE431: "SMPTE 431-2 (DCI-P3)" = lib.AVCOL_PRI_SMPTE431
SMPTE432: "SMPTE 432-1 (Display P3)" = lib.AVCOL_PRI_SMPTE432
EBU3213: "EBU 3213-E / JEDEC P22" = lib.AVCOL_PRI_EBU3213
V_GAMUT: "Panasonic V-Gamut (not part of H.273)" = lib.AVCOL_PRI_V_GAMUT


@cython.cfunc
Expand Down
4 changes: 4 additions & 0 deletions av/video/reformatter.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ class Interpolation(IntFlag):
SINC = cast(int, ...)
LANCZOS = cast(int, ...)
SPLINE = cast(int, ...)
STRICT = cast(int, ...)
PRINT_INFO = cast(int, ...)
FULL_CHR_H_INT = cast(int, ...)
FULL_CHR_H_INP = cast(int, ...)
DIRECT_BGR = cast(int, ...)
ACCURATE_RND = cast(int, ...)
BITEXACT = cast(int, ...)
UNSTABLE = cast(int, ...)
ERROR_DIFFUSION = cast(int, ...)

class Colorspace(IntEnum):
Expand Down Expand Up @@ -65,6 +67,7 @@ class ColorTrc(IntEnum):
SMPTE2084 = cast(int, ...)
SMPTE428 = cast(int, ...)
ARIB_STD_B67 = cast(int, ...)
V_LOG = cast(int, ...)

class ColorPrimaries(IntEnum):
BT709 = cast(int, ...)
Expand All @@ -79,6 +82,7 @@ class ColorPrimaries(IntEnum):
SMPTE431 = cast(int, ...)
SMPTE432 = cast(int, ...)
EBU3213 = cast(int, ...)
V_GAMUT = cast(int, ...)

class VideoReformatter:
def reformat(
Expand Down
Loading
Loading