Skip to content

Fix MJPEG fallback when capture rate is below requested output - #59

Draft
steveseguin wants to merge 2 commits into
mainfrom
fix/mjpeg-low-framerate-fallback
Draft

steveseguin wants to merge 2 commits into
mainfrom
fix/mjpeg-low-framerate-fallback

Conversation

@steveseguin

@steveseguin steveseguin commented Oct 4, 2026 •

Copy link
Copy Markdown
Owner

Problem

When a V4L2 camera advertises only a lower MJPEG frame rate than requested (for example, 15 fps capture and the default 30 fps output), the fallback removes the source-rate constraint but then requires fixed 30 fps output through videorate drop-only=true. A drop-only converter cannot produce that higher cadence, so negotiation fails and video does not start.

Change

Remove drop-only=true from the decoded MJPEG rate fallback, preserving max-rate and the requested output caps. Videorate can duplicate decoded frames when capture is slower and drop frames when it is faster. Adjust the diagnostic to describe rate conversion. Native H.264 passthrough remains unconstrained rather than modifying compressed frames.

Add one focused regression to the existing capture-mode test module, with 15/30/60 fps synthetic MJPEG subcases. It evaluates the actual fallback fragment from main, avoiding a duplicated implementation and any camera or signaling startup.

Verification

  • Native GStreamer 1.26.2 synthetic MJPEG through the actual source-generated suffix: baseline 15→30 fails not-negotiated (-4); fixed 15→30, 60→30 and source-supported 30→30 reach EOS.
  • The exact added regression, executed through a thin native ctypes adapter because local Gst GI typelibs are unavailable, fails only the 15 fps baseline subcase and passes all three fixed subcases.
  • Independent review reproduced the failure and fix, including 15→30 frame duplication and 60→30 frame dropping, and reviewed the final production/test changes.
  • Nine actual-source V4L2 selection probes pass, covering MJPEG rates, H.264 passthrough rates, missing-H.264 fallback, nearest size and missing mode data. Eight existing capture-mode/decoder tests and nine device-resolution tests pass with isolated source and stand-ins where needed. Thirteen existing QA camera/raw caps tests pass against native GStreamer through a thin ctypes caps adapter.
  • Changed files compile and parse with Python 3.9 grammar. Direct local import of the capture test module is blocked by missing gi; the complete application test suite has not passed locally. Compatibility CI passed all 151 tests, including the added native regression, on Bullseye/Python 3.9/GStreamer 1.18, Bookworm/3.11/1.22, and Trixie/3.13/1.26 at final head 0b5c4c46665be14230f0570f22b03440f043479c.

Reviewed against main 4f94ca2dcfced9f67eb72acf4102518cd3ef6674. No physical camera, remote board, live media, external signaling, merge or deployment was used. Native synthetic media establishes rate negotiation only; this is not a hardware or end-to-end interoperability claim. This is independent of recording fixes #57 and #58.

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

This branch has not been deployed

No deployments
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.

2 participants