diff --git a/CHANGELOG.rst b/CHANGELOG.rst index fa41c6682..d89ead006 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -28,6 +28,9 @@ We are operating with `semantic versioning `_. v17.0.2 (next) -------------- +Features: +- Expose ``AVCodecContext.global_quality`` by :gh-user:`WyattBlue` in (:pr:`2246`). + Fixes: diff --git a/av/codec/context.py b/av/codec/context.py index 10b255b2b..0e8692d80 100644 --- a/av/codec/context.py +++ b/av/codec/context.py @@ -590,6 +590,23 @@ def codec_tag(self, value): else: raise ValueError("Codec tag should be a 4 character string.") + @property + @cython.cdivision(True) + def global_quality(self): + """Global quality for codecs which cannot change it per frame. + + Stored internally in lambda units; this property converts to/from + QP units using ``FF_QP2LAMBDA``. + + Wraps :ffmpeg:`AVCodecContext.global_quality`. + + """ + return self.ptr.global_quality // lib.FF_QP2LAMBDA + + @global_quality.setter + def global_quality(self, value: cython.int): + self.ptr.global_quality = value * lib.FF_QP2LAMBDA + @property def bit_rate(self): return self.ptr.bit_rate if self.ptr.bit_rate > 0 else None diff --git a/av/codec/context.pyi b/av/codec/context.pyi index e0c447186..808bb292b 100644 --- a/av/codec/context.pyi +++ b/av/codec/context.pyi @@ -62,6 +62,7 @@ class CodecContext: extradata: bytes | None time_base: Fraction codec_tag: str + global_quality: int bit_rate: int | None bit_rate_tolerance: int thread_count: int diff --git a/include/avutil.pxd b/include/avutil.pxd index 3ee78d2f5..d7a1fb765 100644 --- a/include/avutil.pxd +++ b/include/avutil.pxd @@ -18,6 +18,8 @@ cdef extern from "libavutil/avutil.h" nogil: cdef char* avutil_configuration() cdef char* avutil_license() + int FF_QP2LAMBDA + cdef enum AVPictureType: AV_PICTURE_TYPE_NONE AV_PICTURE_TYPE_I diff --git a/tests/test_codec_context.py b/tests/test_codec_context.py index 1173a5865..d0629480e 100644 --- a/tests/test_codec_context.py +++ b/tests/test_codec_context.py @@ -68,6 +68,11 @@ def iter_raw_frames( class TestCodecContext(TestCase): + def test_global_quality(self): + ctx = Codec("mpeg4", "w").create() + ctx.global_quality = 5 + assert ctx.global_quality == 5 + def test_skip_frame_default(self): ctx = Codec("png", "w").create() assert ctx.skip_frame == "DEFAULT"