diff --git a/av/codec/context.py b/av/codec/context.py index 6fefb1857..3d3c2ba91 100644 --- a/av/codec/context.py +++ b/av/codec/context.py @@ -661,6 +661,19 @@ def profile(self, value): return i += 1 + @property + def level(self): + """Codec level. + + Wraps :ffmpeg:`AVCodecContext.level`. + + """ + return self.ptr.level + + @level.setter + def level(self, value: cython.int): + self.ptr.level = value + @property def time_base(self): if self.is_decoder: diff --git a/av/codec/context.pyi b/av/codec/context.pyi index 808bb292b..e74502571 100644 --- a/av/codec/context.pyi +++ b/av/codec/context.pyi @@ -57,6 +57,7 @@ class CodecContext: type: Literal["video", "audio", "data", "subtitle", "attachment"] options: dict[str, str] profile: str | None + level: int @property def profiles(self) -> list[str]: ... extradata: bytes | None diff --git a/include/avcodec.pxd b/include/avcodec.pxd index 02e9ac9ca..2fec164e4 100644 --- a/include/avcodec.pxd +++ b/include/avcodec.pxd @@ -280,6 +280,7 @@ cdef extern from "libavcodec/avcodec.h" nogil: int thread_type int bits_per_coded_sample int profile + int level AVDiscard skip_frame int subtitle_header_size diff --git a/tests/test_codec_context.py b/tests/test_codec_context.py index 730b50bbe..d1af537c5 100644 --- a/tests/test_codec_context.py +++ b/tests/test_codec_context.py @@ -75,6 +75,14 @@ def test_global_quality(self): ctx.global_quality = 5 assert ctx.global_quality == 5 + def test_level(self): + with av.open(fate_suite("h264/interlaced_crop.mp4")) as container: + assert container.streams.video[0].codec_context.level == 41 + + ctx = Codec("mpeg4", "w").create() + ctx.level = 5 + assert ctx.level == 5 + def test_skip_frame_default(self): ctx = Codec("png", "w").create() assert ctx.skip_frame == "DEFAULT"