我們用 SMART——Specific(具體)、Measurable(可衡量)、Achievable(可達成)、Relevant(具關聯)、Time-bound(有時限)——把每個故事拆成五天,作為每次動手造輪子前的五個檢查問題。
本篇是故事四「從 ONVIF 攝影機截圖太難了,我們來搞 V4L2」的 Relevant 篇:這項工作與客戶價值、專案目標及交付有什麼關係?
本篇定位:分析技術方案是否仍對應原始問題,並討論跨越抽象邊界造成的維護成本。
那句「我們真的走得通」不是吹牛。提案的同事確實驗證過:裝置節點打得開、格式列得出來、影像讀得到。如果題目是「在攝影機裡抓到影像」,他成功了。
於是我們認真盤了一次:這條路走到交付長什麼樣子。
程式要在攝影機上跑,得為它的處理器架構做交叉編譯(cross compilation):先弄清楚它的指令集、C 函式庫與核心版本,再建一套對得上的工具鏈並固定下來。這套工具鏈從此也是我們要維護的東西。
抓到影像之後還有一段路。V4L2 並不是只會吐未壓縮的畫素——壓縮格式表裡就有 JPEG、H.264,拿不拿得到看驅動支援什麼。真正的成本在別處:用 VIDIOC_S_FMT 協商格式時,驅動會依硬體能力自行調整參數而不是報錯,你得回頭檢查它究竟給了什麼;再用 VIDIOC_REQBUFS、QBUF、DQBUF 與 STREAMON 管好一整套緩衝佇列;拿到畫面還要依 colorspace 與量化範圍自己做色彩轉換。想用硬體編碼,SoC 若提供 V4L2 的 memory-to-memory 編碼器驅動就能走標準介面,沒有那層驅動就得回頭抱原廠 SDK。
再來是部署。多數攝影機的根檔案系統是唯讀映像,可寫的只有一小塊快閃記憶體,或開機就清空的暫存區——程式放進去,下次重開可能就不見了。要讓它斷電後自己活回來,得把啟動掛勾插進原廠的開機流程,等於在別人的產品裡改開機順序。而這一切的入口,是一組出廠預設密碼的 SSH 通道。
盤到一半,會議室安靜了:這不是一支截圖程式,這是在別人的產品裡經營一套小系統。
V4L2 位在攝影機作業系統內部。以 Linux 為基礎的攝影機,內部擷取這一段常見但不必然建立在 V4L2 上——感測器、ISP 到編碼器是否全程走 V4L2 節點,取決於 SoC 廠商的驅動設計。無論如何,它解的問題叫「本機影像擷取」,我們的叫「遠端攝影機整合」,中間隔著一整條網路和一道產品邊界。
跨過這道邊界的代價,不在第一版能不能跑,而在之後的每一天。
原廠韌體升級是最明顯的一顆。韌體更新通常是整個檔案系統一起換掉,我們塞進去的程式與掛勾會直接消失。每次升級都是一輪重新部署與重測;久了會出現更糟的選擇——為了保住功能乾脆不升級,讓安全修補跟著停擺,用資安風險替一支截圖程式續命。
保固與支援是第二顆。被動過內部的設備一出問題,故障是產品的,還是我們塞進去那支程式的?原廠有理由拒絕受理,客戶問的人卻是我們。
第三顆是複用。換一個型號、甚至同品牌的下一代,處理器架構、系統版本、裝置節點命名都可能不同,工具鏈與部署腳本要重做。走標準介面,換設備只是換一組位址;走設備內部,等於重開一個專案,原本要的跨品牌整合就被綁死在特定型號的特定韌體上。
走標準介面不是零成本,只是形狀不同:工具鏈、部署、韌體升級與保固留在原廠那一側,我們仍要處理各家實作的差異;那是一份可攜的成本,處理過一次能帶到下一台設備上。
讓判斷落地的工具,是把兩條路並排寫成一張責任清單:誰編譯、誰部署、誰處理韌體升級、誰扛保固與資安。走標準介面,前幾格多半填「原廠」或「不需要」,我們只留下「誰維護整合程式」;走設備內部,每一格都得填上自己的名字,而韌體升級與資安那兩格,我們其實承擔不了——那台設備不是我們的產品。清單把「走得通」和「養得起」拆成兩個問題,後者才是專案要回答的。
Relevant 的檢查更樸素:把方案講成一句話,看它對齊的是需求還是別的東西。「透過設備公開介面取得影像」對齊需求;「在設備內部維護一支自己的擷取程式」對齊的是控制感。相關與否不看技術多深,看它落在邊界的哪一側,以及那一側是不是你的。
也該替 V4L2 說句公道話。主機上接一台 USB 攝影機、或者你本來就是攝影機韌體的開發者,用 V4L2 天經地義——那時你人在邊界裡面,而且邊界是你的產品。同一支 VIDIOC_S_FMT 呼叫,寫在自家主機的程式裡是正解,寫進別人的攝影機裡就是錯位:同一個介面換一個位置,評價整個翻轉。
一個技術可以很底層、很厲害,卻仍然與眼前的整合問題無關。「走得通」證明的是能力,不是相關性;最貴的浪費往往不是失敗的方案,而是成功地解掉一個不存在的問題,然後開始長期供養這個成功。
這些都是事後的清醒。回到當初卡住的那兩天,我們該掙扎多久才允許往下走?誰說了算?憑什麼證據?這個故事還欠最後一個答案。