From 20d97c68c4835de4d907e91f2518be9dc0e9c363 Mon Sep 17 00:00:00 2001 From: Lukas Geiger Date: Wed, 11 Mar 2026 12:04:06 +0000 Subject: [PATCH 1/3] Reduce Python overhead in reformat --- av/video/reformatter.py | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/av/video/reformatter.py b/av/video/reformatter.py index a29283717..42ff47d57 100644 --- a/av/video/reformatter.py +++ b/av/video/reformatter.py @@ -3,7 +3,7 @@ import cython import cython.cimports.libav as lib from cython.cimports.av.error import err_check -from cython.cimports.av.video.format import VideoFormat +from cython.cimports.av.video.format import VideoFormat, get_pix_fmt from cython.cimports.av.video.frame import alloc_video_frame @@ -91,6 +91,7 @@ class ColorPrimaries(IntEnum): @cython.cfunc +@cython.inline def _resolve_enum_value( value: object, enum_class: object, default: cython.int ) -> cython.int: @@ -106,6 +107,16 @@ def _resolve_enum_value( raise ValueError(f"Cannot convert {value} to {enum_class.__name__}") +@cython.cfunc +@cython.inline +def _resolve_format(format: object, default: lib.AVPixelFormat) -> lib.AVPixelFormat: + if format is None: + return default + if isinstance(format, VideoFormat): + return cython.cast(VideoFormat, format).pix_fmt + return get_pix_fmt(format) + + @cython.cfunc def _set_frame_colorspace( frame: cython.pointer(lib.AVFrame), @@ -186,18 +197,15 @@ def reformat( selection based on the number of available CPUs. Defaults to ``0`` (auto). """ - - video_format: VideoFormat = VideoFormat( - format if format is not None else frame.format - ) + c_dst_format = _resolve_format(format, frame.format.pix_fmt) c_src_colorspace = _resolve_enum_value( - src_colorspace, Colorspace, frame.colorspace + src_colorspace, Colorspace, frame.ptr.colorspace ) c_dst_colorspace = _resolve_enum_value( - dst_colorspace, Colorspace, frame.colorspace + dst_colorspace, Colorspace, frame.ptr.colorspace ) c_interpolation = _resolve_enum_value( - interpolation, Interpolation, int(Interpolation.BILINEAR) + interpolation, Interpolation, SWS_BILINEAR ) c_src_color_range = _resolve_enum_value(src_color_range, ColorRange, 0) c_dst_color_range = _resolve_enum_value(dst_color_range, ColorRange, 0) @@ -213,9 +221,9 @@ def reformat( return self._reformat( frame, - width or frame.ptr.width, - height or frame.ptr.height, - video_format.pix_fmt, + width if width is not None else frame.ptr.width, + height if height is not None else frame.ptr.height, + c_dst_format, c_src_colorspace, c_dst_colorspace, c_interpolation, From 02ce7b47266f7209f9e7b12c85a836cce05ae75b Mon Sep 17 00:00:00 2001 From: Lukas Geiger Date: Wed, 11 Mar 2026 12:06:30 +0000 Subject: [PATCH 2/3] Simplify early return --- av/video/reformatter.py | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/av/video/reformatter.py b/av/video/reformatter.py index 42ff47d57..fc07f409a 100644 --- a/av/video/reformatter.py +++ b/av/video/reformatter.py @@ -260,25 +260,6 @@ def _reformat( src_format = cython.cast(lib.AVPixelFormat, frame.ptr.format) # Shortcut! - if frame.ptr.hw_frames_ctx: - if ( - dst_format == src_format - and width == frame.ptr.width - and height == frame.ptr.height - and dst_colorspace == src_colorspace - and src_color_range == dst_color_range - and not set_dst_color_trc - and not set_dst_color_primaries - ): - return frame - - frame_sw = alloc_video_frame() - err_check(lib.av_hwframe_transfer_data(frame_sw.ptr, frame.ptr, 0)) - frame_sw.pts = frame.pts - frame_sw._init_user_attributes() - frame = frame_sw - src_format = cython.cast(lib.AVPixelFormat, frame.ptr.format) - if ( dst_format == src_format and width == frame.ptr.width @@ -290,6 +271,14 @@ def _reformat( ): return frame + if frame.ptr.hw_frames_ctx: + frame_sw = alloc_video_frame() + err_check(lib.av_hwframe_transfer_data(frame_sw.ptr, frame.ptr, 0)) + frame_sw.pts = frame.pts + frame_sw._init_user_attributes() + frame = frame_sw + src_format = cython.cast(lib.AVPixelFormat, frame.ptr.format) + if self.ptr == cython.NULL: self.ptr = sws_alloc_context() if self.ptr == cython.NULL: From d66859cc26d2a5aa8fa8b298c162aa3d035f5eb3 Mon Sep 17 00:00:00 2001 From: Lukas Geiger Date: Wed, 11 Mar 2026 12:15:00 +0000 Subject: [PATCH 3/3] Make casting consistent --- av/video/reformatter.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/av/video/reformatter.py b/av/video/reformatter.py index fc07f409a..202c32115 100644 --- a/av/video/reformatter.py +++ b/av/video/reformatter.py @@ -214,6 +214,8 @@ def reformat( dst_color_primaries, ColorPrimaries, 0 ) c_threads: cython.int = threads if threads is not None else 0 + c_width: cython.int = width if width is not None else frame.ptr.width + c_height: cython.int = height if height is not None else frame.ptr.height # Track whether user explicitly specified destination metadata set_dst_color_trc: cython.bint = dst_color_trc is not None @@ -221,8 +223,8 @@ def reformat( return self._reformat( frame, - width if width is not None else frame.ptr.width, - height if height is not None else frame.ptr.height, + c_width, + c_height, c_dst_format, c_src_colorspace, c_dst_colorspace,