[Guide] Dragon Q6A: Netflix DRM (Widevine), real HW video decode (Venus/V4L2), and Jellyfin client setup

Dragon Q6A (12GB) as a home streaming box: Netflix DRM, real hardware video decode, and a Jellyfin client — full write-up

Sharing this in case it saves someone else the same week of trial and error. Board: Radxa Dragon Q6A, 12GB RAM, running Radxa OS (Ubuntu 24.04-based, aarch64, kernel 6.18.x-qcom). Goal: use it as a daily-driver media/streaming box — Netflix/Prime/Disney+ in-browser, and a local Jellyfin client for a home library served from a separate Raspberry Pi 4 + OpenMediaVault box.

Three separate problems, three separate fixes. Posting the whole path, including the dead ends, because the dead ends are the useful part.


Part 1 — Netflix/Widevine DRM in the browser

Short version: it works, but not the way it works on Raspberry Pi OS, and Chromium is a dead end on this platform if it comes from the Ubuntu apt/snap wrapper.

Why Chromium doesn’t work

apt install chromium on Ubuntu 24.04 installs a snap wrapper, not a real Chromium binary (chromium --version reports ... snap). Snap’s sandboxing blocks the browser from reading a manually-installed Widevine CDM sitting outside its confined filesystem view, no matter what --widevine-cdm-path flags you pass. chrome://components will sit at 0.0.0.0 forever and demo.castlabs.com throws Failed to get MediaKeySystemAccess regardless of what you do.

Don’t waste time on Chromium here unless someone finds a non-snap .deb for this platform.

What actually works: Firefox + manual GMP install

  1. Install real Firefox from Mozilla’s own apt repo (not the Canonical/firefox-esr package that a mozillateam PPA can silently pull in and set as default — check dpkg -l | grep firefox, you may end up with both installed and the wrong one launching by default):

bash

curl -fsSL https://packages.mozilla.org/apt/repo-signing-key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/packages.mozilla.org.gpg
echo "deb [signed-by=/usr/share/keyrings/packages.mozilla.org.gpg] https://packages.mozilla.org/apt mozilla main" | sudo tee /etc/apt/sources.list.d/mozilla.list
printf 'Package: *\nPin: origin packages.mozilla.org\nPin-Priority: 1000\n' | sudo tee /etc/apt/preferences.d/mozilla
sudo apt update && sudo apt install firefox -y
  1. Get an aarch64 Widevine CDM. The AsahiLinux widevine-installer script works fine here even though it’s aimed at Apple Silicon — the CDM itself only cares about CPU architecture + glibc, not the SoC:

bash

git clone https://github.com/AsahiLinux/widevine-installer.git
cd widevine-installer && sudo bash widevine

This drops files under /var/lib/widevine/, not inside any browser profile — which is exactly why it silently does nothing by default.

  1. Firefox’s own auto-download of Widevine is unreliable on Linux aarch64 (same reports from RPi5 users — it gets stuck on “will be installed shortly” forever). Skip it and install manually into the GMP folder instead:

bash

PROFILE=~/.config/mozilla/firefox/<your-profile>.default-release
mkdir -p "$PROFILE/gmp-widevinecdm/<version-from-manifest.json>"
cp /var/lib/widevine/WidevineCdm/_platform_specific/linux_arm64/libwidevinecdm.so "$PROFILE/gmp-widevinecdm/<version>/"
cp /var/lib/widevine/WidevineCdm/manifest.json "$PROFILE/gmp-widevinecdm/<version>/"
chmod a-w "$PROFILE/gmp-widevinecdm/<version>"

Also check about:configmedia.eme.enabled — mine was false out of the box, which silently hides the entire DRM settings section in the GUI (confusing, since there’s nothing to click to fix it if you don’t know the pref exists).

Restart Firefox, check about:addons → Plugins — Widevine should show up there. Verify at https://demo.castlabs.com/ before touching a real streaming site.

Netflix specifically also needs a fake user-agent

Even with a fully working CDM, Netflix hard-blocks playback (Failed to get MediaKeySystemAccess from their player, even though the browser-level EME check passes) unless the UA string claims to be ChromeOS. Confirmed this is a known thing, not specific to this board.

Don’t set general.useragent.override globally in about:config. I did this first and it “worked” for Netflix, but it broke sign-in on Google and Claude.ai entirely — both flagged the browser as “not secure” and refused login. That’s Google’s anti-spoofing detection: a UA string claiming ChromeOS/Chrome combined with a JS engine/TLS fingerprint that doesn’t match real Chrome gets flagged, and the override applies to every site since it’s a global pref, not scoped to Netflix.

Fix: delete the global override, and instead install the “User-Agent Switcher and Manager” extension (addons.mozilla.org) with a domain whitelist:

  1. about:config → find general.useragent.override → delete it (trash-can icon) if you’d set it globally.

  2. Install the extension, open its popup (toolbar icon).

  3. In the userAgent field, paste:

   Mozilla/5.0 (X11; CrOS aarch64 15236.80.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36
  1. Click Options (opens a fuller settings page) → select White-List Mode.

  2. In the White-List textbox, list only the streaming domains:

   netflix.com, primevideo.com, disneyplus.com
  1. Back in the popup, click Apply (all tabs).

Result: only those three domains get the ChromeOS UA (keeping DRM/playback working), everything else — Google login, Claude, general browsing — sees Firefox’s real UA and behaves normally again.

Desktop launchers

Since the UA spoofing is now handled per-domain by the extension rather than a launch flag, the .desktop files can be plain:

bash

mkdir -p ~/.local/share/applications
cat > ~/.local/share/applications/netflix.desktop << 'EOF'
[Desktop Entry]
Version=1.0
Type=Application
Name=Netflix
Exec=firefox --new-window "https://www.netflix.com"
Icon=netflix
Terminal=false
Categories=AudioVideo;Network;
EOF
chmod +x ~/.local/share/applications/netflix.desktop

(repeat for primevideo.com / disneyplus.com). GNOME picks these up automatically and even auto-groups them into a folder in the app grid if you launch each once. No UA flag needed in the launcher at all — the extension’s domain rule takes care of it.

The catch: capped at SD quality

This CDM is sideloaded from a ChromeOS image, not OEM-provisioned for this device, so it only ever gets Widevine L3 (software-only decrypt), never L1 (hardware-backed). Netflix/most studios cap L3 sessions at SD (~480p). This isn’t fixable from userspace — it’s a policy decision on the content side. Fine for a dev-board news feed, not fine if you wanted this to be your 4K TV box.


Part 2 — Real hardware video decode (this is the part I think is actually useful to the forum)

This board has Qualcomm’s Venus video codec block, exposed by the kernel via V4L2 (/dev/video0, /dev/video1, driver name qcom-venus). That part just works out of the box — confirmed via:

bash

sudo apt install v4l-utils
v4l2-ctl --list-devices
# Qualcomm Venus video encoder (platform:qcom-venus): /dev/video0, /dev/video1

VAAPI does not work on this platform for video decode. vainfo fails to open msm_drv_video.so (va_openDriver() returns -1). This matters because most generic Linux desktop software (Kodi’s stock Ubuntu package included) assumes VAAPI is the way to get hardware accel on Linux, and will silently fall back to (or crash trying) software decode if VAAPI isn’t there.

The trap: raw ffmpeg CLI hangs forever

If you naively test with:

bash

ffmpeg -vcodec h264_v4l2m2m -i test.mp4 -f null -

…it correctly identifies the qcom-venus driver, negotiates the format, and then hangs indefinitely on VIDIOC_G_FMT, in an uninterruptible-ish way that timeout/SIGTERM won’t kill cleanly (needed SIGKILL, and even that took a while). dmesg logs nothing during the hang — no timeout, no error, the kernel driver just never gets a response back from firmware for this specific call pattern. If you only test this way you’ll conclude Venus is broken. It isn’t.

What actually works

Radxa’s own docs for this board specify --hwdec=v4l2m2m-copy for mpv, not the raw CLI invocation above:

bash

mpv --hwdec=v4l2m2m-copy test.mp4
# Using hardware decoding (v4l2m2m-copy).

Clean playback, confirmed hardware decode, no hang. Whatever queue/buffer setup mpv (and per Radxa’s docs, Chromium/Firefox too) does automatically is apparently required and isn’t something the bare ffmpeg CLI negotiates the same way.

Kodi

Stock kodi from Ubuntu’s apt repo has no easy way to force v4l2m2m-copy from its GUI (it’s built around VAAPI/VDPAU toggles). With HW accel on, playback breaks; with it off, you get CPU-only software decode. If someone knows a Kodi build/setting that exposes V4L2 M2M properly on this platform, would love to hear it — for now I gave up on Kodi and use mpv/mpv-based clients directly.

Firefox’s own HW decode is flaky

about:support → Graphics reports HARDWARE_VIDEO_DECODING: available, H264_HW_DECODE/HEVC_HW_DECODE/VP9_HW_DECODE all “available” — but the same page’s failure log shows repeated VideoBridgeParent ... AbnormalShutdown and Couldn't sanitize GL_RENDERER "FD643", matching actual segfaults (sig=11) I caught in dmesg from Firefox’s MediaPDecoder process. It sometimes works, sometimes crashes the decoder process mid-playback. Wouldn’t rely on it for anything long-running yet.


Part 3 — Home media stack: Jellyfin client, server elsewhere

Setup: Jellyfin server on a separate Raspberry Pi 4 (4GB) + OpenMediaVault, via the OMV Compose plugin (docker-compose). Dragon Q6A is Jellyfin client only.

Worth noting for anyone doing the same split: Jellyfin has no official hardware transcode support for Qualcomm at all (their supported list: Intel/AMD/NVIDIA/Apple Silicon/Rockchip RKMPP, and a V4L2 path that’s Raspberry-Pi-specific and explicitly being deprecated by Jellyfin upstream due to poor FFmpeg integration). So any transcode need falls back to pure software on the Pi4’s Cortex-A72 — weak for anything beyond 1080p. The saving grace: if the client can Direct Play the source (no transcode), server-side CPU is irrelevant — it’s just serving bytes. All the actual decode work happens on the Dragon Q6A.

Client: Jellyfin Desktop via Flatpak (mpv-based)

The official client (org.jellyfin.JellyfinDesktop on Flathub — heads up, this is the current app ID; the old com.github.iwalton3.jellyfin-media-player ID from older guides is stale and errors with “not installed” even after flatpak install succeeds under the new name):

bash

flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak install flathub org.jellyfin.JellyfinDesktop -y
flatpak override --user --device=all org.jellyfin.JellyfinDesktop

It failed to open a video window at all on first run (Failed to init component: display, vo/libmpv: No render context set) — Qt/Wayland issue inside the Flatpak sandbox on this GNOME/Wayland desktop. Fix:

bash

flatpak run --env=QT_QPA_PLATFORM=xcb org.jellyfin.JellyfinDesktop

Forces Xwayland instead of native Wayland for the Qt UI. After that: HEVC Main10 + HDR10 + EAC3 5.1 source file played back as “Direct Play”, player reported as “MPV Video Player” — zero transcoding, server untouched, smooth playback on the board. Made this permanent with a .desktop launcher baking in the env var so it’s a normal app-menu entry, not something you re-type in a terminal every time.

Ignore in the logs: Cannot load libcuda.so.1 (it’s just probing for an NVIDIA GPU that obviously isn’t there), LIRC Socket Error (IR remote support, irrelevant), Vulkan hwaccel initialisation returned error (Adreno doesn’t support the specific VK_KHR_video_decode_queue extension mpv tried first — it falls through to V4L2M2M fine after that).


TL;DR for anyone landing here from search

  • Chromium = dead end (snap sandboxing). Use real Firefox from Mozilla’s own apt repo.

  • Widevine CDM must be manually placed inside the Firefox profile’s gmp-widevinecdm/ folder — installing it system-wide via the Asahi script alone does nothing for Firefox by itself.

  • Netflix needs a fake ChromeOS UA on top of a working CDM. Setting general.useragent.override globally breaks Google/Claude.ai login (“browser not secure”) — scope it per-domain instead with an extension (White-List Mode, netflix.com/primevideo.com/disneyplus.com only).

  • Sideloaded Widevine = L3 only = SD-capped playback, permanently. Not a config problem.

  • Venus decode (qcom-venus via V4L2) genuinely works — but only through tools that set it up correctly (mpv --hwdec=v4l2m2m-copy, apparently also Chromium/Firefox internally). Raw ffmpeg -vcodec h264_v4l2m2m CLI hangs with zero kernel-side error logged — don’t use that as your test.

  • VAAPI is a dead end on this SoC for video decode.

  • Kodi’s stock Ubuntu package doesn’t expose V4L2 M2M cleanly — mpv-based clients (or Jellyfin Desktop, which wraps mpv) are the path of least resistance right now.

  • Jellyfin Desktop Flatpak needs QT_QPA_PLATFORM=xcb to even open a window on GNOME/Wayland here.

Happy to answer questions or dig up exact package versions if anyone’s trying to replicate this.