feat(viewer,build,balena): add arm64/Qt6 pi3-64 board and the Rock Pi 4 fleet; keep 32-bit pi3 as legacy - #2985
Merged
Merged
Conversation
11 tasks
There was a problem hiding this comment.
Pull request overview
Adds a new pi3-64 board target to support Raspberry Pi 3 hardware running a 64-bit OS with the Qt 6 / eglfs viewer stack, while keeping the existing 32-bit pi3 (Qt 5) stream as legacy/maintenance. This extends the build/deploy pipeline, runtime board selection, and documentation so the new board is treated similarly to pi4-64.
Changes:
- Introduce
pi3-64as a first-class build target (image builder contexts, Dockerfile template, codecs, and media-player routing). - Update install/upgrade/runtime scripts to select
pi3-64on Pi 3 hardware whenuname -mreportsaarch64, and to apply the eglfs/KMS runtime DRM-card rewrite onpi3-64. - Wire
pi3-64through balena tooling + GitHub Actions workflows and update docs / Raspberry Pi Imager JSON generation + tests.
Reviewed changes
Copilot reviewed 19 out of 27 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| website/content/docs/installation-options.md | Document pi3-64 as the recommended 64-bit Pi 3 option; keep 32-bit Pi 3 as legacy. |
| website/content/docs/balena-fleet-deployment.md | Include pi3-64 in the supported $BOARD_TYPE list and explain legacy vs recommended. |
| tools/raspberry_pi_imager/tests/test_build_pi_imager_json.py | Extend Pi Imager JSON tests to cover pi3-64 artifacts and non-maintenance behavior. |
| tools/raspberry_pi_imager/build_pi_imager_json.py | Add pi3-64 to supported boards while keeping maintenance suffix limited to pi2/pi3. |
| tools/image_builder/utils.py | Add pi3-64 build parameters and treat it as a Qt 6 board in viewer context. |
| tools/image_builder/constants.py | Add pi3-64 to build target options. |
| tests/test_processing.py | Add test asserting Pi 3-64 HW decode codec set is H.264-only. |
| tests/test_media_player.py | Add test ensuring DEVICE_TYPE=pi3-64 forces MPV path despite model-string reporting pi3. |
| src/anthias_viewer/media_player.py | Force MPV selection when DEVICE_TYPE indicates pi3-64 to avoid Qt5/GStreamer routing. |
| src/anthias_viewer/init.py | Update rotation/platform comments to include pi3-64 under eglfs behavior. |
| src/anthias_server/processing.py | Add pi3-64 to HW decode codec mapping (H.264 only). |
| docs/board-enablement.md | Document the new pi3-64 stream and selection behavior. |
| docs/balena-fleet-host-config.md | Include pi3-64 in fleet host-config documentation and key applicability. |
| docker/eglfs-kms.json | Add shared eglfs KMS config template file. |
| docker/Dockerfile.viewer.j2 | Treat pi3-64 like pi4-64 for eglfs/KMS; copy the shared eglfs-kms.json. |
| bin/upgrade_containers.sh | Select pi3-64 on Pi 3 hardware when running aarch64; otherwise keep legacy pi3. |
| bin/start_viewer.sh | Apply runtime DRM-card selection rewrite for eglfs/KMS on both pi4-64 and pi3-64. |
| bin/install.sh | Select pi3-64 vs legacy pi3 based on uname -m on Pi 3 hardware. |
| bin/deploy_to_balena.sh | Allow pi3-64 as a valid --board option. |
| bin/balena_unpin_devices.py | Include anthias-pi3-64 fleet in the default fleet set. |
| bin/balena_ota_deploy.sh | Map board pi3-64 to the anthias-pi3-64 fleet for OTA deploys. |
| bin/balena_fleet_maintenance.py | Add fleet → device-type mapping for screenly_ose/anthias-pi3-64. |
| balena-host-config.json | Add host config entry for pi3-64 mirroring Pi 3 settings. |
| .github/workflows/scripts/mirror-latest-tags.sh | Mirror tags for the new pi3-64 board images. |
| .github/workflows/docker-build.yaml | Build/publish GHCR images for pi3-64 in the main matrix. |
| .github/workflows/deploy-balena-manual.yaml | Add pi3-64 to manual deploy workflow inputs and “all” expansion. |
| .github/workflows/build-balena-disk-image.yaml | Add pi3-64 to disk-image build/release workflows and fleet/image mapping. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…gacy Revises issue #2906 Phase 2. The original plan (delete the Qt 5 toolchain, force Pi 2/Pi 3 onto Qt 6) is abandoned: Qt 5 was fixed up on master and stays. Instead, add a NEW board target `pi3-64` — a 64-bit (arm64) Qt 6 viewer image for Raspberry Pi 3 hardware on a 64-bit OS — as its own image stream, disk image, and balena fleet. The legacy 32-bit armhf/Qt5 `pi3` board is left untouched and flagged as legacy/maintenance. pi3-64 mirrors the existing `pi4-64` path (Qt 6, eglfs_kms; video played in-process by AnthiasViewer's QtMultimedia pipeline — QMediaPlayer + the ffmpeg/libavcodec backend with V4L2 HW decode, no external player). VideoCore IV is H.264-only HW decode. Board selection is by `uname -m`: a Pi 3 on a 64-bit OS gets `pi3-64`, a 32-bit OS keeps `pi3` (the model string is identical on both arches). - image_builder: pi3-64 build params (arm64) + is_qt6; constants. - Dockerfile.viewer.j2 + start_viewer.sh: pi3-64 shares the pi4-64 eglfs KMS path; renamed board-agnostic eglfs-kms-pi4.json -> eglfs-kms.json. - Detection: install.sh / upgrade_containers.sh (aarch64 Pi 3 -> pi3-64). - Runtime: media_player force_mpv set (selects MPVMediaPlayer, the QtMultimedia D-Bus shim); processing codec grid {'h264'}. - CI: docker-build matrix + mirror-latest-tags. - Balena (fleet screenly_ose/anthias-pi3-64, device type raspberrypi3-64): disk-image + manual-deploy workflows, balena_ota_deploy.sh, balena_fleet_maintenance.py, balena_unpin_devices.py, deploy_to_balena.sh, balena-host-config.json. - Pi Imager: SUPPORTED_BOARDS += pi3-64 (non-maintenance); pi3 stays legacy. - Docs + tests. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
vpetersson
force-pushed
the
feature/pi3-64-qt6-board
branch
from
June 3, 2026 05:07
edc37af to
d8538ad
Compare
Copilot review: the list is introduced as 'links to the images', so the new pi3-64 entry should be navigable like the surrounding bullets. Link the label to the release-images section. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Wires the anthias-rockpi4 balena fleet (device type rockpi-4b-rk3399)
into the OTA deploy + disk-image pipeline. The fleet has no
board-specific image build: it runs the generic arm64 containers, so
bin/balena_ota_deploy.sh / bin/deploy_to_balena.sh map the rockpi4
board to the <short-hash>-arm64 image tags (and strip the /dev/vchiq
mount — no VideoCore on RK3399), and the disk-image preflight verifies
the arm64 images exist.
Root-cause fix for the fleet's codec gate: balena ships no
anthias_host_agent service, so host:board_subtype was never published
and resolve_device_key() stayed 'arm64' — whose HW-decode set is empty,
rejecting every video upload. The model-string → subtype table moves to
the dependency-free anthias_common.device_helper.detect_board_subtype
(single source, imported by host_agent), and
anthias_common.board.get_board_subtype now falls back to reading
/proc/device-tree/model in-container when Redis has no value. The
device tree is kernel-global — the same mechanism get_device_type has
always used for Pi detection — so the rockpi4 fleet resolves its
{h264, hevc} envelope without a host-side daemon, and compose installs
whose host_agent died self-heal too.
- build-balena-disk-image.yaml: rockpi4 in both matrices, fleet +
rockpi-4b-rk3399 image cases, arm64 images in the preflight check.
- deploy-balena-manual.yaml: rockpi4 board option.
- balena-host-config.json: rockpi4 declared {} (config.txt is
RPi-only; the reconcile hard-fails on a missing key).
- balena_fleet_maintenance.py / balena_unpin_devices.py: fleet added.
- tests: get_board_subtype Redis-first + device-tree-fallback order;
detect_board_subtype patch targets follow the move.
- docs: board-enablement, balena-fleet-host-config,
installation-options.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
5 tasks
vpetersson
added a commit
that referenced
this pull request
Jun 7, 2026
- CalVer (YYYY.0M.MICRO); still June 2026, micro 1 -> 2 - Ships the Qt 6 video audio fix (#3001) — PulseAudio in the viewer container; videos were silent on pi4-64/pi5/x86/arm64 since the QtMultimedia migration - Adds the arm64/Qt6 pi3-64 board and the Rock Pi 4 fleet (#2985) - Page-load watchdog so a stalled fetch can't freeze the display (#3003), Sentry error tracking for the Django services (#3007) - Redis data persisted to the mounted volume so device identity survives recreation (#2983); unpinner also rolls OS + supervisor updates (#2984) - Streamed backup downloads (#3005), 12-hour AM/PM asset times (#3002), BuildKit frontend via mirror.gcr.io (#3008) Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
5 tasks
vpetersson
added a commit
that referenced
this pull request
Jul 5, 2026
* fix(build): ship +rpt1 ffmpeg on pi3-64 so H.264 uses HW decode - pi3-64 was omitted from the _rpt1-ffmpeg-pin.j2 board gate, so it shipped stock Debian ffmpeg (no v4l2_request/SAND/vout-drm) while its sibling pi4-64 got the Pi-patched +rpt1 build - consequence: QtMultimedia can't engage the VideoCore IV bcm2835 H.264 decoder and falls back to software; SW can't sustain 1080p30 on the Pi 3 (measured 0.74x realtime) and drops frames / stalls presentation under load (issue #3084) - the gate (#2885) predates the pi3-64 board (#2985), which was grouped with pi4-64 everywhere else; add pi3-64 here too - verified via rendered Dockerfiles: pi3-64/pi4-64/pi5/arm64 now carry the +rpt1 pin; x86 and the Qt5 boards (pi2/pi3) stay on stock Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> * docs(build): clarify pi3-64 uses V4L2 M2M, not v4l2_request Copilot review: the Pi 3-64 comment implied the HW-decode path is v4l2_request/DRM. It's actually the stateful bcm2835-codec V4L2 M2M decoder (h264_v4l2m2m). Reword to say so and anchor to the on-device result (stock=SW, +rpt1=/dev/video10). Comment-only; gate unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> --------- Co-authored-by: Claude Opus 4.8 (1M context) <[email protected]>
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.



Issues Fixed
Continues #2906 (Phase 2, revised). Supersedes #2917 — same goal, different approach: rather than deleting the Qt 5 toolchain and moving Pi 2 / Pi 3 to Qt 6, this keeps Qt 5 (now fixed up on master) and adds a separate 64-bit Qt 6 image stream for the Pi 3. Also adds the new
screenly_ose/anthias-rockpi4balena fleet.Description
New board
pi3-64. A 64-bit (arm64) Qt 6 viewer image for Raspberry Pi 3 hardware running a 64-bit OS, with its own image stream, disk image, and balena fleet (screenly_ose/anthias-pi3-64, device typeraspberrypi3-64). The legacy 32-bit armhf / Qt 5pi3board is left untouched and flagged as legacy/maintenance.pi3-64reuses the existingpi4-64path — arm64, Qt 6 from Debian Trixie apt,eglfs+ KMS config, and in-process QtMultimedia video (QMediaPlayer→ QMLVideoOutput, ffmpeg/libavcodec backend with V4L2 HW decode; no external player, no cage/wayland). VideoCore IV hardware decode is H.264-only.Devices pick the stream by OS architecture: a Pi 3 reports the same model string on both arches, so
bin/install.sh/bin/upgrade_containers.shselectpi3-64whenuname -misaarch64and the legacypi3otherwise. There is no in-place arch switch — moving a device to the 64-bit stream requires reflashing to a 64-bit OS, so existing 32-bit Pi 3 / Pi 2 deployments are unaffected.New Rock Pi 4 fleet.
screenly_ose/anthias-rockpi4(balena device typerockpi-4b-rk3399) joins the OTA deploy + disk-image pipeline. There is no rockpi4-specific image build — the fleet runs the generic arm64 containers, sobin/balena_ota_deploy.sh/bin/deploy_to_balena.shpin the<short-hash>-arm64image tags for it (and strip the/dev/vchiqmount; no VideoCore on RK3399), and the release preflight verifies the arm64 images exist.That fleet surfaced a real gap: balena ships no
anthias_host_agentservice, sohost:board_subtypewas never published andresolve_device_key()stayedarm64— whose HW-decode set is empty, i.e. every video upload would have been rejected on the fleet. Root-cause fix: the model-string → subtype table moves to the dependency-freeanthias_common.device_helper.detect_board_subtype(single source, imported by host_agent), andanthias_common.board.get_board_subtypenow falls back to reading/proc/device-tree/modelin-container when Redis has no value. The device tree is kernel-global — the same mechanismget_device_typehas always used for Pi detection — so the rockpi4 fleet resolves its{h264, hevc}envelope without a host-side daemon, and compose installs whose host_agent died self-heal too. Redis (the host_agent value) remains authoritative when present.Both fleets exist in balena cloud (0 devices so far); the first master
docker-build.yamlrun after merge produces the<short-hash>-{pi3-64,arm64}GHCR images the pipeline depends on. The branch is current with master (no conflicts).Interplay with #3001 (PulseAudio for Qt 6 viewers): the Pi 3B+ verification below reproduced the
pa_context_connect() failedsymptom that PR fixes. Itsstart_pulseaudiogates on thepulseaudiopackage being present, which it adds inside theis_qt6apt block —pi3-64is inis_qt6here, so the new board inherits the audio fix automatically once both PRs land. The two PRs touch the same three files; whichever merges second carries a trivial textual rebase.Hardware verification (Raspberry Pi 3 Model B+ 1 GB, 64-bit Debian Trixie)
The three
pi3-64images were built locally (arm64 via QEMU) and deployed to a real Pi 3B+:uname -m=aarch64resolvespi3-64; the eglfs no-display guard parks the viewer correctly while no screen is attached.ANTHIAS_LOW_RAM=1engages (single-QWebEngineViewmode).Anthias service startD-Bus handshake and runs stably (this is the exact point where the 32-bit Qt 5 build hits its intermittent WebEngine-init heap corruption; seedocs/board-enablement.md).h264_v4l2m2m(bcm2835-codec,/dev/video10) decodes 720p at ~4× realtime."Video codec 'hevc' is not hardware-decoded on this device. Supported: h264."plus the libx264 re-encode recipe.Checklist
🤖 Generated with Claude Code