--- tags: Linux kernel, vcam, v4l2 --- # vcam 測試記錄 此篇為測試 jserv 老師的 github 專案 [vcam](https://github.com/jserv/vcam) 的過程記錄。 測試環境 - Lubuntu 18.04 - Linux kernel 4.15.0-74 ## 準備相關套件 編譯 linux kernel module 會用到 linux header。安裝命令如下: ```shell $ sudo apt install linux-headers-$(uname -r) ``` 為了方便後續驗證 vcam 的 v4l2 interface,先安裝工具 vlc 和 v4l-utils: ```shell $ sudo apt install v4l-utils $ sudo apt install vlc ``` 編譯前最後一個步驟,下載 source code: ```shell $ git clone https://github.com/jserv/vcam.git ``` ## 編譯 在 vcam 目錄下執行 `make` 即可,過程訊息如下 > make -C /lib/modules/4.15.0-74-generic/build M=/home/ben/study/vcam modules make[1]: Entering directory '/usr/src/linux-headers-4.15.0-74-generic' CC [M] /home/ben/study/vcam/module.o CC [M] /home/ben/study/vcam/control.o CC [M] /home/ben/study/vcam/device.o CC [M] /home/ben/study/vcam/videobuf.o CC [M] /home/ben/study/vcam/fb.o LD [M] /home/ben/study/vcam/vcam.o Building modules, stage 2. MODPOST 1 modules CC /home/ben/study/vcam/vcam.mod.o LD [M] /home/ben/study/vcam/vcam.ko make[1]: Leaving directory '/usr/src/linux-headers-4.15.0-74-generic' cc -O2 -Wall -Wextra -pedantic -std=c99 -o vcam-util vcam-util.c 編譯完成可以看到目錄下產生了 kernel module 和執行檔,分別是 `vcam.ko` 和 `vcam-util`。 ## 載入 vcam 測試的第一個步驟是載入編譯出的 module。首先確認相依的 module videobuf2_vmalloc 和 videobuf2_v4l2 是否已載入 ```shell $ lsmod | grep videobuf2* ``` 因為我使用的電腦是內建 camera 的筆電,從下方輸出訊息可以看到相依 module 已經載入 > videobuf2_vmalloc 16384 1 uvcvideo videobuf2_memops 16384 1 videobuf2_vmalloc videobuf2_v4l2 24576 1 uvcvideo videobuf2_core 40960 2 videobuf2_v4l2,uvcvideo videodev 184320 3 videobuf2_core,videobuf2_v4l2,uvcvideo 若相依的 module 還未載入,執行下面指令載入 ```shell $ sudo modprobe videobuf2_vmalloc videobuf2_v4l2 ``` 執行下面指令載入 vcam module ```shell $ sudo insmod vcam.ko ``` 執行 `lsmod | grep vcam` 確認載入是否成功 > vcam 36864 0 videobuf2_vmalloc 16384 2 vcam,uvcvideo videobuf2_v4l2 24576 2 vcam,uvcvideo videobuf2_core 40960 3 vcam,videobuf2_v4l2,uvcvideo videodev 184320 4 videobuf2_core,vcam,videobuf2_v4l2,uvcvideo ## 檢視 vcam 相關資訊 kernel module 載入後,可用下方指令列出目前有哪些 vcam device 產生 ```shell $ sudo ./vcam-util -l ``` 輸出如下 > Available virtual V4L2 compatible devices: > 1. vcamfb1(640,480,rgb24) -> /dev/video1 得知有一個 vcam device 是 /dev/video1,其對應輸入裝置為 vcamfb1,可接受的格式為 24-bit RGB,解析度 640x480。 實際使用指令 `ls -l /dev/video1` 確認 device file 存在 > crw-rw----+ 1 root video 81, 1 Feb 18 21:46 /dev/video1 此外 module 載入後還會產生一個 device file vcamctl,後續可用工具程式 vcam-util 對其做 ioctl,修改或增減 vcam device > crw------- 1 root root 238, 0 Feb 18 21:46 /dev/vcamctl 使用下方指令測試此 vcam device 的能力(v4l2相關操作的相容性) ```shell $ v4l2-compliance -d /dev/video1 -f ``` 輸出結果如下 >v4l2-compliance SHA : not available > >Driver Info: > Driver name : vcam > Card type : vcam > Bus info : platform: virtual > Driver version: 4.15.18 > Capabilities : 0x85200001 > Video Capture > Read/Write > Streaming > Extended Pix Format > Device Capabilities > Device Caps : 0x05200001 > Video Capture > Read/Write > Streaming > Extended Pix Format > >Compliance test for device /dev/video1 (not using libv4l2): > >Required ioctls: > test VIDIOC_QUERYCAP: OK > >Allow for multiple opens: > test second video open: OK > test VIDIOC_QUERYCAP: OK > test VIDIOC_G/S_PRIORITY: OK > test for unlimited opens: OK > >Debug ioctls: > test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported) > test VIDIOC_LOG_STATUS: OK (Not Supported) > >Input ioctls: > test VIDIOC_G/S_TUNER/ENUM_FREQ_BANDS: OK (Not Supported) > test VIDIOC_G/S_FREQUENCY: OK (Not Supported) > test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported) > test VIDIOC_ENUMAUDIO: OK (Not Supported) > test VIDIOC_G/S/ENUMINPUT: OK > test VIDIOC_G/S_AUDIO: OK (Not Supported) > Inputs: 1 Audio Inputs: 0 Tuners: 0 > >Output ioctls: > test VIDIOC_G/S_MODULATOR: OK (Not Supported) > test VIDIOC_G/S_FREQUENCY: OK (Not Supported) > test VIDIOC_ENUMAUDOUT: OK (Not Supported) > test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported) > test VIDIOC_G/S_AUDOUT: OK (Not Supported) > Outputs: 0 Audio Outputs: 0 Modulators: 0 > >Input/Output configuration ioctls: > test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported) > test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported) > test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported) > test VIDIOC_G/S_EDID: OK (Not Supported) > >Test input 0: > > Control ioctls: > test VIDIOC_QUERY_EXT_CTRL/QUERYMENU: OK (Not Supported) > test VIDIOC_QUERYCTRL: OK (Not Supported) > test VIDIOC_G/S_CTRL: OK (Not Supported) > test VIDIOC_G/S/TRY_EXT_CTRLS: OK (Not Supported) > test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK (Not Supported) > test VIDIOC_G/S_JPEGCOMP: OK (Not Supported) > Standard Controls: 0 Private Controls: 0 > > Format ioctls: > test >VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK > fail: v4l2-test-formats.cpp(1140): node->has_frmintervals && !cap->capability > test VIDIOC_G/S_PARM: FAIL > test VIDIOC_G_FBUF: OK (Not Supported) > test VIDIOC_G_FMT: OK > test VIDIOC_TRY_FMT: OK > test VIDIOC_S_FMT: OK > test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported) > test Cropping: OK (Not Supported) > test Composing: OK (Not Supported) > test Scaling: OK (Not Supported) > > Codec ioctls: > test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported) > test VIDIOC_G_ENC_INDEX: OK (Not Supported) > test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported) > > Buffer ioctls: > test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK > test VIDIOC_EXPBUF: OK > >Test input 0: > >Stream using all formats: > test MMAP for Format RGB3, Frame Size 640x480@59.94 Hz: > Stride 1920, Field None: OK > test MMAP for Format RGB3, Frame Size 640x480@0.00 Hz: > Stride 1920, Field None: OK > >Total: 45, Succeeded: 44, Failed: 1, Warnings: 0 下方指令也可以印出 vcam device 的相關資訊 ```shell $ sudo v4l2-ctl -d /dev/video1 --all ``` >Driver Info (not using libv4l2): > Driver name : vcam > Card type : vcam > Bus info : platform: virtual > Driver version: 4.15.18 > Capabilities : 0x85200001 > Video Capture > Read/Write > Streaming > Extended Pix Format > Device Capabilities > Device Caps : 0x05200001 > Video Capture > Read/Write > Streaming > Extended Pix Format >Priority: 2 >Video input : 0 (vcam_in 0: ok) >Format Video Capture: > Width/Height : 640/480 > Pixel Format : 'RGB3' > Field : None > Bytes per Line : 1920 > Size Image : 921600 > Colorspace : sRGB > Transfer Function : Default (maps to sRGB) > YCbCr/HSV Encoding: Default (maps to ITU-R 601) > Quantization : Default (maps to Full Range) > Flags : >Streaming Parameters Video Capture: > Frames per second: 29.970 (30000/1001) > Read buffers : 1 ## 測試 vcam 使用 vlc 播放 vcam 影像 ```shell $ vlc v4l2:///dev/video1 ``` 看到的影像是固定不變的漸層畫面 ![](https://i.imgur.com/t4LpAup.png) 試著對 /proc/vcamfb1 持續寫入 random 資料 ```shell $ cat /dev/urandom > /proc/vcamfb1 ``` 看到的影像是不停跳動的雜訊 ![](https://i.imgur.com/uxMOqAv.jpg) 寫支小程式產生持續變化的單色畫面,程式碼如下: ```C= #include <stdio.h> int main() { int i, j; unsigned char rgb[3] = {10, 60, 128}; while (1) { for (i = 0; i < 480; i++) { for (j = 0; j < 640; j++) { fwrite(rgb, sizeof(rgb), 1, stdout); } } for (i = 0; i < 3; i++) { rgb[i]++; } } return 0; } ``` 編譯並程式,將輸出導向 /proc/vcamfb1 ```shell $ gcc rgb.c -o rgb $ ./rgb > /proc/vcamfb1 ``` 從 vlc 看到影像的確是單色,且會漸漸改變顏色。因為懶得做 gif 動畫,下面只截一張圖示意 ![](https://i.imgur.com/YCM6cwZ.png) ## 後續 - 用 vcam-util 增減和修改 device - v4l2 device driver 架構 - framebuffer 的運作機制