fix(viewer): rotate pi3-64 video by dropping the vc4 overlay when rotated - #3189
Conversation
…ated On pi3-64 (VideoCore IV / eglfs) video is scanned out on a dedicated vc4 DRM overlay plane (kmssink, #3164) that the QOpenGLCompositor never touches, so QT_QPA_EGLFS_ROTATION rotates the UI/images/webpages but leaves the video landscape when the screen is set to portrait (reported on the forum: video locked horizontal regardless of rotation). The vc4 planes advertise only rotate-0 / rotate-180, so the overlay can't be turned 90/270 in hardware at all. Take the HW overlay path only when the screen is upright; when rotated, drop ANTHIAS_VIDEO_OVERLAY so VideoView falls back to the CPU-raster blit, whose widget composites through the eglfs-rotated backing store and so inherits the transform like images/webpages do. Upright keeps the full-rate HW overlay (30fps); rotated trades frame rate for correct orientation, the right call for a rotated screen. Also corrects the two stale "every Qt6 board rotates uniformly" comments that predated the overlay path. Verified on a real 64-bit Pi 3: unfixed rotation=90 leaves two active DRM planes (eglfs-rotated UI + a landscape video overlay); with the fix only the composited UI plane remains and the video rotates with it. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_017BbxH9mN3JPpKKF3VmkeCf
There was a problem hiding this comment.
Pull request overview
Adjusts AnthiasViewer’s environment setup so pi3-64 video correctly follows screen_rotation on eglfs by disabling the vc4 DRM overlay path when rotated, forcing the raster/composited fallback that inherits QT_QPA_EGLFS_ROTATION.
Changes:
- Update
_build_webview_env()to enableANTHIAS_VIDEO_OVERLAYonly whenscreen_rotation == 0onpi3-64, and actively drop any stale overlay flag when rotated. - Add unit tests covering upright vs. rotated overlay selection for
pi3-64. - Update rotation-related commentary in
media_player.pyand__init__.pyto reflect the pi3-64 overlay exception.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| tests/test_viewer.py | Adds assertions for pi3-64 env selection: upright keeps overlay, rotated drops overlay while preserving eglfs rotation. |
| src/anthias_viewer/media_player.py | Updates rotation rationale comments around per-video rotation behavior. |
| src/anthias_viewer/init.py | Implements the overlay drop-on-rotation behavior for pi3-64 and expands explanatory docs/comments. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The vc4 overlay plane can only rotate 0°/180° in hardware (measured: it advertises rotate-0 and rotate-180, no 90/270), so 90°/270° still fall to the eglfs-composited raster path — but 180° is a free scanout-time transform. VideoView::gstPlayOverlay now sets the kmssink plane's rotation=180 property when QT_QPA_EGLFS_ROTATION=180, and _build_webview_env keeps ANTHIAS_VIDEO_OVERLAY for 0°/180° (dropping it only for 90°/270°). Measured on a real 64-bit Pi 3 (1080p30 H.264): 180° now holds the full 30 fps at ~7% CPU with no thermal cost, versus ~9 fps and thermal throttling on the raster path. 90°/270° remain raster-only (a VideoCore IV hardware limit — no 90/270 plane rotation exists anywhere on the SoC). Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_017BbxH9mN3JPpKKF3VmkeCf
Hardware-validated on a real 64-bit Pi 3, with the trade-offs measuredExtended the fix after measuring frame drops on the raster path. Full picture (1080p30 H.264, 30s steady-state window each):
Why 90/270 can't be smooth (hardware limit): VideoCore IV has no 90/270 video rotation anywhere — the vc4 DRM planes advertise only Why 180° is now full-rate: a DRM plane Validation evidence (on the board): at 180°, |
Note: the GPU / zero-copy path was measured and is slower than raster on VC-IV — don't re-litigateThe obvious "just rotate on the GPU zero-copy like mpv/Kodi" idea was tested on the board (GStreamer GL vout,
The GL path imports the decoder dmabuf fine and rotates for free (6.6 vs 6.7 — identical), and stays cool (GPU-bound, not CPU). But VideoCore IV's V3D can't push 1080p GLES video above ~6.7 fps even with no rotation — below the CPU raster path. So zero-copy GPU rotation would be a regression for 90/270, not a fix. This is the same wall as #3084: the only thing on this SoC that presents 1080p30 is the display controller's scanout (the DRM overlay plane), which rotates 0/180 only. Smooth 90/270 portrait video needs Pi 4 (V3D 4.2) / Pi 5. Hence: overlay (+ HW plane rotate for 180) for 0/180, raster for 90/270. |
…tant - _build_video_options docstring: drop the stale ``video-rotate`` bullet (the dict is now audio-device only; rotation is handled at the platform layer) per Copilot. - videoview.cpp: use DRM_MODE_ROTATE_180 instead of the bare literal 4 in the kmssink plane-properties rotation, per Copilot. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_017BbxH9mN3JPpKKF3VmkeCf
…avior Copilot: the docstring still said the pi3-64 overlay is used "only when upright"; it's actually kept for 0°/180° (plane HW-rotate for 180°) and dropped only for 90°/270°. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_017BbxH9mN3JPpKKF3VmkeCf
|



Problem
On the 64-bit Raspberry Pi 3 (
pi3-64, VideoCore IV, eglfs), video plays but stays locked in landscape when the screen is set to a portraitscreen_rotation— while images, web pages and the UI all rotate correctly. Reported on the forum: https://forums.screenly.io/t/on-raspberry-pi-3-b-with-anthias-2026-07-1-it-seems-that-the-videos-dont-work/6730Root cause
pi3-64 can't present video through the QML
VideoOutputRHI path on the vc4 GL driver, so it scans the decoded frame out on a dedicated vc4 DRM overlay plane (kmssink), composited by the display controller. That plane is independent of the eglfsQOpenGLCompositor, soQT_QPA_EGLFS_ROTATION— which rotates the GL scene (UI / images / web pages) — never touches it. The vc4 planes also advertise onlyrotate-0/rotate-180, so the overlay can't be turned 90°/270° in hardware at all.Fix
Take the hardware overlay path only when the screen is upright. When rotated, drop
ANTHIAS_VIDEO_OVERLAYsoVideoViewfalls back to the CPU-raster blit, whose widget composites through the eglfs-rotated backing store and therefore inherits the rotation like images/web pages do.Also corrects two stale comments that assumed every Qt6 board rotates video uniformly at the platform layer (they predated the overlay path).
Validation
Unit tests cover the env selection (upright → overlay, rotated → raster, pi3-64 only). Verified end-to-end on a real 64-bit Pi 3:
screen_rotation=90: two active DRM planes — the eglfs-rotated UI plane plus a landscape video overlay plane (bug reproduced).screen_rotation=90: only the composited UI plane remains; the video is folded into it and rotates with the UI. The viewer process showsANTHIAS_VIDEO_RASTER=1,QT_QPA_EGLFS_ROTATION=90, and noANTHIAS_VIDEO_OVERLAY.🤖 Generated with Claude Code