linux-v4l2: frame rate list truncates packed value to 32-bit int, so selected frame rate is ignored (driver falls back to max fps)
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 72/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- c, linux
- Domain
- audio-video-rtc
Research direction
The truncation is in plugins/linux-v4l2/v4l2-input.c, in v4l2_framerate_list()'s discrete branch, where the int64_t from v4l2_pack_tuple() is stored in an int. Check how v4l2_unpack_tuple() and v4l2_set_framerate() read the saved value, then confirm the 1/60 case packs to 4294967356 and survives a save/load round trip. Done when a discrete 60 fps selection logs Framerate: 60.00 fps; the zero-numerator fallback in the issue is a separate question.
Written by the indexing model from the issue text.
Description
Operating System Info
Other
Other OS
Linux (Bazzite / Fedora 44), kernel 7.2.9, KDE Plasma (Wayland)
OBS Studio Version
32.2.2
OBS Studio Version (Other)
No response
OBS Studio Log URL
https://obsproject.com/logs/WnFAT6SSKggJAjrQ
OBS Studio Crash Log URL
No response
Expected Behavior
Selecting a frame rate (e.g. 60.00) in the Video Capture Device (V4L2) properties makes OBS request that frame rate from the device.
Current Behavior
OBS ignores the selected frame rate and requests the device's fastest interval instead. With an Elgato 4K X (UVC, discrete frame intervals of 30/50/59.94/60/120/144 fps), selecting 60.00 produces:
v4l2-input: Pixelformat: NV12
v4l2-input: Framerate: 144.00 fps
The scene collection then contains "framerate": 60.
Side effects: the capture's select() timeout is computed from the bogus frame rate (5 frame periods ≈ 34.7 ms at 144 fps). When the source actually delivers 30 or 60 fps, OBS logs repeated select timed out messages. With MJPG, a timeout or bad frame shortly after start can be followed by failed to unpack jpeg or h264 / Stopped capture after 0 frames. The source then stays frozen on its last frame until it's recreated or OBS is restarted.
Steps to Reproduce
- Add a Video Capture Device (V4L2) source for a UVC device that reports discrete frame intervals.
- Choose a resolution and select a frame rate below the device maximum (e.g. 60.00).
- Check the log: Framerate: shows the device's maximum fps, not the selected value.
Anything else we should know?
In plugins/linux-v4l2/v4l2-input.c, v4l2_framerate_list(), discrete case (line 590 in 32.2.2):
int pack = v4l2_pack_tuple(frmival.discrete.numerator, frmival.discrete.denominator);
v4l2_pack_tuple() returns int64_t (PACK64(a, b) = a << 32 | b). Storing it in an int drops the numerator. For 1/60, PACK64(1, 60) = 4294967356 becomes 60. On load, v4l2_unpack_tuple() sees the upper 32 bits are zero and takes the legacy 16-bit path: numerator = 60 >> 16 = 0, denominator = 60. VIDIOC_S_PARM receives timeperframe = 0/60, and uvcvideo picks the shortest supported interval (144 fps).
The hard-coded list in the non-discrete branch passes *packed (int64_t) directly, so only the discrete branch is affected.
Suggested fix...in theory:
Scene collections already saved with the truncated value (numerator 0) would still request the max rate. It may be worth treating an unpacked numerator of 0 as invalid in v4l2_unpack_tuple() / v4l2_set_framerate(), either by falling back to the device default or by correcting it.
Known workaround:
With OBS closed, set the source's "framerate" in the scene collection JSON to the correctly packed value, e.g. 4294967356 for 1/60. OBS then logs Framerate: 60.00 fps and the timeouts stop. Re-selecting a frame rate in the dropdown writes the truncated value again.
- Dominant language
- C
- Stars
- 77.5k
- Forks
- 10.7k
- Avg merge
- 2d 4h
- Merged PRs (30d)
- 38
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from obsproject/obs-studio
-
ENABLE_CORE_MODULES=OFF fails to configure: obs-core-modules.c is never generatedPossibly taken @PatTheMav claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
obsproject/obs-studio#14013 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
obsproject/obs-studio#13936 · 10 comments ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
obsproject/obs-studio#13929 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 92/100
obsproject/obs-studio#13918 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
obsproject/obs-studio#13905 ·
Maintainers usually reply within 1 day
All issues in obsproject/obs-studio
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 80/100
Maintainers usually reply within 1 day
-
`inverse()` of a controlled `CUGate` drops the phase parameter γPossibly taken @rupasri118 claimed this today. Openbug mod: circuit
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
Qiskit/qiskit#17223 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
OpenPrinting/libcupsfilters#284 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 85/100
libsdl-org/SDL#16530 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
FriendsofECCE/ECCE#336 · 1 comment ·