Skip to content

Fix cuvidCreateDecoder segfault on Linux (tcu_ulong layout) - #1

Open
devnen wants to merge 1 commit into
shootthesound:mainfrom
devnen:fix-cuvid-decoder-linux-ulong
Open

Fix cuvidCreateDecoder segfault on Linux (tcu_ulong layout)#1
devnen wants to merge 1 commit into
shootthesound:mainfrom
devnen:fix-cuvid-decoder-linux-ulong

Conversation

@devnen

@devnen devnen commented May 27, 2026

Copy link
Copy Markdown

cuvidCreateDecoder segfaults on Linux because tcu_ulong fields in CUVIDDECODECREATEINFO and CUVIDSOURCEDATAPACKET are declared as c_uint32. That's correct on Windows LLP64 (4 bytes) but wrong on Linux LP64 (unsigned long is 8 bytes). Result: the struct is short by ~68 bytes and the driver reads garbage.

Patch:

  • Adds a tcu_ulong alias at the top of decoder.py: c_uint32 on Windows, c_ulong on Linux/macOS.
  • Switches the affected fields in CUVIDDECODECREATEINFO (13 fields plus the Reserved2 array element type) and CUVIDSOURCEDATAPACKET (flags, payload_size) to tcu_ulong.
  • Leaves enum fields (CodecType, ChromaFormat, OutputFormat, DeinterlaceMode) as c_uint32 since those are 4 bytes on both platforms in the C header.
  • No changes to CUVIDPARSERPARAMS, CUVIDEOFORMAT, CUVIDPROCPARAMS, CUVIDPICPARAMS (they use unsigned int, which is 4 bytes on both platforms).
  • Updates the file docstring to note Linux is now handled.

Sanity check:

  • ctypes.sizeof(CUVIDDECODECREATEINFO) on Linux x86_64: 108 -> 176 (matches nv-codec-headers/dynlink_cuviddec.h layout)
  • ctypes.sizeof(CUVIDSOURCEDATAPACKET) on Linux x86_64: 24 -> 32
  • Both unchanged on Windows.

Verified on:

  • Linux: RTX 3090, driver 595.58.03, Pop!_OS 22.04, Python 3.11, cuda-bindings 13.2.0. End-to-end encode -> decode round-trip works in NV12 4:2:0 mode. Cosine sim 1.0000 lossless, expected lossy signature at QP18 (max_abs_diff 10, mean 1.6 on 256x256 random-noise input).
  • Windows: not re-tested by me. The patch is c_uint32 on Windows by definition, so it should be a no-op on that platform. Someone with a Windows setup confirming the existing tests still pass would close that gap.

Caveat: I tested only NV12 4:2:0 on this hardware because the 3090's NVDEC doesn't support HEVC 4:4:4 decode (Lovelace+ feature). The 4:4:4 path through this fix should be unaffected since the struct fields are the same; someone on a 40-series or 50-series card could confirm.

The file's own docstring at lines 22-23 already flagged the Windows-only assumption, so this is the documented follow-up.

`tcu_ulong` is `unsigned long` in cuviddec.h: 4 bytes on Windows LLP64,
8 bytes on Linux LP64. The affected fields in CUVIDDECODECREATEINFO and
CUVIDSOURCEDATAPACKET were declared as c_uint32, which is correct on
Windows but truncates the struct by ~68 bytes on Linux. The driver reads
past the buffer and segfaults inside cuvidCreateDecoder.

Patch adds a tcu_ulong alias (c_uint32 on Windows, c_ulong on Linux/macOS)
and switches the 13 affected fields in CUVIDDECODECREATEINFO plus flags
and payload_size in CUVIDSOURCEDATAPACKET. Enum fields stay c_uint32.

sizeof on Linux x86_64:
- CUVIDDECODECREATEINFO: 108 -> 176 (matches nv-codec-headers layout)
- CUVIDSOURCEDATAPACKET: 24 -> 32

Both unchanged on Windows.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant