Skip to content

Fix GStreamer pipeline for MJPG v4l2 capture - #8572

Merged
danoli3 merged 1 commit into
openframeworks:masterfrom
PeteHaughie:fix/gst-mjpg-pipeline
Oct 5, 2026
Merged

danoli3 merged 1 commit into
openframeworks:masterfrom
PeteHaughie:fix/gst-mjpg-pipeline

Conversation

@PeteHaughie

Copy link
Copy Markdown
Contributor

Summary

ofGstVideoGrabber::setup() builds a broken GStreamer pipeline for MJPG (v4l2) cameras, so capture fails on Linux with Internal data stream error. Two independent defects in the pipeline string builder:

  1. decodebin appended after jpegdec. The decoder selection is:

    if (format.mimetype == "image/jpeg")    decodebin  = "! jpegdec ";
    if (format.mimetype == "video/x-bayer") decodebin  = "! bayer2rgb ";
    else if (encoded/unknown)               decodebin += "! decodebin ";

    The second if is not chained to the jpeg branch, and an MJPG device's format_name ("MJPG") maps to GST_VIDEO_FORMAT_UNKNOWN, so "! decodebin " is appended after jpegdec. decodebin cannot link the raw video jpegdec emits -> streaming stopped, reason not-linked (-1).

  2. videoscale overwrites videoconvert. When the requested size differs from the selected device format:

    if (format_name != getGstFormatName(internalPixelFormat)) scale  = "! videoconvert ";
    if (w != format.width || h != format.height)              scale  = "! videoscale method=2 ";  // clobbers the above

    With internalPixelFormat defaulting to OF_PIXELS_RGB, the appsink's RGB caps are then never satisfied -> reason not-negotiated (-4).

Reproduction

Any Linux v4l2 camera that exposes MJPG, when the size passed to ofVideoGrabber::setup(w, h) differs from the format OF selects. Here: a USB capture card offering 720x576 MJPG, asked for 640x480.

Pipelines (from the ofGstUtils log):

  • before: v4l2src ! image/jpeg,width=720,height=576,framerate=30/1 ! jpegdec ! decodebin ! videoscale method=2 ! appsink caps="video/x-raw, format=RGB, width=640, height=480" -> not-linked
  • fix 1 only: jpegdec ! videoscale ! appsink(RGB) -> not-negotiated
  • after: jpegdec ! videoconvert ! videoscale method=2 ! appsink(RGB) -> streams

Verified with gst-launch-1.0 against the same device, and end-to-end on a Raspberry Pi 3 (headless KMS/GBM) with a MacroSilicon 534d:2109 UVC capture device.

Notes

  • Platform-independent; affects any GStreamer 1.x Linux build.
  • Only reachable when internalPixelFormat != OF_PIXELS_NATIVE (the default OF_PIXELS_RGB path).

For image/jpeg input the decoder selection built "! jpegdec ! decodebin":
the bayer/decodebin if-chain is separate from the jpegdec branch, and
format_name "MJPG" maps to GST_VIDEO_FORMAT_UNKNOWN, so "! decodebin "
was appended after jpegdec. decodebin cannot link the raw video jpegdec
emits, so v4l2src aborts with:
  Internal data stream error. ... streaming stopped, reason not-linked (-1)

Removing decodebin then exposes a second problem: when the requested size
differs from the selected device format, the videoscale assignment
overwrites the videoconvert set just above it, so the appsink's RGB caps
are never satisfied:
  streaming stopped, reason not-negotiated (-4)

Make the decoder selection a single if/else chain and append videoscale
instead of overwriting videoconvert. A 720x576 MJPG camera asked for
640x480 now builds and runs:
  v4l2src ! image/jpeg,width=720,height=576,framerate=30/1 !
  jpegdec ! videoconvert ! videoscale method=2 ! appsink (RGB 640x480)
Copilot AI balanced review requested due to automatic review settings October 4, 2026 09:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

Both targeted changes correctly address the described pipeline failures without introducing unresolved issues.

Review effort: Balanced
Findings: None

What changed in this PR

Fixes GStreamer pipeline construction for MJPG V4L2 capture.

Changes:

  • Prevents decodebin from being appended after jpegdec.
  • Preserves videoconvert when adding videoscale.
File Description
libs/​openFrameworks/​video/​ofGstVideoGrabber.cpp Corrects decoder selection and composes conversion/scaling stages.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@danoli3 danoli3 added this to the 0.12.2 milestone Oct 5, 2026
@danoli3
danoli3 merged commit 5052e08 into openframeworks:master Oct 5, 2026
20 checks passed
@danoli3

danoli3 commented Oct 5, 2026

Copy link
Copy Markdown
Member

thanks!

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants