fix: use named c_ubyte arrays to prevent dangling pointer segfault in SDL_UpdateNVTexture

This commit is contained in:
Matteo Benedetto
2026-03-24 00:31:44 +01:00
parent bb0ac90c96
commit 5332ce9880
@@ -246,24 +246,22 @@ class GStreamerBackend(PlayerBackend):
if frame.pixel_format == "NV12" and frame.uv_pixels is not None: if frame.pixel_format == "NV12" and frame.uv_pixels is not None:
# Zero-copy NV12 path: upload Y and UV planes separately. # Zero-copy NV12 path: upload Y and UV planes separately.
# SDL_UpdateNVTexture avoids a full BGRA conversion on CPU. # SDL_UpdateNVTexture avoids a full BGRA conversion on CPU.
# ctypes.create_string_buffer returns c_char_Array_N; cast to # Use named c_ubyte arrays so the buffers stay alive for the
# LP_c_ubyte which SDL_UpdateNVTexture requires. # duration of the C call (ctypes.cast of a temporary would produce
# a dangling pointer after CPython reference-counts the temp away).
try: try:
_ubyte_p = ctypes.POINTER(ctypes.c_ubyte) y_arr = (ctypes.c_ubyte * len(frame.pixels)).from_buffer_copy(frame.pixels)
y_data = bytes(frame.pixels) uv_arr = (ctypes.c_ubyte * len(frame.uv_pixels)).from_buffer_copy(frame.uv_pixels)
uv_data = bytes(frame.uv_pixels)
y_buf = ctypes.cast(ctypes.create_string_buffer(y_data), _ubyte_p)
uv_buf = ctypes.cast(ctypes.create_string_buffer(uv_data), _ubyte_p)
log.debug( log.debug(
"SDL_UpdateNVTexture: %dx%d y_len=%d uv_len=%d pitch=%d uv_pitch=%d", "SDL_UpdateNVTexture: %dx%d y_len=%d uv_len=%d pitch=%d uv_pitch=%d",
frame.width, frame.height, frame.width, frame.height,
len(y_data), len(uv_data), len(frame.pixels), len(frame.uv_pixels),
frame.pitch, frame.uv_pitch, frame.pitch, frame.uv_pitch,
) )
result = sdl2.SDL_UpdateNVTexture( result = sdl2.SDL_UpdateNVTexture(
self._texture, None, self._texture, None,
y_buf, frame.pitch, y_arr, frame.pitch,
uv_buf, frame.uv_pitch, uv_arr, frame.uv_pitch,
) )
except Exception: except Exception:
log.error( log.error(