為什麼多個消費者可以從網路攝像頭訪問 single v4l2-loopback 流
我最近需要一個網路攝像頭同時由 3 個應用程序(網路瀏覽器、影片會議應用程序和 ffmpeg 保存流)共享。
不可能簡單地共享 /dev/video* 流,因為一旦一個應用程序正在使用它,其他應用程序就不能,其他任何東西都會得到“設備或資源繁忙”或同等情況。
所以我轉向 v4l2-loopback,目的是將網路攝像頭鏡像到 3 個環回。
使用 3 個環回確實可以按預期工作,但真正讓我感到驚訝的是,我實際上並不需要3 個環回,而只需要 1 個。
如果我創建單個環回並使用 ffmpeg 提供它,則所有 3 個應用程序都可以同時使用單個鏡像環回,而不會出現“設備或資源繁忙”問題。
所以這比我計劃的還要好,沒有我需要幫助的實際問題。
但我的問題是,環回怎麼可能?為什麼不直接使用原始來源?
創建單個環回的範例命令:
sudo modprobe v4l2loopback video_nr=30 exclusive_caps=1 card_label="loopback cam"
使用 ffmpeg 將 /dev/video5 鏡像到環回 (/dev/video30) 的範例命令。這將預設為 raw,但最近建構的 ffmpeg 可以使用像 MJPEG 這樣的替代流,無論如何,行為都是相同的:
ffmpeg -f v4l2 -i /dev/video5 -codec copy -f v4l2 /dev/video30
完成此操作後,嘗試使用多個應用程序訪問 /dev/video30,以下是一些範例:
ffmpeg -f v4l2 -i /dev/video30 -codec libx264 recordstream.mp4 ffplay -f video4linux2 -i /dev/video30
相關的系統資訊:
- Ubuntu 20.04
- 核心:5.4.0-31-generic
- 包:v4l2loopback-dkms 0.12.3-1
這是設計使然。首先,假設多個程序可以打開 /dev/video0 設備,但只有其中一個程序能夠發出某些控制(ioctl()),直到流式傳輸開始。
那些 V4L2控制項定義了比特率之類的東西。開始流式傳輸後,如果您嘗試,核心將不允許您更改它們並返回
EBUSY
(設備或資源忙)。請參閱核心原始碼中的此註釋。這有效地阻止了其他消費者,因為您應該在開始流式傳輸之前設置它們。v4l2loopback 有什麼不同?它為多個開啟者添加了邏輯和資料結構,預設情況下不會通過提供自己的設置器來嘗試應用新控制項。
注意 v4l2loopback 需要有多個開啟者,至少兩個是有用的。一位讀者和一位作家。