STM32 з нуля без HAL: GStreamer якого немає: як насправді стрімити з Luckfox. Частина 8

Серія «STM32 з нуля без HAL» • Місяць 3 • Тижні 3-4

Про що ця стаття

Привіт! Продовжую серію про STM32 без HAL і embedded Linux. В минулих статтях ми розібрали Buildroot, DTS, підключили STM32 до Luckfox через UART і дали Python трохи порулити STM32. Настав час додати до системи камеру.

Але тут чекає сюрприз. На основі пошуку в гугл можна зробити висновок, кожен хто хоче стрімити відео з Linux шукає GStreamer, але саме тут з Luckfox западня.

В цій статті розкажу:

  • Що замість GStreamer використовує Rockchip
  • Як підключити камеру MIS5001 і пройти від dmesg до живого стріму
  • Як запустити RTSP через rkipc — IP camera daemon від Rockchip
  • Зменшити затримку стріму з 10 секунд до 1
  • Про перший досвід — тоді прошивка не знала про камеру

Частина 1. Очікування vs реальність

Що ми очікували

В статті Це не Raspberry Pi. І саме тому це цікаво. Luckfox Pico Pro: від ATmega8 до живого відеостріму ми вже запускали RTSP стрім. Але тоді прошивка з коробки не знала про камеру MIS5001 — довелося перепрошивати. Але в цьому проекті я одразу прошив оновлену прошивку і в цій серії ви мали нагоду пройти зі мною увесь цей шлях, тому камера вже доступна, просто підключай фізично і стрімь.

Перше що спадає на думку — GStreamer. Класичний pipeline для IP камери:

gst-launch-1.0 v4l2src ! jpegenc ! tcpserversink port=8080

Перевіряємо:

gst-launch-1.0 --version
# no gstreamer
gst-inspect-1.0 2>/dev/null | wc -l
# 0

GStreamer на Luckfox порожній. Взагалі нічого. Це не баг і не помилка конфігурації. Таке вже мабуть архітектурне рішення Rockchip.

Чому GStreamer відсутній

Rockchip для своїх SoC (RV1106, RV1103, RK3588 та інших) використовує власний медіа стек — Rockchip MPP (Media Process Platform). Це низькорівневий API для апаратного кодування і декодування відео через вбудований VPU.

Архітектура виглядає так:

Камера (MIPI CSI) → ISP (Image Signal Processor) → VPU (кодування H.264/H.265/JPEG) → мережа

GStreamer з плагіном gstreamer1-rockchip теоретично можна зібрати через Buildroot — але це окремий квест і поки що не ризикнув це пройти. Офіційний образ Luckfox не включає його. Натомість є:

  • Rockchip MPP — С бібліотека для прямої роботи з VPU
  • rk_mpi_* утиліти — тестові програми для кожного компонента
  • rkipc — повноцінний IP camera daemon від Rockchip
  • sample_demo_vi_venc — зразок pipeline VI→ISP→VENC

Аналогія з STM32: замість GStreamer (стандартний інтерфейс) Rockchip дає свій HAL для медіа. Як я писав hal_uart.c замість використання готової бібліотеки — тут теж треба знати специфічний API.

Частина 2. Камера: підключення і діагностика

Камера MIS5001

MIS5001 — 5MP MIPI CSI камера з сенсором mis5001. Підключається до роз’єму CSI на Luckfox Pico Pro. Офіційно підтримується, але тільки в нових прошивках — в старих (ті плати які я придбав не містили оновлену прошивку) її немає в списку сенсорів.

Підключаємо камеру і дивимося dmesg:

dmesg | grep -iE 'mis5001|sensor|csi' | tail -10

Без камери (стара ситуація):

sc3336 4-0030: Unexpected sensor id(000000), ret(-5)
mis5001 4-0031: Failed to get pwdn-gpios

Після підключення камери:

rockchip-csi2-dphy csi2-dphy0: dphy0 matches m00_b_mis5001 4-0031:bus type 5
rockchip-mipi-csi2 mipi0-csi2: stream ON
rockchip-csi2-dphy0: dphy0, data_rate_mbps 891

’stream ON’ в dmesg — CSI шина активна. Сенсор відповідає. Дані йдуть від камери до ISP. Це ще не означає що відео готове — ISP треба налаштувати, але фізичний рівень працює.

IQ файли — калібрування ISP

ISP (Image Signal Processor) на RV1106 — це апаратний блок який перетворює сирий Bayer патерн з сенсора в RGB зображення. Він робить корекцію кольору, глушить шум, AWB (авто баланс білого), AE (авто експозиція).

Для кожного сенсора потрібен свій файл калібрування — IQ (Image Quality) файл. Без нього ISP не знає характеристики сенсора і зображення буде сірим або взагалі не з’явиться, до речі сірий муар проявляється на початку підключення, а потім відео стабілізується.

Перевіряємо наявність IQ файлів:

ls /etc/iqfiles/
# mis5001_CMK-OT2115-PC1_30IRC-F16.json <- наш файл є!
# sc3336_CMK-OT2119-PC1_30IRC-F16.json
# sc4336_OT01_40IRC_F16.json

Якщо IQ файла для вашого сенсора нема — перепрошивайте новішим образом. Без IQ файла rkipc запуститься але зображення не буде. Це перша причина ’камера є але відео немає’.

Перший тест: rk_mpi_vi_test

Перед запуском повноцінного стріму перевіримо чи взагалі ISP отримує кадри:

# Зупиняємо rkipc якщо запущений
RkLunch-stop.sh
# Тест захоплення кадрів
rk_mpi_vi_test -w 1920 -h 1080 -c 1 -d 0 -m 0 -l 10 -o 1

Перед кожним тестом запускайте RkLunch-stop.sh! Процес rkipc тримає камеру і блокує інші програми. Якщо не зупинити — отримаєте ’Address already in use’ або Segmentation fault.

Успішний вивід містить:

sensor name = m00_b_mis5001 4-0031
sensor raw width : 2592
sensor raw height: 1944
ispStreamOn done
create file(/data/test_0_0_1.bin) succeed

У моєму випадку були такі рядки:

cmpi             19:32:57-231 {getFrameRuntime   :1347} -------------------------------vviBuf->buf_size: 3133440
cmpi             19:32:57-607 {getFrameRuntime   :1364} write fail, ret = 330240, pixSize = 3110400
cmpi             19:32:57-631 {getFrameRuntime   :1364} write fail, ret = 0, pixSize = 3110400

Бо /data замалий. Тож, якщо бачите ’write fail’ — проблема з місцем на /data:

df -h /data
ls -la /data/test_0_0_1.bin

Файл test_0_0_1.bin — це сирий YUV буфер з ISP. Його можна переглянути на ПК через ffmpeg: ffplay -f rawvideo -pixel_format nv12 -video_size 1920×1080 test_0_0_1.bin

Частина 3. rkipc — IP camera daemon

Що таке rkipc

rkipc — це повноцінний IP camera daemon від Rockchip. Він реалізує весь pipeline від сенсора до мережевого стріму:

mis5001 → ISP (rkaiq) → MPP (H.264 encoding) → RTSP server (порт 554)

По суті rkipc — це те що в IP камерах робить прошивка. Rockchip відкрив цей код для розробників Luckfox.

Перевіряємо чи запущений:

ps | grep rkipc
# 877 root rkipc -a /oem/usr/share/iqfiles

Проблема: неправильний конфіг

При першому запуску rkipc шукає конфіг /userdata/rkipc.ini. Якщо його нема — генерує дефолтний, який не підходить для mis5001. Симптом:

RK_MPI_VENC_GetStream timeout a004800e

Це означає що відеоенкодер не отримує кадри від ISP — неправильні параметри в ini файлі.

Знаходимо правильний конфіг для нашої камери:

find /oem /userdata /etc -name '*.ini' 2>/dev/null
# /oem/usr/share/rkipc-mis5001-500w.ini <- наш файл!
# /oem/usr/share/rkipc-300w.ini
# /oem/usr/share/rkipc-400w.ini

/userdata на Luckfox — тільки 2.2MB. Якщо він повний (100%) — cp не спрацює. Перевіряйте: df -h /userdata. Якщо повний — видаліть старий rkipc.ini і копіюйте знову.

Копіюємо правильний конфіг:

kill $(ps | grep rkipc | grep -v grep | awk '{print $1}')
rm /userdata/rkipc.ini # видаляємо якщо є
cp /oem/usr/share/rkipc-mis5001-500w.ini /userdata/rkipc.ini

Запуск і перевірка

Запускаємо rkipc з правильним конфігом:

RkLunch-stop.sh 2>/dev/null; sleep 1
rkipc -c /userdata/rkipc.ini -a /oem/usr/share/iqfiles/ > /tmp/rkipc.log 2>&1 &
sleep 8
ps | grep rkipc # перевіряємо що живий

Перевіряємо лог:

cat /tmp/rkipc.log | grep -iE 'rtsp|port|listen|venc|timeout' | head -20

Успішний вивід:

sensor name = m00_b_mis5001 4-0031
ispStreamOn done
[INFO] rtsp server demo starting on port 554
[DEBUG] add session path: /live/0
[DEBUG] add session path: /live/1

Якщо бачите ’rtsp server starting on port 554′ і немає ’VENC_GetStream timeout’ — все працює!

Перевірка портів через /proc/net/tcp: 0×022A = 554 в hex. Якщо в списку є рядок з ’00000000:022A’ — RTSP слухає на всіх інтерфейсах. На Luckfox команда ss відсутня, netstat теж показує не все — /proc/net/tcp надійніший.

Частина 4. RTSP стрім: підключення і затримка

VLC не працює — це нормально

Перша спроба підключитися через VLC: rtsp://192.168.1.125:554/live/0

VLC видає помилку з’єднання. Це відома проблема — VLC 3.x не завжди сумісний з RTSP сервером від Rockchip. Не витрачайте час на налаштування VLC.

# Використовуйте ffplay (пакет ffmpeg):
ffplay 

rtsp://192.168.1.125/live/0

# Або mpv:
mpv 

rtsp://192.168.1.125/live/0

Проблема затримки

Перший запуск ffplay дає ~10 секунд затримки. Це буферизація — ffplay за замовчуванням накопичує великий буфер для стабільного відтворення.

Для низької затримки (~ 1 секунда):

ffplay -fflags nobuffer -flags low_delay -framedrop 

rtsp://192.168.1.125/live/0

Розшифровка параметрів:

  • -fflags nobuffer — не буферизувати вхідний потік
  • -flags low_delay — режим мінімальної затримки для декодера
  • -framedrop — дозволяє пропускати кадри якщо не встигає

Затримка 1-2 секунди — це нормально для RTSP через TCP/IP. Для нульової затримки потрібен інший протокол (наприклад WebRTC) або UDP транспорт: ffplay -rtsp_transport udp rtsp://192.168.1.125/live/0

Два потоки: /live/0 і /live/1

rkipc піднімає два RTSP потоки:

  • /live/0 — основний потік, висока роздільна здатність (1920×1080 або вища)
  • /live/1 — субпотік, менша роздільна здатність для мобільних клієнтів

Параметри обох потоків задаються в rkipc.ini. У нас rkipc-mis5001-500w.ini (500w = 5 мегапікселів):

cat /userdata/rkipc.ini | grep -E ’width|height|bitrate’ | head —10

Частина 5. Архітектура: що під капотом

Повний pipeline

Тепер коли стрім працює — розберемо що відбувається всередині:

mis5001 (MIPI CSI) → rkcif (CIF driver) → /dev/video0

rkaiq (ISP tuning, AWB, AE) — читає mis5001_CMK-OT2115-PC1_30IRC-F16.json

|rkisp (ISP hardware) → /dev/video11 (mainpath) /dev/video12 (selfpath)

rkmpp (MPP encoder) → H.264 bitstream

rtsp_demo → TCP port 554 → /live/0, /live/1

Кожен блок — окремий компонент:

  • rkcif — CIF (Camera Interface) driver, забирає дані з MIPI шини
  • rkaiq — Rockchip AIQ (AI quality), алгоритми обробки зображення. Читає JSON конфіг
  • rkisp — ISP hardware, апаратна обробка RAW → YUV
  • rkmpp — Media Process Platform, апаратне кодування через VPU
  • rtsp_demo — RTSP сервер, вбудований в rkipc

Порівняння з STM32: pipeline камери нагадує наш bare-metal підхід. Замість того щоб дати Universal HAL (як намагається бути GStreamer), Rockchip дає прямий доступ до апаратних блоків. Більше контролю, менше абстракцій.

Де сидить відео: /dev/video*

На платі 20+ відео пристроїв. Не лякайтесь:

ls /dev/video* /dev/media*
# /dev/video0-video20, /dev/media0, /dev/media1
  • /dev/video0-3 — сирий вивід з CIF (RAW Bayer дані від сенсора)
  • /dev/video11 — ISP mainpath (основний вивід після обробки, YUV)
  • /dev/video12 — ISP selfpath (другий вивід, менша роздільна здатність)
  • /dev/video13 — ISP bypasspath
  • /dev/video17-18 — ISP rawrd (зворотній шлях для RAW capture)

rkipc читає з /dev/video12 (selfpath) через rkaiq і MPP, кодує в H.264, відправляє в RTSP.

Автозапуск: RkLunch.sh

При старті системи rkipc запускається автоматично через RkLunch.sh. Цей скрипт не в стандартному /etc/init.d/ — він запускається з іншого місця (специфіка образу Luckfox).

Для зупинки перед тестами:

RkLunch-stop.sh

Ніколи не запускайте два процеси які використовують камеру одночасно. rk_mpi_vi_test, sample_demo_vi_venc, rkipc — всі вони монопольно захоплюють ISP. Завжди зупиняйте попередній перед запуском нового.

Частина 6. Порівняння: тоді і зараз

Перший досвід (стаття про Luckfox, березень 2026)

В першій статті про Luckfox ми вже розглядали як запускати RTSP стрім. Але тоді шлях був трохи тернистий інший:

  • Прошивка з коробки не знала про MIS5001 — sensor id = 0×000000
  • Довелося перепрошивати через upgrade_tool і Maskrom режим
  • rkipc запустився з дефолтним конфігом і стрім якось заробив
  • VLC не працював вже тоді — рятував ffplay
  • Наступного дня стрім ’зник’ — rkipc потребує ~15 сек для підняття RTSP

Цікавий патерн: тоді все ’просто запрацювало’ після перепрошивки. Тепер ми знаємо чому: правильна прошивка включає rkipc-mis5001-500w.ini в /userdata при першому запуску. Але якщо /userdata переповнений — ini не скопіюється і буде проблема.

Зараз ми розуміємо кожен крок:

  • dmesg показує стан сенсора — знаємо що шукати
  • IQ файли — розуміємо навіщо вони і де шукати
  • rkipc.ini — знаємо який файл правильний для якого сенсора
  • /proc/net/tcp замість netstat — знаємо як перевірити порти на uclibc
  • MTD розділи — розуміємо що /userdata це flash 2.2MB а не tmpfs
  • -fflags nobuffer — знаємо як зменшити затримку

Це і є різниця між ’запрацювало’ і ’розумію чому запрацювало’. За місяць роботи з Luckfox накопичився контекст який перетворює магію в інженерію.

Алгоритм діагностики: коли стрім не йде

Якщо rtsp://192.168.1.125/live/0 не підключається — перевіряйте по черзі:

  1. Камера детектується? dmesg | grep -iE ’mis5001|csi’ — шукайте ’stream ON’
  2. IQ файл є? ls /etc/iqfiles/ — має бути файл для вашого сенсора
  3. rkipc запущений? ps | grep rkipc
  4. Порт 554 відкритий? cat /proc/net/tcp | grep ’022A’ — шукайте рядок з 0A (listening)
  5. Лог чистий? cat /tmp/rkipc.log | grep timeout — не повинно бути VENC_GetStream timeout
  6. Правильний ini? Порівняйте /userdata/rkipc.ini з /oem/usr/share/rkipc-mis5001-500w.ini
  7. /userdata не повний? df -h /userdata — якщо 100% — це проблема

VLC помилка з’єднання — це не діагностика. VLC не завжди сумісний з Rockchip RTSP. Краще перевіряйте через ffplay rtsp://IP/live/0 перш ніж робити висновки. Хоча може я щось упустив і все нормально працює

Підсумок

За ці два тижні третього місяця ми:

  • З’ясували що GStreamer на Luckfox відсутній — і це не проблема
  • Підключили камеру MIS5001, навчились читати dmesg для діагностики
  • Розібрали IQ файли і їх роль в роботі ISP
  • Запустили rkipc з правильним конфігом і отримали RTSP стрім
  • Зменшили затримку з 10 секунд до 1 через ffplay параметри
  • Зрозуміли архітектуру pipeline: CSI → ISP → MPP → RTSP

Далі — NPU і face detection, як на мене цікавий досвід, тому підписуйтесь чи додавайт в закладки, щоб не пропустити. Наступний крок: навчити систему розпізнавати обличчя і через UART давати команду STM32 вмикати реле. Повний ланцюжок від камери до фізичної дії.

А якщо хочете побачити звідки ростуть ноги — ось попередні статті серії:

Довідники

Репозиторій: github.com/pipicosim800-maker/stm32F103

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті

👍ПодобаєтьсяСподобалось7
До обраногоВ обраному3
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Залишилось плату ініціалізації ініціалізувати (STM32 з нуля без HAL. Ініціалізація крила/октопуса/квардуполоса на кухні. Частина 9) і готовий мілфдефтеківець ( STM32 з нуля без HAL. Як пройти поліграфа з першого разу: Частина 10.)

Прийнято. Серія задумувалась, як робота з ARM загалом не тільки з stm, а npu знайшов і трохи занесло в сторону 😀 та невже то не цікаво

Підписатись на коментарі