Video Decoding
This chapter covers hardware video decoding of H.264 / H.265 / VP9 / AV1 on the RK182X using the MPP framework.
Overall block diagram
Bitstream (file / network stream)
↓
MPP Decoder (VPU hardware decoding)
↓
YUV frames (NV12 / NV16)
↓
RGA format conversion → NPU inference / display / encoding
(zero-copy via DMA-BUF throughout)The RK182X VPU supports hardware decoding of H.264 / H.265 / VP9 / AV1. The upper limits depend on the VPU of the attached Host SoC; with the RK3588 as reference, hardware decoding goes up to 4K@60fps (H.265/VP9/AV1) and 8K@30fps (H.264/H.265).
1. Supported Decoding Formats
| Format | Profile | Max resolution | Max frame rate |
|---|---|---|---|
| H.265 / HEVC | Main / Main10 | 4096×2304 | 60 fps |
| H.264 / AVC | High Profile | 4096×2304 | 60 fps |
| VP9 | Profile 0 / 2 | 4096×2304 | 60 fps |
| AV1 | Main Profile | 4096×2304 | 60 fps |
| MJPEG | Baseline | 8192×8192 | 30 fps |
2. Environment Verification
MPP header directory:
ls /usr/include/rockchip/ | head -15Output:
mpp_buffer.h
mpp_compat.h
mpp_err.h
mpp_frame.h
mpp_log_def.h
mpp_log.h
mpp_meta.h
mpp_packet.h
mpp_rc_api.h
mpp_rc_defs.h
mpp_sys_cfg.h
mpp_sys_cfg_st.h
mpp_task.h
rk_hdr_meta_com.h
rk_mpi_cmd.hMPP decode control commands:
grep -E "MPP_DEC_SET_EXT_BUF_GROUP|MPP_DEC_SET_OUTPUT_FORMAT" /usr/include/rockchip/rk_mpi_cmd.h | head -5Output:
MPP_DEC_SET_EXT_BUF_GROUP, /* IMPORTANT: set external buffer group to mpp decoder */
MPP_DEC_SET_OUTPUT_FORMAT,MPP buffer types:
grep -E "MPP_BUFFER_TYPE_DRM" /usr/include/rockchip/mpp_buffer.h | head -5Output:
* MPP_BUFFER_TYPE_DMA_HEAP > MPP_BUFFER_TYPE_DRM > MPP_BUFFER_TYPE_ION
MPP_BUFFER_TYPE_DRM,
* DRM SECURE buffer : MPP_BUFFER_TYPE_DRM | MPP_BUFFER_FLAGS_SECUREBuffer group function definition:
grep "mpp_buffer_group_get_internal" /usr/include/rockchip/mpp_buffer.h | head -5Output:
#define mpp_buffer_group_get_internal(group, type, ...) \MPP library files:
find /usr/lib -name "librockchip_mpp*"Output:
/usr/lib/aarch64-linux-gnu/librockchip_mpp.so
/usr/lib/aarch64-linux-gnu/librockchip_mpp.so.0
/usr/lib/aarch64-linux-gnu/librockchip_mpp.so.1VPU device node:
ls /dev/mpp_serviceOutput:
/dev/mpp_serviceCross-compilation tool:
which aarch64-linux-gnu-gccOutput:
/usr/bin/aarch64-linux-gnu-gcc3. Complete Decoding C Code Example
Seven-step flow: mpp_create → mpp_init(CTX_DEC, coding) → fopen the bitstream → allocate a buffer group → loop (decode_put_packet + decode_get_frame) → process frames (fd) → clean up.
#include <stdio.h>
#include <stdlib.h>
#include <rockchip/mpp_buffer.h>
#include <rockchip/mpp_frame.h>
#include <rockchip/mpp_packet.h>
#include <rockchip/rk_mpi.h>
#include <rockchip/rk_mpi_cmd.h> /* MPP_DEC_SET_OUTPUT_FORMAT etc. */
int main(int argc, char **argv)
{
if (argc < 2) {
printf("Usage: %s <input.h264>\n", argv[0]);
return -1;
}
// Create the MPP decoder + get the MppApi pointer
MppCtx ctx = NULL;
MppApi *mpi = NULL;
MPP_RET ret = mpp_create(&ctx, &mpi);
if (ret != MPP_OK) {
printf("mpp_create failed: %d\n", ret);
return -1;
}
// Initialize as an H.264 decoder
// Note: the decoding type is passed as the third argument (MppCodingType) of mpp_init
MppCodingType type = MPP_VIDEO_CodingAVC;
ret = mpp_init(ctx, MPP_CTX_DEC, type);
if (ret != MPP_OK) {
printf("mpp_init failed: %d\n", ret);
return -1;
}
// Open the input file
FILE *fp = fopen(argv[1], "rb");
if (!fp) { perror("fopen"); return -1; }
// Create an external buffer group so the VPU writes decoded frames directly into it
MppBufferGroup frame_group = NULL;
ret = mpp_buffer_group_get_internal(&frame_group, MPP_BUFFER_TYPE_DRM);
if (ret != MPP_OK) {
printf("mpp_buffer_group_get failed: %d\n", ret);
fclose(fp);
return -1;
}
// Push the external group to the decoder — the zero-copy path
mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, frame_group);
// Decoding loop
unsigned char *pkt_buf = malloc(1024 * 1024);
MppPacket packet = NULL;
MppFrame frame = NULL;
RK_S64 pts = 0;
while (!feof(fp)) {
size_t read_len = fread(pkt_buf, 1, 1024 * 1024, fp);
if (read_len <= 0) break;
mpp_packet_init(&packet, pkt_buf, read_len);
mpp_packet_set_pts(packet, pts++); // PTS is a timestamp, not a byte count
ret = mpi->decode_put_packet(ctx, packet);
if (ret != MPP_OK) { printf("put_packet failed\n"); break; }
for (;;) {
ret = mpi->decode_get_frame(ctx, &frame);
if (ret != MPP_OK || !frame) break;
RK_U32 width = mpp_frame_get_width(frame);
RK_U32 height = mpp_frame_get_height(frame);
MppBuffer buf = mpp_frame_get_buffer(frame);
int fd = mpp_buffer_get_fd(buf); // DMA-BUF fd, can be passed straight to RGA/NPU
printf("Decoded: %dx%d, fd=%d\n", width, height, fd);
// TODO: pass to RGA/NPU for processing
mpp_frame_deinit(&frame);
frame = NULL;
}
mpp_packet_deinit(&packet);
packet = NULL;
}
// Clean up
free(pkt_buf);
fclose(fp);
mpp_buffer_group_put(frame_group);
mpp_destroy(ctx);
printf("Decode complete.\n");
return 0;
}3.1 Key API Points
| API | Description |
|---|---|
<rockchip/rk_mpi.h> | Actual header location (not "rk_mpi.h") |
mpp_init(ctx, MPP_CTX_DEC, MppCodingType) | The decode type is passed as the third argument; there is no MPP_SET_DEC_CODING_TYPE control command |
mpp_buffer_group_get_internal(&g, type) | The 5-argument mpp_buffer_group_get is too complex; the macro is recommended |
mpp_packet_set_pts(pkt, ts) | The second argument is an RK_S64 timestamp (not a byte count) |
MPP_DEC_SET_EXT_BUF_GROUP | Push the external buffer group to the decoder via mpi->control for zero copy |
decode_put_packet + decode_get_frame | Both are MppApi members (mpi->), not top-level functions |
4. Compiling the Decoder
All VPU decoding capability is encapsulated in librockchip_mpp; linking only needs -lrockchip_mpp.
aarch64-linux-gnu-gcc decode_test.c \
-I$RK182X_SDK/mpp/include \
-L/usr/lib/aarch64-linux-gnu \
-lrockchip_mpp \
-o decode_test
adb push decode_test /usr/bin/
adb shell /usr/bin/decode_test /tmp/test.h2645. FAQ
| Symptom | Cause | Resolution |
|---|---|---|
mpp_create failed | Library path / device permission | ls -l /dev/mpp_service |
mpp_init failed | Unsupported coding type | Verify MPP_VIDEO_CodingAVC/HEVC/VP9/AV1 |
| Garbled decoding output | Buffer group not set | Call MPP_DEC_SET_EXT_BUF_GROUP |
MPP_DEC_SET_OUTPUT_FORMAT has no effect | Called before mpp_init | Order: mpp_init → control |
mpp_buffer_group_get_internal macro expansion error | Header files too old | Upgrade librockchip-mpp-dev |
decode_get_frame keeps returning empty | PTS not incrementing | mpp_packet_set_pts(packet, pts++) |
6. Next Steps
- MPP Multimedia Framework — multimedia framework overview
- RGA 2D Acceleration — hardware-accelerated preprocessing
- NPU Overview — combining AI inference with video analytics
