---
Hey everyone! Long-time lurker, first post here.
I picked up one of those cheap RK3229 TV boxes and decided to see how far I could push it on a mainline
kernel — no Android, no BSP, no blobs. What started as curiosity about whether rkvdec actually worked on
kernel 6.6 turned into a full rabbit hole of GStreamer pipelines, PHY register dumps, and DRM memory
bandwidth math.
The whole debugging and documentation process was done collaboratively with Claude (Anthropic's AI
assistant), which made it a lot easier to dig into kernel driver internals and iterate on the pipeline
without spending weeks at it. All the results were validated on real hardware.
Sharing here in case it saves someone else the same rabbit hole.
---
[GUIDE] Hardware H.264 decode at 720p — mainline kernel 6.6, GStreamer, no blobs
After spending some time on my RK3229 TV box running Armbian 24.2.5 Bookworm (kernel
6.6.22-current-rockchip), I got hardware H.264 decode working at 720p real-time using only mainline kernel
drivers and open-source GStreamer plugins. Posting here in case it helps others.
---
What works
- H.264 720p@30fps fully hardware decoded via rkvdec (the mainline V4L2 stateless decoder)
- Direct HDMI output via kmssink (DRM/KMS — no X11, no Wayland needed)
- Audio output via ALSA (HDMI or analog)
- YouTube streaming with audio+video in sync using a small proxy server
What doesn't work and why
- 1080p: The decoder itself handles it, but writing ~90 MB/s of NV12 frames to uncached DRM memory
saturates the Cortex-A7 memory bus. Not a software problem — there's no fix without DMA-BUF zero-copy
between rkvdec and the DRM subsystem.
- YouTube in a browser: Browsers do their own software decode — no VA-API bridge exists for rkvdec on
mainline. Even with a desktop environment installed, frame rate will be unusable.
- HEVC / AV1: Not supported by rkvdec on RK3228/RK3229.
---
The GStreamer pipeline
# Local H.264 file — video only
gst-launch-1.0 filesrc location=video.mp4 ! qtdemux ! h264parse \
! v4l2slh264dec ! videoconvert ! kmssink driver-name=rockchip sync=true
# YouTube streaming with audio (requires proxy — see repo)
gst-launch-1.0 -e \
souphttpsrc location="http://PROXY_IP:8091/play?v=VIDEO_ID&q=720&fmt=ts" automatic-redirect=true ! \
tsdemux name=demux \
demux. ! queue ! h264parse ! v4l2slh264dec ! videoconvert ! kmssink driver-name=rockchip sync=true \
demux. ! queue ! aacparse ! avdec_aac ! audioconvert ! audioresample \
! "audio/x-raw,rate=44100,channels=2" ! alsasink device=hw:2
Key points:
- v4l2slh264dec is the stateless GStreamer element — do not use h264_v4l2m2m (that's for stateful decoders
like RPi)
- kmssink driver-name=rockchip uses /dev/dri/card0 (Rockchip DRM display), not the Lima GPU
- For YouTube, MPEG-TS (fmt=ts) is required — fragmented MP4 with empty_moov breaks GStreamer cap
negotiation
---
Why this is different from Jock's media framework
Jock's framework uses kernel 4.4 + RKMPP proprietary blobs. This uses kernel 6.6 mainline + rkvdec upstream
driver + open-source GStreamer. No blobs, works with current Armbian, survives kernel upgrades.
---
Requirements
- Armbian 24.x with kernel 6.6-current-rockchip (kernel 5.15 / Bullseye not tested — V4L2 stateless API
wasn't stable until 5.18)
- GStreamer 1.22 from Debian Bookworm
sudo apt install -y gstreamer1.0-tools gstreamer1.0-plugins-base \
gstreamer1.0-plugins-good gstreamer1.0-plugins-bad \
gstreamer1.0-libav gstreamer1.0-alsa
---
Repo with scripts and full setup guide
https://github.com/Reinoldo-Ozy/rk322x-mediaplayer
Includes the yt-play playback script and the proxy server (yt_proxy.py) with systemd unit. The README
covers the full setup, performance numbers, and a detailed limitations section.
Tested on a generic MXQ Pro-style box with RK3229, 2 GB RAM, Armbian 24.2.5 Bookworm, kernel
6.6.22-current-rockchip, DTB rk322x-box.dtb.