單元 5 · 第一個鏡頭跑起來

argus / HSB 取流

Jetson 標準取流

argus 與 v4l2
argus_camera --mode 0 --duration 1
v4l2-ctl -d /dev/video0 --set-fmt-video=width=1280,height=720,pixelformat=NV12
第一步驗證:argus_camera 出圖 = 感測器→ISP→輸出鏈路通。

HSB / Holoscan 取流

Holoscan 接收感測器(示意)
# Holoscan Operator 設定感測器源(HSB 通道)
# 經乙太網路接收感測器資料進 GPU 管線

⚠️ HSB 取流 API 以 NVIDIA Holoscan 最新文件為準。

5.7 深入:取流的完整驗證

OV9281 取流驗證
# 確認 media 管線
media-ctl -p -d /dev/media0
# 取一幀
v4l2-ctl -d /dev/video0 --stream-mmap=1 --stream-count=1 --stream-to=f.yuv
# 檢查格式
v4l2-ctl -d /dev/video0 --list-formats-ext
通過標準:取到一幀 = 感測器→CSI→video 鏈路通。接著才談調校。

5.8 練習

  1. 跑完整取流流程,確認格式。
  2. 記錄支援的 fourcc 清單。

5.9 深入原理:取流背後的狀態機與 buffer

V4L2 取流不是「一下就開始」,而是一串狀態:idle → initialized(設定 format)→ streaming(buffer 來回)。了解狀態才能看懂錯誤訊息。

S_FMT(設格式)REQBUFS(申請 buffer)QBUF(放入佇列)STREAMONDQ/QB 迴圈
狀態現象錯誤徵兆
streaming 前無幀
STREAMON 失敗取流卡住format 不被支援、driver 沒準備好
buffer 不足偶發掉幀DQ 逾時、EIO
陷阱:argus_camera 會自動完成上面全部狀態;v4l2-ctl 也會。但自己寫 app 時每個狀態都要確認回傳值——最常見的 bug 是忘了 QBUF 就 STREAMON。

5.10 Worked Example:把一幀 YUV 存檔並檢查

取 1 幀 NV12 並驗證大小
v4l2-ctl -d /dev/video0 \
  --set-fmt-video=width=1280,height=800,pixelformat=NV12 \
  --stream-mmap=3 --stream-count=1 --stream-to=frame.nv12
# 驗證檔案大小(NV12 = W×H×1.5 bytes)
ls -l frame.nv12                # 期望 ≈ 1280×800×1.5 = 1,536,000 B
# 檢查 fourcc 是否真的支援
v4l2-ctl -d /dev/video0 --list-formats-ext
為什麼驗證大小:檔案大小不符 = format 設定沒生效(可能 fallback 到別的模式)。大小對了才確定解析度/格式正確,之後分析才有意義。

5.11 疑難排解決策樹:取不到幀

「v4l2-ctl 取流無輸出」
1. media graph 完整且 link 啟用(unit-04)?
   ├─ 否 → 先修 graph
   └─ 是 ─┐
2. format 在支援清單內?
   ├─ 否 → 換 --list-formats-ext 內的值
   └─ 是 ─┐
3. STREAMON 回傳錯誤?
   ├─ 是 → 看 dmesg(感測器/CSI 錯誤)
   └─ 否 ─┐
4. (HSB) Holoscan 端是否也開始收?
   └─ 否 → 確認 host/sensor 兩端格式與通道一致

5.12 常見錯誤與陷阱

陷阱 1:解析度在兩端不一致——sensor mode 與 video format 的解析度不同,會裁切或填補。一律以感測器支援的 mode 為準。
陷阱 2:fourcc 打錯——NV12 不是 NV21YUYV 不是 YU12。寫錯時 driver 多半拒絕或 fallback,要回讀確認。
陷阱 3:HSB 端與 host 端 buffer 設定不匹配——走 HSB 時,感測器端送出的 format 必須與 host 解包預期一致,否則解出的像素錯位(unit-08 詳述)。

5.13 深入:mmap vs DMABUF buffer 的選擇

V4L2 取流 buffer 主要有兩種:mmap(driver 分配、應用映射)與 DMABUF(外部/GPU buffer 傳給 driver)。NVIDIA 平台的 GPU 直連管線偏好 DMABUF,讓感測器資料直接落地 GPU 記憶體。

方式誰分配適合
mmapdriver簡單取流、驗證
DMABUF應用/GPUGPU 管線、零拷貝
陷阱:Argus/Holoscan 底層常自動用 DMABUF。若你自己用 v4l2-ctl 取流時選了不支援的 buffer 方式,會回 ENOTTY 或 EINVAL。先用 --stream-mmap 驗證鏈路,再用 DMABUF 做效能。

5.14 練習

  1. 取一幀 NV12 並用檔案大小驗證格式正確。
  2. 故意用不支援的解析度,觀察 driver 行為與錯誤訊息。
  3. 用 argus_camera 與 v4l2-ctl 各取一次,比較兩者輸出差異。
看完這單元你應該能說出:
  • argus_camera / v4l2-ctl 取流。
  • 「出圖 = 鏈路通」驗證。
  • HSB 走 Holoscan 管線概念。
  • Thor 與 Orin 取流共通與差異。

延伸閱讀

5.15 進階真實情境 Worked Example:多感測器同時取流的 buffer 競爭

場景:Thor T5000 同時接 4 顆 OV9281(各 1280×800 RAW10 @ 120 fps),全部走 CSI。目標:4 路同時取流不掉幀。

4 路取流的 buffer 策略
# 單顆 OV9281:每幀 1280×800×10/8 = 1,280,000 bytes ≈ 1.22 MB
# 4 顆 = 4.88 MB/幀 × 120 fps = 585.6 MB/s
# Thor DDR 頻寬 > 100 GB/s → 資料面不是瓶頸
# 瓶頸在:4 組 V4L2 queue 的 DMA 對齊與 buffer 分配

# 方案:DMABUF + 3-buffer deep queue
v4l2-ctl -d /dev/video0 --stream-mmap=3 --stream-count=-1 # continuous
v4l2-ctl -d /dev/video1 --stream-mmap=3 --stream-count=-1
v4l2-ctl -d /dev/video2 --stream-mmap=3 --stream-count=-1
v4l2-ctl -d /dev/video3 --stream-mmap=3 --stream-count=-1

# 每路 3 buffers × 1.22 MB = 3.66 MB × 4 路 = 14.6 MB
# GPU DMABUF 池共需 ~15 MB

# 驗證:4 路跑 10 分鐘,監控:
cat /sys/kernel/debug/v4l2/video*/queue_status
# 每路 queue 的 queued_count 應穩定在 1-2,不持續增加
# 若某路 queued_count 持續上升 → 該路 buffer 被 GPU 占用太久 → 降該路 fps
設計決策:4 路同時取流的瓶頸不是頻寬而是 buffer 管理。用 DMABUF 避免 CPU 拷貝,用 3-buffer deep queue 保底(一路在 ISP、一路在 GPU、一路在 queue)。監控 queue_status 是多感測器取流的標準除錯手法。

5.16 深入原理擴充:V4L2 的 request API 與 Thor 的 multi-stream pipeline

標準 V4L2 取流是「被動的」:driver 推帧、app 接。Thor 引入了 request API(media request)的增強版:app 可以「預先提交」下一幀的控制參數(曝光、增益),ISP 在該幀被取走時自動套用。這讓多感測器同步曝光成為可能——app 同時對 4 個 video node 提交相同時間戳的 request。

容易忽略的邊界案例:request API 的時間戳精度依賴 kernel 的 clock domain。若 4 顆感測器的 video node 分屬不同的 clock source(例如 CSI lane group 不同),request 的套用時間可能差 1–2 行。對立體視覺等精確同步場景,必須用 hardware frame sync pin(FSIN)而非 request API 的軟體時間戳。

5.17 診斷式疑難排解表

症狀可能原因解決方案
v4l2-ctl 取流後檔案大小為 0stream-count 設定為 0 或 format 未設定就取流先 --set-fmt-video 再 --stream-mmap;確認 stream-count ≥ 1
4 路同時取流中有一路偶發 timeout該路的 DMA buffer 被其他路或 GPU 佔用增加該路 buffer deep queue;確認 DMABUF 池夠大;降低該路 fps
NV12 輸出檔案大小不等於 W×H×1.5format 設定未生效,driver fallback 到其他 format回讀 format(V4L2_QUERYBUF)確認實際 fourcc;用 --list-formats-ext 確認支援
argus_camera 出圖但 v4l2-ctl 取流畫面全黑Argus 與 V4L2 使用不同的 buffer 路徑(DMABUF vs mmap)統一 buffer 分配方式;或用 argus 做取流、v4l2-ctl 只做 format 驗證
HSB 路徑的取流延遲比 CSI 高 5 ms乙太網路封包 + 橋接解包延遲這是正常行為;若延遲不可接受,改用 CSI 或在 HSB 端減少封包大小

5.18 進階挑戰題

  1. 設計一個多感測器取流壓力測試:4 顆 OV9281 @ 120 fps 同時取流 1 小時,每 10 分鐘記錄每路的掉幀數、queue 深度與 GPU 使用率。找出瓶頸在哪一層。
  2. 分析 mmap vs DMABUF 在 4 路取流下的 CPU 使用率差異。用 time 工具量測 user/system 時間,畫出對照表。
  3. 若你要在 Holoscan 管線中同時接收 CSI 與 HSB 兩條路徑的感測器資料,設計一個 buffer pool 管理策略:兩條路徑的 buffer 深度、格式與 GPU 記憶體預算如何規劃?

5.19 專案級端到端 Worked Example:第一張圖專案 — 從取流到可分析的檔案

場景:新開發板到手,目標在 30 分鐘內「取到第一張圖」並確認格式正確,為後續 RAW 分析打基礎。

里程碑規劃
M1 環境確認(2 min)
   ├─ media graph 完整(unit-04)
   └─ 通過:四層 node 全啟用

M2 第一次取流(5 min)
   ├─ v4l2-ctl --stream-mmap=3 --stream-count=1 --stream-to=first.nv12
   └─ 通過:檔案大小 = W×H×1.5

M3 顯示檢查(5 min)
   ├─ ffplay / 轉 PNG 目視
   └─ 通過:畫面非全黑/全綠、無明顯撕裂

M4 格式清單(5 min)
   ├─ v4l2-ctl --list-formats-ext
   └─ 通過:記錄 fourcc 與解析度組合

M5 RAW 取樣(5 min)
   ├─ 以 SRGGB10 取 1 幀
   └─ 通過:大小 = W×H×10/8

M6 收尾(8 min)
   └─ 通過:三份檔案(NV12/RAW/格式清單)進 repo

驗證命令:
  ls -l first.nv12
  # 1280×800 NV12 → 1,536,000 B;SRGGB10 → 1,280,000 B
專案要點:「第一張圖」不是出圖就結束——必須同時拿到 NV12(看畫質)、RAW(分析用)、格式清單(記錄能力)。三份都有才叫「第一張圖專案完成」。

5.20 量測 / 驗證 SOP:取流功能驗證

取流 SOP(Step 1–6)
Step 1 格式查詢
   v4l2-ctl -d /dev/video0 --list-formats-ext
Step 2 設定格式
   v4l2-ctl -d /dev/video0 --set-fmt-video=width=1280,height=800,pixelformat=NV12
Step 3 回讀確認
   v4l2-ctl -d /dev/video0 --get-fmt-video
   # 確認實際套用的格式(可能 fallback)
Step 4 取流
   v4l2-ctl -d /dev/video0 --stream-mmap=3 --stream-count=1 --stream-to=f.nv12
Step 5 檔案驗證
   ls -l f.nv12
   # NV12: W×H×1.5;RAW10: W×H×10/8
Step 6 連續性測試
   v4l2-ctl -d /dev/video0 --stream-mmap=3 --stream-count=300 --stream-to=f2.nv12
   # 300 幀無 timeout

判讀指標:
  檔案大小不符 → format fallback(回 Step 2 改)
  timeout/掉幀 → buffer 深度或頻寬

5.21 平台間對照:取流工具與流程

面向Thor T5000RPi5Orange PiOrin Nano
標準取流v4l2-ctl / argus_cameralibcamera-still / rpicamv4l2-ctlv4l2-ctl / argus_camera
RAW 取樣v4l2-ctl + Holoscanrpicam --rawv4l2-ctlargus raw
連續壓力測試--stream-count--timelapse / burst--stream-count--stream-count
GPU 路徑取流✅ Holoscan(DMABUF)⚠️ Argus 內部
HSB 網路取流✅ 支援
選擇思考:取流的「概念與狀態機」四平台相同(S_FMT→REQBUFS→QBUF→STREAMON→DQ 迴圈)。Thor 的差異是多了 Holoscan/DMABUF 這條 GPU 直連路徑。

5.22 互動式檢核清單

5.18 Register 位元級完整工作流

本單元涉及的關鍵 register,以及「讀→改→寫→驗證」的完整位元級操作序列:

Register位址功能Bit Field 說明
CSI_PHY_CTRL0x0c090000CSI PHY 控制bit[0]=enable, bit[2:1]=data rate mode, bit[3]=lane power down
讀→改→寫→驗證 完整序列(以 CSI_PHY_CTRL 為例)
# Step 1: 讀取目前值
$ devmem2 0x0c090000 w
# 記錄 current_value

# Step 2: 計算新值
$ new_value=$(current_value | 0x0001)

# Step 3: 寫入
$ devmem2 0x0c090000 w $new_value

# Step 4: 驗證讀回值與預期一致
$ devmem2 0x0c090000 w
$ [ "$(devmem2 0x0c090000 w | grep Read)" = "expected" ] && echo "PASS" || echo "FAIL"

5.19 多層疑難排解決策樹

決策樹 1:argus 取流失敗
1. `nvgstcapture` 無輸出?
   ├─ 檢查 sensor 是否 streaming:`v4l2-ctl -d /dev/video0 --stream-mmap --stream-count=1`
   │  ├─ 成功 → argus 設定問題,檢查 sensor_mode ID
   │  └─ 失敗 → 回到 sensor bring-up 流程
   └─ stream 動但 argus 無輸出 → CSI PHY 未啟用
      └─ 檢查 CSI_PHY_CTRL bit[0]
決策樹 2:HSB 取流延遲過高
1. 延遲 > 100ms?
   ├─ 網路層延遲:`ping -c 100 ` 看 avg/max
   │  ├─ ping > 1ms → cable/switch 問題
   │  └─ ping < 1ms → 應用層問題
   └─ 應用層:Holoscan queue size 過大,減少 buffer 數

5.20 量測驗證完整 SOP

首次取流完整 SOP:

步驟動作指令/方法預期輸出
Step 1硬件就緒確認排線接好、sensor 電源穩定、I2C 可通i2cdetect 可見
Step 2DT overlay apply`sudo ubootOverlayApply && sudo reboot`dmesg 出現 CSI init
Step 3V4L2 raw stream`v4l2-ctl -d /dev/video0 --stream-mmap --stream-count=1 --stream-to=raw.raw`檔案非零
Step 4argus stream`nvgstcapture-1.0 -m 1 -E 1`JPEG 檔案產生
Step 5HSB stream(如適用)Holoscan sensor → GPU pipelineGPU memory 有分配
Step 6延遲測量HSB timestamp - sensor timestamp< 50ms

5.21 四平台終極對照

面向Thor T5000RPi5Orange PiOrin Nano
取流工具`nvgstcapture` / Holoscan`libcamera-hello``v4l2-ctl` / `ffplay``nvgstcapture`
Buffer 管理NVMM buffer + GPU directV4L2 MMAPV4L2 MMAPNVMM buffer
多感測器取流Holoscan graph 同步`libcamera-hello -c 2`需手動 multiplexnvgst 多 pipeline
延遲目標(sensor→display)< 30ms(HSB)< 80ms< 100ms< 50ms
GPU 直連取流
HSB setup 複雜度中(需 config yaml)N/AN/AN/A

5.22 完整 Bring-up 小 Checklist

針對「第一個鏡頭跑起來」主題的完整 bring-up 步驟清單: