Skip to content

Video: unify rendering on videoconvert→appsink + cross-platform zero-copy#14332

Merged
HTRamsey merged 1 commit into
mavlink:masterfrom
HTRamsey:refactor/video-appsink
May 9, 2026
Merged

Video: unify rendering on videoconvert→appsink + cross-platform zero-copy#14332
HTRamsey merged 1 commit into
mavlink:masterfrom
HTRamsey:refactor/video-appsink

Conversation

@HTRamsey
Copy link
Copy Markdown
Collaborator

@HTRamsey HTRamsey commented May 5, 2026

Summary

Replaces the per-platform custom GStreamer sinks (qml6glsink, qml6d3d11sink) with a single qgcvideosinkbin that pushes frames to a QVideoSink via appsink + a thin adapter (GstAppSinkAdapter). Adds optional zero-copy GPU paths (DMABuf/EGLImage on Linux, D3D11 on Windows, IOSurface on macOS, AHardwareBuffer on Android) with automatic per-frame fallback to a CPU copy if a GPU import fails.

The Linux GPU path routes through glupload so va's DMA_DRM DMABuf output is imported into GL textures (still zero-copy) and consumed as GLMemory by appsink — works on GStreamer 1.24+ with the Mesa va plugin without needing 1.26's format=DMA_DRM appsink negotiation.

Why

  • Single rendering pipeline shrinks the per-platform surface area (no more custom QML sink plugins to maintain per Qt version, no gstqml6gl/, no gstqml6d3d11/).
  • Consolidates the video → Qt boundary in GstAppSinkAdapter, which makes telemetry, fallback, and lifecycle uniform across receivers.
  • Zero-copy is now automatic when the decoder + driver supports it; users no longer pick between sinks.

What changes

Pipeline

  • New element qgcvideosinkbin (LGPL, ships in-tree): one bin with two construction modes selected by a construct-only gpu-zerocopy GObject prop.
    • CPU path (gpu-zerocopy=FALSE): videoconvert → appsink accepting widely-supported formats. Always works.
    • GPU path (gpu-zerocopy=TRUE): platform-specific zero-copy. On Linux: glupload → appsink with memory:GLMemory caps. On other platforms: bare appsink with the platform's native memory feature in caps (memory:D3D11Memory, memory:AHardwareBuffer, etc.).
  • Old custom sinks (qml6glsink, qml6d3d11sink) removed.

Adapter (GstAppSinkAdapter)

  • Pulls samples from appsink, parses caps once per caps-change (cached), dispatches to the matching QHwVideoBuffer subclass via makeHwVideoBuffer() factory.
  • Per-frame factory returns nullptr ⇒ adapter copies to system memory (CPU fallback path) instead of crashing.
  • Q_PROPERTY telemetry: gpuFrameCount, cpuFrameCount, gpuFallbackCount for runtime introspection (1 Hz throttled signal).
  • DMA_DRM caps (GStreamer 1.24+) parsed via gst_video_info_dma_drm_from_caps so future decoders that emit them work without further changes.
  • Reads gpu-zerocopy back from the bin via g_object_get after construction so the adapter's path mode can never disagree with the bin's actual pipeline (eliminates a class of fact-vs-bin desync bugs).

QHwVideoBuffer implementations

  • GstDmaBufVideoBuffer — Linux DMABuf via EGLImage import, modifier-aware (EGL_EXT_image_dma_buf_import_modifiers).
  • GstGlVideoBuffer — generic GLMemory wrap with proper GstGLSyncMeta flush before texture access.
  • GstD3D11VideoBuffer — Windows D3D11Memory share with QRhi's D3D11 backend; ref-leak-safe on early-exit.
  • GstIOSurfaceVideoBuffer — macOS CoreVideo CVPixelBuffer via gst_apple_core_video_memory_get_pixel_buffer() (replaces a UB pointer-cast heuristic).
  • GstAHardwareBufferVideoBuffer — Android AHardwareBuffer via eglGetNativeClientBufferANDROID (gst-plugins-bad ≥ 1.28).
  • GstHwVideoBuffer base + GstHwVideoBufferFactory consolidate the previously copy-pasted GstSample/info/format ownership and dispatch.

Context bridges

  • GstGlContextBridge — Linux GL context bridge for glupload's NEED_CONTEXT bus message. Tries Qt's EGL native interface first (Wayland/eglfs/xcb_egl), falls back to GLX (the xcb default on Qt 6 desktop) wrapping GstGLDisplayX11 + GST_GL_PLATFORM_GLX.
  • GstD3D11ContextBridge — Windows D3D11 device wrap via gst_d3d11_device_wrap.
  • GstContextBridgeRegistry — replaces a hardcoded #if chain in GstVideoReceiver with a registry-based dispatcher.

Settings

  • gpuZeroCopyEnabled (default off, "experimental") replaced with forceCpuVideoPath (default off, no "experimental" framing). Default behavior is now: use GPU when the decoder supports it, fall back to CPU per-frame on import failure. The new flag is a debug escape hatch that forces the CPU path.
  • forceCpuVideoPath=true and forceVideoDecoder=Software both resolve to the CPU pipeline. Software decoder + GPU path is structurally impossible (SW decoders output system memory) — handled silently in GStreamer::createVideoSink, no warning needed.

Tests

  • 30 GStreamer unit tests; new ones cover: CPU/GPU bin construction, GLMemory dispatch, DMABuf fallback (synthesized via factory mock), caps cache invalidation, teardown under load, context bridge registry fanout, Q_PROPERTY telemetry signal, QGCRhiCapture cache lifecycle, CPU memcpy active-row stride correctness.

Verified on Linux desktop (xcb, GStreamer 1.24.2)

RTSP H.265 4K @ 10 fps from a Dahua camera, vah265dec selected by decodebin3:

Setting Bin pipeline Allocator Frame stats (1 min)
Default glupload → appsink GLMemoryPBO GL:627/0
forceCpuVideoPath=true videoconvert → appsink SystemMemory CPU:387
forceVideoDecoder=Software videoconvert → appsink SystemMemory CPU:n

Start/stop exercised across multiple process cycles; clean teardown (Adapter teardown — CPU:0 DMABuf:0 GL:627 GL-failures:0), no leaks reported.

Performance

Same throughput across all three modes when the camera is the bottleneck. Differences scale with resolution and stream count:

  • Default GPU path — 0 CPU memcpy per frame, ~0 PCIe round-trip bandwidth.
  • Force CPU — 1× GPU→CPU download (videoconvert) + 1× CPU→GPU upload (QRhi) per frame. ~750 MB/s memory bandwidth at 4K@30, ~1.5 GB/s at 4K@60.
  • Force SW decoder — adds CPU decode cost (4K HEVC ~150–300% of one core); the only path with a hard real-time ceiling.

The GPU path is what makes multi-stream viable; per-stream marginal cost on the GPU path is essentially decode + render budget, with no cross-bus traffic.

Test plan

  • Linux desktop (xcb, GStreamer 1.24.2): RTSP H.265 4K, default + forceCpuVideoPath=true + forceVideoDecoder=Software
  • All 30 GStreamer unit tests pass
  • Wayland session
  • Windows + D3D11 zero-copy
  • macOS + IOSurface zero-copy
  • Android + AHardwareBuffer zero-copy
  • GStreamer 1.28 SDK (CI)
  • Multi-stream concurrency (videoContent + thermalVideo)
  • Recording branch (filesink) under both CPU and GPU modes

@codecov
Copy link
Copy Markdown

codecov Bot commented May 6, 2026

Codecov Report

❌ Patch coverage is 21.47344% with 1375 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (master@c70bab0). Learn more about missing BASE report.

Files with missing lines Patch % Lines
...nager/VideoReceiver/GStreamer/GstAppSinkAdapter.cc 32.27% 315 Missing and 132 partials ⚠️
...ceiver/GStreamer/HwBuffers/GstDmaBufVideoBuffer.cc 1.68% 233 Missing ⚠️
...anager/VideoReceiver/GStreamer/GstVideoReceiver.cc 0.00% 153 Missing and 2 partials ⚠️
...Receiver/GStreamer/HwBuffers/GstGlContextBridge.cc 13.17% 123 Missing and 22 partials ⚠️
...deoReceiver/GStreamer/gstqgc/gstqgcvideosinkbin.cc 39.59% 75 Missing and 44 partials ⚠️
...eoReceiver/GStreamer/HwBuffers/GstGlVideoBuffer.cc 7.36% 88 Missing ⚠️
.../VideoManager/VideoReceiver/GStreamer/GStreamer.cc 0.00% 39 Missing and 6 partials ⚠️
...ver/GStreamer/HwBuffers/GstHwVideoBufferFactory.cc 16.00% 28 Missing and 14 partials ⚠️
src/Settings/VideoSettings.cc 3.22% 24 Missing and 6 partials ⚠️
src/VideoManager/VideoManager.cc 0.00% 21 Missing ⚠️
... and 10 more

❌ Your patch check has failed because the patch coverage (21.47%) is below the target coverage (30.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##             master   #14332   +/-   ##
=========================================
  Coverage          ?   25.30%           
=========================================
  Files             ?      764           
  Lines             ?    65542           
  Branches          ?    30308           
=========================================
  Hits              ?    16586           
  Misses            ?    37296           
  Partials          ?    11660           
Flag Coverage Δ
unittests 25.30% <21.47%> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/Settings/VideoSettings.h 14.28% <ø> (ø)
src/VideoManager/VideoManager.h 0.00% <ø> (ø)
...eoManager/VideoReceiver/GStreamer/gstqgc/gstqgc.cc 100.00% <100.00%> (ø)
...er/VideoReceiver/GStreamer/gstqgc/gstqgcelement.cc 60.00% <ø> (ø)
...ideoReceiver/GStreamer/gstqgc/gstqgcvideosinkbin.h 100.00% <ø> (ø)
src/QGCApplication.cc 21.44% <0.00%> (ø)
...anager/VideoReceiver/GStreamer/GStreamerHelpers.cc 36.69% <0.00%> (ø)
...anager/VideoReceiver/GStreamer/GstAppSinkAdapter.h 0.00% <0.00%> (ø)
...eceiver/GStreamer/HwBuffers/GstDmaBufVideoBuffer.h 0.00% <0.00%> (ø)
...anager/VideoReceiver/GStreamer/GStreamerLogging.cc 19.35% <0.00%> (ø)
... and 15 more

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update c70bab0...7dafa79. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

Build Results

Platform Status

Platform Status Details
Linux Passed View
Windows Passed View
MacOS Passed View
Android Passed View

All builds passed.

Pre-commit

Check Status Details
pre-commit Failed (non-blocking) View

Pre-commit hooks: 4 passed, 44 failed, 7 skipped.

Test Results

linux-coverage: 90 passed, 0 skipped
Total: 90 passed, 0 skipped

Code Coverage

Coverage Baseline Change
59.1% 59.2% -0.1%

Artifact Sizes

Artifact Size Δ from master
QGroundControl 216.84 MB -4.65 MB (decrease)
QGroundControl-aarch64 176.75 MB -0.02 MB (decrease)
QGroundControl-installer-AMD64 134.72 MB -0.01 MB (decrease)
QGroundControl-installer-AMD64-ARM64 77.31 MB +0.00 MB (increase)
QGroundControl-installer-ARM64 106.03 MB -0.03 MB (decrease)
QGroundControl-linux 335.07 MB -1.97 MB (decrease)
QGroundControl-mac 187.07 MB -1.14 MB (decrease)
QGroundControl-windows 187.09 MB -1.14 MB (decrease)
QGroundControl-x86_64 171.94 MB -0.41 MB (decrease)
Total size decreased by 9.37 MB

Updated: 2026-05-09 06:29:19 UTC • Triggered by: Android

@HTRamsey HTRamsey force-pushed the refactor/video-appsink branch 4 times, most recently from 81018d4 to bfc8da4 Compare May 8, 2026 02:55
@HTRamsey HTRamsey requested review from DonLakeFlyer May 8, 2026 02:55
@HTRamsey HTRamsey force-pushed the refactor/video-appsink branch 2 times, most recently from 1a05440 to 16cea1b Compare May 8, 2026 16:13
@github-actions github-actions Bot added the Tools label May 8, 2026
@HTRamsey HTRamsey force-pushed the refactor/video-appsink branch 2 times, most recently from a4982c4 to 96cec4b Compare May 8, 2026 17:05
@HTRamsey
Copy link
Copy Markdown
Collaborator Author

HTRamsey commented May 8, 2026

@HTRamsey HTRamsey force-pushed the refactor/video-appsink branch 3 times, most recently from 914b174 to 29f876c Compare May 8, 2026 18:13
@jnomikos
Copy link
Copy Markdown
Contributor

jnomikos commented May 8, 2026

I tested on both Ubuntu 24.04 and Android and it seems to be working well on my end.

@HTRamsey HTRamsey force-pushed the refactor/video-appsink branch 6 times, most recently from a31a92f to 754cefc Compare May 8, 2026 22:08
@HTRamsey HTRamsey marked this pull request as ready for review May 8, 2026 22:09
Copilot AI review requested due to automatic review settings May 8, 2026 22:09
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Unifies QGroundControl’s GStreamer video rendering by removing the custom per-platform Qt6 QML sink plugins and routing all decoded frames through a single qgcvideosinkbin (videoconvert/gluploadappsink) into Qt’s VideoOutput via a new GstAppSinkAdapter, with optional per-platform zero-copy GPU import paths and CPU fallback.

Changes:

  • Replaces qml6glsink / qml6d3d11sink usage with a single in-tree qgcvideosinkbin + appsinkQVideoSink adapter flow.
  • Adds cross-platform GPU zero-copy infrastructure (GLMemory/DMABuf/D3D11/D3D12/IOSurface/AHardwareBuffer) plus context-bridge plumbing and telemetry.
  • Updates QML/UI/settings/tests to use QtMultimedia.VideoOutput and introduces the forceCpuVideoPath setting (with legacy migration).

Reviewed changes

Copilot reviewed 87 out of 87 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tools/setup/build-gstreamer.py Updates CLI help text for Qt prefix usage.
test/VideoManager/GStreamer/GStreamerTest.h Adds declarations for expanded GStreamer/appsink/zero-copy tests.
test/VideoManager/GStreamer/CMakeLists.txt Adjusts test target notes/documentation.
test/Camera/VideoManagerTest.h Renames unit test to match new QML type expectation.
test/Camera/VideoManagerTest.cc Switches unit test QML from custom Gst item to QtMultimedia.VideoOutput.
src/VideoManager/VideoReceiver/GStreamer/VideoItemStub.h Removes stub QML item previously used for custom sink types.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/QGCRhiCapture.h Adds helper API to capture/cache the live QRhi*.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/QGCRhiCapture.cc Implements QRhi caching and bridge reset on scene graph teardown.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstIOSurfaceVideoBuffer.mm Adds IOSurface/CVPixelBuffer zero-copy buffer wrapper (Metal).
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstIOSurfaceVideoBuffer.h Declares IOSurface zero-copy buffer wrapper.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstHwVideoBufferFactory.h Declares factory for selecting per-sample GPU buffer wrappers.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstHwVideoBufferFactory.cc Implements dispatch to DMABuf/GL/D3D/IOSurface/AHB wrappers with CPU fallback.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstHwVideoBuffer.h Introduces common base class for GStreamer-backed QHwVideoBuffers.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstHwVideoBuffer.cc Implements GstSample lifetime ownership for the base buffer class.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstGlVideoBuffer.h Declares GLMemory zero-copy buffer wrapper.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstGlVideoBuffer.cc Implements GLMemory texture wrapping + sync handling.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstGlContextBridge.h Declares Qt↔gst-gl context bridging API.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstGlContextBridge.cc Implements NEED_CONTEXT/query handling and bridge registration/reset.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstDmaBufVideoBuffer.h Declares DMABuf→EGLImage zero-copy wrapper.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstDmaBufVideoBuffer.cc Implements DMABuf import (modifier-aware) and texture lifecycle.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstD3DVideoBufferCommon.h Adds shared D3D11/D3D12 frame-texture scaffolding and diagnostics.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstD3DContextBridgeCommon.h Declares shared D3D context bridge helpers.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstD3DContextBridgeCommon.cc Implements shared QRhi backend checks and NEED_CONTEXT matching/logging.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstD3D12VideoBuffer.h Declares D3D12 zero-copy buffer wrapper.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstD3D12VideoBuffer.cc Implements D3D12 resource import with slice staging when required.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstD3D12ContextBridge.h Declares D3D12 device bridging for gst-d3d12 elements.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstD3D12ContextBridge.cc Implements D3D12 device creation/dispatch and bridge registration/reset.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstD3D11VideoBuffer.h Declares D3D11 zero-copy buffer wrapper.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstD3D11VideoBuffer.cc Implements D3D11 texture import with slice staging when required.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstD3D11ContextBridge.h Declares D3D11 device bridging for gst-d3d11 elements.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstD3D11ContextBridge.cc Implements D3D11 device wrapping/dispatch and bridge registration/reset.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstContextBridgeRegistry.h Declares registry to fan out GstBus sync messages to bridges.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstContextBridgeRegistry.cc Implements registry, reset fanout, and test-only clearing.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstAHardwareBufferVideoBuffer.h Declares Android AHardwareBuffer zero-copy wrapper.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstAHardwareBufferVideoBuffer.cc Implements AHardwareBuffer import via EGLImage/ExternalOES.
src/VideoManager/VideoReceiver/GStreamer/HwBuffers/CMakeLists.txt Adds build-time feature detection and per-platform GPU-path compilation.
src/VideoManager/VideoReceiver/GStreamer/GstVideoReceiver.h Adds decoder/QoS stats properties and probe state to receiver.
src/VideoManager/VideoReceiver/GStreamer/GStreamerLogging.cc Renames logging categories for consistency.
src/VideoManager/VideoReceiver/GStreamer/GStreamerHelpers.cc Renames logging category and updates decoder-rank comment.
src/VideoManager/VideoReceiver/GStreamer/GStreamer.h Renames and generalizes sink adapter setup API.
src/VideoManager/VideoReceiver/GStreamer/GStreamer.cc Switches to appsink-based sinkbin creation and shared adapter setup; updates plugin checks.
src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqml6gl/qt6/qt6glitem.h Removes custom Qt6 GL QML sink code (deleted).
src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqml6gl/qt6/gstqt6glutility.h Removes custom Qt6 GL QML sink utilities (deleted).
src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqml6gl/qt6/gstqt6glutility.cc Removes custom Qt6 GL QML sink utilities impl (deleted).
src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqml6gl/qt6/gstqt6gl.h Removes custom Qt6 GL QML sink header (deleted).
src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqml6gl/qt6/gstqt6elements.h Removes custom Qt6 GL QML sink elements header (deleted).
src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqml6gl/qt6/gstqt6element.cc Removes custom Qt6 GL QML sink registration (deleted).
src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqml6gl/qt6/gstqsg6glnode.h Removes GL scenegraph node for old sink (deleted).
src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqml6gl/qt6/gstqsg6glnode.cc Removes GL scenegraph node impl for old sink (deleted).
src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqml6gl/qt6/gstqml6glsink.h Removes old qml6gl sink header (deleted).
src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqml6gl/qt6/gstplugin.cc Removes old qml6gl plugin glue (deleted).
src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqml6gl/gstqml6glregister.h Removes old QML type registration shim (deleted).
src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqml6gl/gstqml6glregister.cpp Removes old QML type registration shim (deleted).
src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqml6gl/CMakeLists.txt Removes build for old qml6gl plugin (deleted).
src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqml6d3d11/gstqml6d3d11register.h Removes old D3D11 QML type registration shim (deleted).
src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqml6d3d11/gstqml6d3d11register.cpp Removes old D3D11 QML type registration shim (deleted).
src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqml6d3d11/CMakeLists.txt Removes build for old qt6d3d11 sink plugin (deleted).
src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqgcvideosinkbin.h Updates sink bin struct and adds appsink accessor API.
src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqgcelements.h Adds include guard + exports debug category pointer.
src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqgcelement.cc Switches debug category from static to exported definition.
src/VideoManager/VideoReceiver/GStreamer/gstqgc/gstqgc.cc Updates plugin init and versioning to use QGC app version.
src/VideoManager/VideoReceiver/GStreamer/gstqgc/CMakeLists.txt Stops building old sink plugins; documents static registration model.
src/VideoManager/VideoReceiver/GStreamer/GstAppSinkAdapter.h Expands adapter API: telemetry properties, caps cache helpers, GPU-path plumbing.
src/VideoManager/VideoReceiver/GStreamer/CMakeLists.txt Adjusts GStreamer deps and wires appsink adapter + HwBuffers subdir.
src/VideoManager/VideoManager.h Removes per-platform sink capability properties from API.
src/VideoManager/VideoManager.cc Removes old QML sink registration/stubs; wires QRhi capture and unified adapter setup.
src/UI/AppSettings/pages/Video.SettingsUI.json Adds UI control for forceCpuVideoPath.
src/Settings/VideoSettings.h Adds forceCpuVideoPath setting fact.
src/Settings/VideoSettings.cc Migrates legacy zero-copy setting and exposes new force-CPU setting visibility.
src/Settings/Video.SettingsGroup.json Adds forceCpuVideoPath setting metadata and descriptions.
src/QGCApplication.cc Removes OpenGL probing logic; keeps default graphics API for appsink→VideoOutput path.
src/FlyView/QGCVideoBackgroundD3D11.qml Removes old D3D11-specific video background (deleted).
src/FlyView/QGCVideoBackground.qml Removes old GL-specific video background (deleted).
src/FlyView/FlightDisplayViewVideoOutput.qml Adds VideoOutput-based FlyView video component and fillMode mapping.
src/FlyView/FlightDisplayViewVideo.qml Switches loaders to the unified VideoOutput component for all platforms.
src/FlyView/FlightDisplayViewGStreamerD3D11.qml Removes old custom D3D11 Gst QML item usage (deleted).
src/FlyView/FlightDisplayViewGStreamer.qml Removes old custom GL Gst QML item usage (deleted).
src/FlyView/CMakeLists.txt Updates QML module file list to remove old components and add VideoOutput component.
cmake/platform/Apple.cmake Enables OBJC/OBJCXX at root scope for .mm compilation.
cmake/find-modules/FindQGCGStreamer.cmake Updates iOS discovery, plugin lists, xcframework handling, and feature probes.
cmake/find-modules/FindGStreamer.cmake Fixes component re-find behavior and makes imported targets GLOBAL.
Comments suppressed due to low confidence (1)

cmake/find-modules/FindQGCGStreamer.cmake:629

  • The xcframework branch sets GStreamer_USE_XCFRAMEWORK and the slice paths, but then falls through into the “Classic .framework path” block which re-normalizes paths and sets GStreamer_USE_FRAMEWORK, likely clobbering the xcframework configuration. This used to return(); consider restoring the early-exit (or wrapping the classic path in an else()) so xcframework and framework discovery don’t both run.
        _gst_normalize_and_validate_root()
    endif()

    # ── Classic .framework path ───────────────────────────────────────────────
    _gst_normalize_and_validate_root()

Comment on lines +862 to +867
if (GstElementFactory *factory = gst_element_factory_find("qgcvideosinkbin")) {
videoSinkBin = gst_element_factory_create_full(factory,
"gpu-zerocopy", gpuZeroCopy ? TRUE : FALSE,
NULL);
gst_object_unref(factory);
}
Comment on lines +216 to +220
const EGLint attribs[] = { EGL_NONE };
EGLImageKHR image = eglCreateImageKHR_(_eglDisplay, EGL_NO_CONTEXT,
EGL_NATIVE_BUFFER_ANDROID,
clientBuffer, attribs);
if (image == EGL_NO_IMAGE_KHR) {
Comment thread src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstD3D11ContextBridge.h Outdated
Comment thread src/VideoManager/VideoReceiver/GStreamer/HwBuffers/GstD3D12ContextBridge.h Outdated
@HTRamsey HTRamsey force-pushed the refactor/video-appsink branch 8 times, most recently from 0459bfa to 07c50ad Compare May 9, 2026 04:54
Drop the vendored qml6glsink and qml6d3d11sink modules (and the
gst-plugins-good / gst-plugins-bad source downloads they required) and
funnel all GStreamer rendering through a single videoconvert→appsink →
GstAppSinkAdapter → QVideoSink → QML VideoOutput chain. Qt picks the
native RHI backend (Metal / Vulkan / D3D11 / OpenGL), so QGCApplication
no longer probes for an OpenGL context or forces a graphics API.

qgcvideosinkbin loses the d3d11sink and glsinkbin fallbacks plus the
widget / aspect-ratio properties they exposed. GStreamer.cc drops the
qml6 / qt6d3d11 / opengl static plugin registrations and verifies only
appsink / qgc / coreelements; the iOS xcframework no longer needs the
opengl plugin filter. VideoManager removes gstreamerD3D11Sink and
gstreamerAppleSink (the QML side now picks one VideoOutput component
unconditionally), and FlightDisplayViewMetal.qml is renamed to
FlightDisplayViewVideoOutput.qml to reflect the universal path.
@HTRamsey HTRamsey force-pushed the refactor/video-appsink branch from 07c50ad to 7dafa79 Compare May 9, 2026 05:49
@HTRamsey HTRamsey merged commit 4cb9d91 into mavlink:master May 9, 2026
29 of 31 checks passed
@HTRamsey HTRamsey deleted the refactor/video-appsink branch May 9, 2026 07:11
@Ryanf55
Copy link
Copy Markdown
Contributor

Ryanf55 commented May 12, 2026

Can we find a way to not rely on the #include <private/qvideotexturehelper_p.h>? This PR has broken compilation on Ubuntu 22, even though I am using QGC 6.10.1.

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.

4 participants