fix(viewer): rotate 180 video in the ISP on the linuxfb boards (Pi 1/2/3)#3207
Merged
Conversation
Rotated video on the Qt5 linuxfb boards (Pi 1/2/3) collapses to ~2 fps because the software `videoflip` rotates every full-resolution frame on a single core. Issue #3198 only measured 90, but 180 is just as broken (measured 2.3 fps on a Pi 2 at 1080p30, vs 27 fps unrotated). 180 does not need the CPU at all: a horizontal flip plus a vertical flip composes to a 180 rotation, and the bcm2835 ISP exposes both as v4l2 controls on the same `v4l2convert` pass that already does the aspect-fit scale. Driving them via `extra-controls` keeps the pipeline fully hardware and restores the full frame rate. Measured on a Pi 2 (1080p30, HW decode ceiling 43.7 fps), by fpsdisplaysink: rotation 0 (all hardware) 27.2 fps rotation 180 (videoflip, before) 2.3 fps rotation 180 (ISP flip, after) 26.9 fps The ISP output is pixel-identical to the software rotation (mean absolute difference 0.00 against rot180 of the unflipped frame), and the integrated viewer stack on a Pi 2 reproduces the same result end to end: 0.5 -> 7.7 delivered fps at rotation 180, matching the unrotated reference, with the screen visibly rotated. 90/270 keep the software videoflip and stay slow: they need a transpose, and no bcm2835 device exposes a rotate control (`v4l2-ctl -l` on the ISP lists only hflip/vflip) — the same limit the pi3-64 vc4 DRM plane hits, which offers 0/180 + reflect only. Reordering to scale-before-flip does not rescue them either: the case that matters, portrait content on a portrait panel, rotates to exactly fill the framebuffer, so there is no downscale to exploit ahead of the flip (measured 1.9 vs 2.1 fps, i.e. slightly worse). Documented as unsupported instead of pretending otherwise. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
There was a problem hiding this comment.
Pull request overview
Improves video playback performance on Qt5/linuxfb Raspberry Pi 1/2/3 boards when screen_rotation=180 by offloading the rotation to the bcm2835 ISP (via v4l2convert extra-controls) instead of using the CPU-bound videoflip.
Changes:
- Update the fbdev GStreamer sink pipeline to apply 180° rotation using ISP
horizontal_flip+vertical_flipcontrols (keeping 90°/270° onvideoflip). - Extend unit tests to validate rotation-specific pipeline composition (90/270 use
videoflip, 180 uses ISP controls, 0 uses neither). - Document the rotation behavior and performance implications for Pi 1/2/3 in board enablement docs.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
src/anthias_viewer/gst_fbdev_player.py |
Adds ISP-driven 180° rotation via v4l2convert extra-controls, keeps 90/270 on videoflip, updates arg choices and docs in-code. |
tests/test_gst_fbdev_player.py |
Updates/expands tests to assert the intended pipeline structure for 0/90/180/270 rotations. |
docs/board-enablement.md |
Documents Pi 1/2/3 rotation limitations and the hardware fast-path for 180°. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
Rotated video on the Qt5 linuxfb boards (Pi 1/2/3) collapses to ~2 fps: the software
videofliprotates every full-resolution frame on a single core. Investigating #3198 on a real Pi 2 turned up two things that reshape it.First, 180 is just as broken as 90 — the issue only ever measured 90. Second, 180 doesn't need the CPU at all. A horizontal flip plus a vertical flip composes to a 180 rotation, and the bcm2835 ISP exposes both as v4l2 controls on the very
v4l2convertpass that already does the aspect-fit scale. Driving them throughextra-controlskeeps the pipeline fully hardware and restores the full frame rate.Measurements (real Pi 2, 1080p30, HW decode ceiling 43.7 fps)
Via
fpsdisplaysink:videoflip(before)videoflip(unchanged)The ISP result is not just fast, it's pixel-identical to the software rotation: mean absolute difference
0.00against a true 180 rotation of the unflipped frame.Validation
Beyond unit tests, this was validated on the integrated viewer stack on a Pi 2 (not a component harness) — same asset, same service, A/B'd against the shipping player:
videoflip)(That sampler under-reads in absolute terms because it costs CPU on a Pi 2; it's used for A/B only, which is why the absolute numbers come from
fpsdisplaysinkabove.) Framebuffer captures confirm the screen is visibly, correctly rotated. Testbed restored to its original state afterwards.Why 90/270 are left alone (and documented as unsupported)
The quarter turns need a transpose, and no bcm2835 device exposes a rotate control —
v4l2-ctl -lon the ISP lists onlyhorizontal_flip/vertical_flip, and nothing on any other video device. That's the same limit the pi3-64 vc4 DRM plane hits (0/180 + reflect only, forum 6730). Two independent blocks, one silicon limit.The "scale before flip" idea from the issue is a dead end, and I've dropped it: it only helps the letterboxed case, while the case that actually matters — portrait content on a portrait-mounted panel — rotates to exactly fill the framebuffer, leaving no downscale to exploit. Measured slightly worse: 1.9 vs 2.1 fps.
So 90/270 keep the software videoflip (visually correct, just slow) and
docs/board-enablement.mdnow states plainly that rotated video is unsupported on Pi 1/2/3 — use a Pi 4/5, where the platform layer rotates. Still images and web pages cost nothing per frame and are unaffected.Test plan
pytest tests/— 1187 passedruff check ./ruff format --checkcleanFixes #3198
🤖 Generated with Claude Code