Отчёт: анализ видео на RK3562 с использованием YOLO на NPU
1. Постановка задачи
Разработать систему анализа видеофайлов стандартных форматов (mp4, avi, mov) на плате RK3562 с использованием нейросетевой детекции объектов на NPU. Результат обработки должен быть playable-видео с нарисованными рамками вокруг найденных объектов.
Требования:
вход — любой стандартный видеоформат;
декодирование через аппаратные средства платы;
детекция объектов через нейросеть на NPU;
отрисовка рамок и подписей классов на кадрах;
кодирование результата обратно в видео;
запуск одной командой без ручного указания параметров.
2. Аппаратная и программная база
Плата: RK3562 (NPU RKNPU2, 1 TOPS).
Драйвер NPU: версия 0.9.8.
Runtime RKNN: librknnrt.so 2.3.0.
Операционная система: Buildroot 2024.02.
Аппаратные кодеки: MPP (Media Process Platform) — поддерживает H.264/H.265 декодирование и H.264 кодирование.
Аппаратный 2D-акселератор: RGA (Raster Graphic Acceleration).
GStreamer: 1.22.9 с плагинами Rockchip.
Среда разработки: виртуальная машина Lubuntu с Buildroot-тулчейном aarch64-linux-gcc 12.3.0.
3. Выбранные модели
Для сравнения взяты две модели детекции объектов, обе сконвертированы в формат RKNN с квантизацией INT8:
YOLOv5n:
источник: rknn_model_zoo/examples/yolov5
вход: 640 на 640, RGB
выход: 3 тензора (80 на 80, 40 на 40, 20 на 20)
размер .rknn: 2.7 МБ
YOLOv8n:
источник: rknn_model_zoo/examples/yolov8
вход: 640 на 640, RGB
выход: 1 тензор
размер .rknn: 4.1 МБ
Обе модели обучены на датасете COCO (80 классов: человек, машина, мяч, бутылка и т.д.).
4. Схема обработки видео
Пайплайн состоит из пяти этапов:
Этап 1 — декодирование.
Входной mp4/avi/mov читается через GStreamer с аппаратным декодером mppvideodec. Видеопоток конвертируется в один из двух форматов:
RGB888 (для разрешений до 640x360)
NV12 (для разрешений больше 640x360)
Этап 2 — инференс.
Каждый кадр подаётся в YOLO-модель на NPU. Модель возвращает список найденных объектов с координатами рамок и вероятностями.
Этап 3 — отрисовка.
Рамки и подписи классов рисуются прямо на кадре через функции draw_rectangle и draw_text из состава rknn_model_zoo. Функции умеют работать и с RGB888, и с NV12 без промежуточной конвертации.
Этап 4 — кодирование.
Результат подаётся в аппаратный энкодер mpph264enc, на выходе — H.264-поток.
Этап 5 — упаковка.
H.264-поток упаковывается в контейнер MPEG-TS через mpegtsmux. Формат MPEG-TS выбран потому, что mp4mux в имеющейся сборке GStreamer не может работать с потоком от mpph264enc из-за отсутствия PTS (временных меток).
5. Ключевая техническая проблема: RGB против NV12
В процессе работы выявлена фундаментальная особенность RK3562: аппаратный 2D-акселератор RGA не может обработать RGB-буферы большого размера, выделенные через стандартный malloc.
Симптом: при разрешении 768x432 в RGB-режиме RGA падал с ошибкой IOMMU page fault. В логе ядра было видно:
rk_iommu ff440f00.iommu: iova = 0x00000000ffe69000: page fault
Причина: RGA работает через IOMMU и требует, чтобы буферы были либо ниже 4 ГБ, либо выделены через DMA-heap. При malloc в 64-битной системе буфер может оказаться в «верхней» части памяти, недоступной для RGA.
Размеры буферов для 768x432:
RGB888: 768 x 432 x 3 = 995 328 байт — RGA падает
NV12: 768 x 432 x 1.5 = 497 664 байт — RGA работает
Для 640x360:
RGB888: 640 x 360 x 3 = 691 200 байт — RGA работает
NV12: 640 x 360 x 1.5 = 345 600 байт — тоже работает
Практическое правило: до 640x360 можно использовать RGB, для больших разрешений нужно использовать NV12.
6. Вторая техническая проблема: stride при декодировании
Аппаратный декодер MPP выравнивает высоту кадра до кратной 8 или 16 пикселям. При декодировании 640x360 реальный размер кадра оказался 353 280 байт вместо ожидаемых 345 600. Разница 7680 байт — это выравнивание.
Из-за этого при попытке читать NV12-поток с фиксированным шагом 345 600 байт каждый следующий кадр начинался со смещением, и картинка «плыла» сверху вниз с искажением цветности.
Решение: пропустить вывод декодера через videoscale и videoconvert с явным указанием формата NV12 и разрешения. Это гарантирует, что на выходе будет чистый поток без паддинга.
Пример команды:
gst-launch-1.0 -q filesrc location=input.mp4 ! qtdemux ! h264parse ! mppvideodec ! videoscale ! videoconvert ! video/x-raw,format=NV12,width=768,height=432 ! filesink location=output.nv12
Проверка: размер файла должен делиться нацело на width x height x 1.5. Например, для 768x432: 306 063 360 / 497 664 = 615 кадров ровно.
7. Третья техническая проблема: упаковка готового H.264-потока в MP4
Тестовые mp4-файлы на раннем этапе создавались без проблем через конвейер videotestsrc |