1*1b4853f5SAndroid Build Coastguard Worker# Trying out virtio-media 2*1b4853f5SAndroid Build Coastguard Worker 3*1b4853f5SAndroid Build Coastguard WorkerThis document demonstrates how to quickly try virtio-media by controlling a 4*1b4853f5SAndroid Build Coastguard Workervirtual host device through a Debian guest image using the 5*1b4853f5SAndroid Build Coastguard Worker[crosvm](https://crosvm.dev/book/) VMM. 6*1b4853f5SAndroid Build Coastguard Worker 7*1b4853f5SAndroid Build Coastguard WorkerThrough this document, we will build and run the following components: 8*1b4853f5SAndroid Build Coastguard Worker 9*1b4853f5SAndroid Build Coastguard Worker- A guest Linux kernel with virtio-media support enabled 10*1b4853f5SAndroid Build Coastguard Worker- The virtio-media guest kernel module 11*1b4853f5SAndroid Build Coastguard Worker- A Debian guest image with v4l-utils installed 12*1b4853f5SAndroid Build Coastguard Worker- Crosvm with virtio-media support 13*1b4853f5SAndroid Build Coastguard Worker 14*1b4853f5SAndroid Build Coastguard Worker## Prerequisites 15*1b4853f5SAndroid Build Coastguard Worker 16*1b4853f5SAndroid Build Coastguard Worker- A C compiler toolchain 17*1b4853f5SAndroid Build Coastguard Worker- The [Rust toolchain](https://rustup.rs/) version 1.75 or later 18*1b4853f5SAndroid Build Coastguard Worker- The `virt-builder utility` (usually available in the `libguestfs-tools` 19*1b4853f5SAndroid Build Coastguard Worker package) 20*1b4853f5SAndroid Build Coastguard Worker 21*1b4853f5SAndroid Build Coastguard Worker## Directory Setup 22*1b4853f5SAndroid Build Coastguard Worker 23*1b4853f5SAndroid Build Coastguard WorkerCreate a workspace directory and get into it: 24*1b4853f5SAndroid Build Coastguard Worker 25*1b4853f5SAndroid Build Coastguard Worker```console 26*1b4853f5SAndroid Build Coastguard Workermkdir virtio_media_playground 27*1b4853f5SAndroid Build Coastguard Workercd virtio_media_playground 28*1b4853f5SAndroid Build Coastguard Worker``` 29*1b4853f5SAndroid Build Coastguard Worker 30*1b4853f5SAndroid Build Coastguard WorkerThis directory can be erased in order to remove everything we will build here. 31*1b4853f5SAndroid Build Coastguard Worker 32*1b4853f5SAndroid Build Coastguard Worker## Guest Kernel Image 33*1b4853f5SAndroid Build Coastguard Worker 34*1b4853f5SAndroid Build Coastguard WorkerThe virtio-media guest driver works with a regular mainline Linux kernel, as 35*1b4853f5SAndroid Build Coastguard Workerlong as the required virtio and V4L2 options are enabled. 36*1b4853f5SAndroid Build Coastguard Worker 37*1b4853f5SAndroid Build Coastguard Worker1. Clone the kernel repository: 38*1b4853f5SAndroid Build Coastguard Worker 39*1b4853f5SAndroid Build Coastguard Worker ```console 40*1b4853f5SAndroid Build Coastguard Worker git clone --branch virtio-media --depth=2 https://github.com/Gnurou/linux 41*1b4853f5SAndroid Build Coastguard Worker cd linux 42*1b4853f5SAndroid Build Coastguard Worker ``` 43*1b4853f5SAndroid Build Coastguard Worker 44*1b4853f5SAndroid Build Coastguard Worker This branch is just a regular Linux mainline release with a commit on top 45*1b4853f5SAndroid Build Coastguard Worker that adds the configuration we will use. 46*1b4853f5SAndroid Build Coastguard Worker 47*1b4853f5SAndroid Build Coastguard Worker2. Build the kernel: 48*1b4853f5SAndroid Build Coastguard Worker 49*1b4853f5SAndroid Build Coastguard Worker ```console 50*1b4853f5SAndroid Build Coastguard Worker mkdir build_virtio_media 51*1b4853f5SAndroid Build Coastguard Worker make O=build_virtio_media virtio_crosvm_defconfig 52*1b4853f5SAndroid Build Coastguard Worker make O=build_virtio_media -j16 bzImage modules 53*1b4853f5SAndroid Build Coastguard Worker ``` 54*1b4853f5SAndroid Build Coastguard Worker 55*1b4853f5SAndroid Build Coastguard Worker (Adjust `-j16` to match your number of CPU cores) 56*1b4853f5SAndroid Build Coastguard Worker 57*1b4853f5SAndroid Build Coastguard Worker## Virtio-media Guest Kernel Module 58*1b4853f5SAndroid Build Coastguard Worker 59*1b4853f5SAndroid Build Coastguard Worker1. Clone the virtio-media repository: 60*1b4853f5SAndroid Build Coastguard Worker 61*1b4853f5SAndroid Build Coastguard Worker ```console 62*1b4853f5SAndroid Build Coastguard Worker cd .. # Back to the workspace root 63*1b4853f5SAndroid Build Coastguard Worker git clone https://github.com/chromeos/virtio-media 64*1b4853f5SAndroid Build Coastguard Worker cd virtio-media/driver 65*1b4853f5SAndroid Build Coastguard Worker ``` 66*1b4853f5SAndroid Build Coastguard Worker 67*1b4853f5SAndroid Build Coastguard Worker2. Build the module: 68*1b4853f5SAndroid Build Coastguard Worker 69*1b4853f5SAndroid Build Coastguard Worker ```console 70*1b4853f5SAndroid Build Coastguard Worker make -C ../../linux/build_virtio_media/ M=$PWD 71*1b4853f5SAndroid Build Coastguard Worker ``` 72*1b4853f5SAndroid Build Coastguard Worker 73*1b4853f5SAndroid Build Coastguard Worker## Guest System Image 74*1b4853f5SAndroid Build Coastguard Worker 75*1b4853f5SAndroid Build Coastguard WorkerCreate the Debian image: 76*1b4853f5SAndroid Build Coastguard Worker 77*1b4853f5SAndroid Build Coastguard Worker```console 78*1b4853f5SAndroid Build Coastguard Workercd ../.. # Back to the workspace root 79*1b4853f5SAndroid Build Coastguard Workervirt-builder debian-12 \ 80*1b4853f5SAndroid Build Coastguard Worker --install v4l-utils \ 81*1b4853f5SAndroid Build Coastguard Worker --root-password password:"" \ 82*1b4853f5SAndroid Build Coastguard Worker --mkdir /root/vmedia \ 83*1b4853f5SAndroid Build Coastguard Worker --append-line '/etc/fstab:vmedia /root/vmedia virtiofs' 84*1b4853f5SAndroid Build Coastguard Worker``` 85*1b4853f5SAndroid Build Coastguard Worker 86*1b4853f5SAndroid Build Coastguard WorkerThis command does the following: 87*1b4853f5SAndroid Build Coastguard Worker 88*1b4853f5SAndroid Build Coastguard Worker- Download a Debian 12 image, 89*1b4853f5SAndroid Build Coastguard Worker- Install the `v4l-utils` package into it, 90*1b4853f5SAndroid Build Coastguard Worker- Set the root password to be empty, 91*1b4853f5SAndroid Build Coastguard Worker- Ensures that the shared virtiofs filesystem labeled `vmedia` (that we will use 92*1b4853f5SAndroid Build Coastguard Worker to share the host directory containing the virtio-media kernel module) is 93*1b4853f5SAndroid Build Coastguard Worker mounted into `/root/vmedia`. 94*1b4853f5SAndroid Build Coastguard Worker 95*1b4853f5SAndroid Build Coastguard Worker## Crosvm 96*1b4853f5SAndroid Build Coastguard Worker 97*1b4853f5SAndroid Build Coastguard Worker1. Clone and checkout the crosvm branch containing the work-in-progress 98*1b4853f5SAndroid Build Coastguard Worker virtio-media support: 99*1b4853f5SAndroid Build Coastguard Worker 100*1b4853f5SAndroid Build Coastguard Worker ```console 101*1b4853f5SAndroid Build Coastguard Worker git clone --depth=1 https://chromium.googlesource.com/crosvm/crosvm 102*1b4853f5SAndroid Build Coastguard Worker cd crosvm 103*1b4853f5SAndroid Build Coastguard Worker git fetch --depth=10 origin refs/changes/29/5065329/9 104*1b4853f5SAndroid Build Coastguard Worker git checkout FETCH_HEAD 105*1b4853f5SAndroid Build Coastguard Worker git submodule update --init 106*1b4853f5SAndroid Build Coastguard Worker ``` 107*1b4853f5SAndroid Build Coastguard Worker 108*1b4853f5SAndroid Build Coastguard Worker2. Build the crosvm binary: 109*1b4853f5SAndroid Build Coastguard Worker 110*1b4853f5SAndroid Build Coastguard Worker ```console 111*1b4853f5SAndroid Build Coastguard Worker cargo build --release --features "media" 112*1b4853f5SAndroid Build Coastguard Worker ``` 113*1b4853f5SAndroid Build Coastguard Worker 114*1b4853f5SAndroid Build Coastguard WorkerIf everything goes well, the binary should be in `target/release/crosvm`, and we 115*1b4853f5SAndroid Build Coastguard Workernow are ready to run our VM and try out some virtual media devices! 116*1b4853f5SAndroid Build Coastguard Worker 117*1b4853f5SAndroid Build Coastguard Worker## Start the VM 118*1b4853f5SAndroid Build Coastguard Worker 119*1b4853f5SAndroid Build Coastguard Worker```console 120*1b4853f5SAndroid Build Coastguard Workercd .. # Back to the workspace root 121*1b4853f5SAndroid Build Coastguard Worker./crosvm/target/release/crosvm run \ 122*1b4853f5SAndroid Build Coastguard Worker linux/build_virtio_media/arch/x86/boot/bzImage \ 123*1b4853f5SAndroid Build Coastguard Worker --rwdisk debian-12.img \ 124*1b4853f5SAndroid Build Coastguard Worker -p "root=/dev/vda1" \ 125*1b4853f5SAndroid Build Coastguard Worker --shared-dir "$PWD/virtio-media:vmedia:type=fs" \ 126*1b4853f5SAndroid Build Coastguard Worker --simple-media 127*1b4853f5SAndroid Build Coastguard Worker``` 128*1b4853f5SAndroid Build Coastguard Worker 129*1b4853f5SAndroid Build Coastguard WorkerThis command does the following: 130*1b4853f5SAndroid Build Coastguard Worker 131*1b4853f5SAndroid Build Coastguard Worker- Start the kernel image we built, 132*1b4853f5SAndroid Build Coastguard Worker- Adds the Debian guest image as a virtual disk, 133*1b4853f5SAndroid Build Coastguard Worker- Passes the kernel parameter to use this virtual disk as root partition, 134*1b4853f5SAndroid Build Coastguard Worker- Shares the folder containing the virtio-media kernel module as a virtiofs 135*1b4853f5SAndroid Build Coastguard Worker filesystem labeled `vmedia`, 136*1b4853f5SAndroid Build Coastguard Worker- Adds a simple, dummy virtio-media test device that is entirely emulated in 137*1b4853f5SAndroid Build Coastguard Worker crosvm. 138*1b4853f5SAndroid Build Coastguard Worker 139*1b4853f5SAndroid Build Coastguard WorkerYou should see the system booting. After a few seconds, press `<enter>` to get 140*1b4853f5SAndroid Build Coastguard Workerthe login prompt. Login as `root` with an empty password. 141*1b4853f5SAndroid Build Coastguard Worker 142*1b4853f5SAndroid Build Coastguard WorkerWe will now want to insert the `virtio-media` kernel module: 143*1b4853f5SAndroid Build Coastguard Worker 144*1b4853f5SAndroid Build Coastguard Worker```console 145*1b4853f5SAndroid Build Coastguard Workerinsmod /root/vmedia/driver/virtio-media.ko 146*1b4853f5SAndroid Build Coastguard Worker``` 147*1b4853f5SAndroid Build Coastguard Worker 148*1b4853f5SAndroid Build Coastguard Worker## Test the Virtual Device 149*1b4853f5SAndroid Build Coastguard Worker 150*1b4853f5SAndroid Build Coastguard WorkerThe simple virtio-media device should have been detected and become visible as 151*1b4853f5SAndroid Build Coastguard Worker`/dev/video0`. Let's see if it works: 152*1b4853f5SAndroid Build Coastguard Worker 153*1b4853f5SAndroid Build Coastguard Worker```console 154*1b4853f5SAndroid Build Coastguard Workerv4l2-compliance -d0 -s 155*1b4853f5SAndroid Build Coastguard Worker``` 156*1b4853f5SAndroid Build Coastguard Worker 157*1b4853f5SAndroid Build Coastguard WorkerThis should display a long list of tests ending with: 158*1b4853f5SAndroid Build Coastguard Worker 159*1b4853f5SAndroid Build Coastguard Worker```console 160*1b4853f5SAndroid Build Coastguard Worker... 161*1b4853f5SAndroid Build Coastguard WorkerTotal for virtio_media device /dev/video0: 54, Succeeded: 54, Failed: 0, Warnings: 1 162*1b4853f5SAndroid Build Coastguard Worker``` 163*1b4853f5SAndroid Build Coastguard Worker 164*1b4853f5SAndroid Build Coastguard WorkerWe can also check its supported capture formats: 165*1b4853f5SAndroid Build Coastguard Worker 166*1b4853f5SAndroid Build Coastguard Worker```console 167*1b4853f5SAndroid Build Coastguard Workerv4l2-ctl -d0 --list-formats 168*1b4853f5SAndroid Build Coastguard Worker``` 169*1b4853f5SAndroid Build Coastguard Worker 170*1b4853f5SAndroid Build Coastguard WorkerWhich informs us that our device only supports `RGB3`: 171*1b4853f5SAndroid Build Coastguard Worker 172*1b4853f5SAndroid Build Coastguard Worker```console 173*1b4853f5SAndroid Build Coastguard Workerioctl: VIDIOC_ENUM_FMT 174*1b4853f5SAndroid Build Coastguard Worker Type: Video Capture 175*1b4853f5SAndroid Build Coastguard Worker 176*1b4853f5SAndroid Build Coastguard Worker [0]: 'RGB3' (24-bit RGB 8-8-8) 177*1b4853f5SAndroid Build Coastguard Worker``` 178*1b4853f5SAndroid Build Coastguard Worker 179*1b4853f5SAndroid Build Coastguard WorkerAnd we can also capture frames from it: 180*1b4853f5SAndroid Build Coastguard Worker 181*1b4853f5SAndroid Build Coastguard Worker```console 182*1b4853f5SAndroid Build Coastguard Workerv4l2-ctl -d0 --stream-mmap --stream-count 30 --stream-to /root/vmedia/simple.rgb 183*1b4853f5SAndroid Build Coastguard Worker``` 184*1b4853f5SAndroid Build Coastguard Worker 185*1b4853f5SAndroid Build Coastguard WorkerThis writes 30 640x480 RGB frames (all filled with a single color) into the 186*1b4853f5SAndroid Build Coastguard Worker`simple.rgb` file of our `virtio-media` directory on the host. You can visualize 187*1b4853f5SAndroid Build Coastguard Workerthe output using a dedicated tool like [YUView](https://github.com/IENT/YUView). 188*1b4853f5SAndroid Build Coastguard Worker 189*1b4853f5SAndroid Build Coastguard WorkerThat's enough for this simple example. Next we will see how to proxy a V4L2 190*1b4853f5SAndroid Build Coastguard Workerdevice on the host into the guest. Let's exit the guest: 191*1b4853f5SAndroid Build Coastguard Worker 192*1b4853f5SAndroid Build Coastguard Worker```console 193*1b4853f5SAndroid Build Coastguard Workerpoweroff 194*1b4853f5SAndroid Build Coastguard Worker``` 195*1b4853f5SAndroid Build Coastguard Worker 196*1b4853f5SAndroid Build Coastguard Worker## Proxy a host V4L2 device into a guest 197*1b4853f5SAndroid Build Coastguard Worker 198*1b4853f5SAndroid Build Coastguard WorkerThis next example uses virtio-media's V4L2 proxy device to make a host V4L2 199*1b4853f5SAndroid Build Coastguard Workerdevice visible almost as-is into a guest. We will need a working V4L2 device on 200*1b4853f5SAndroid Build Coastguard Workerthe host, for this example we will assume a regular USB camera using the 201*1b4853f5SAndroid Build Coastguard Worker`uvcvideo` driver. With the camera plugged, use `v4l2-ctl` on the host to find 202*1b4853f5SAndroid Build Coastguard Workerout the number of the device: 203*1b4853f5SAndroid Build Coastguard Worker 204*1b4853f5SAndroid Build Coastguard Worker```console 205*1b4853f5SAndroid Build Coastguard Workerv4l2-ctl -d0 --info 206*1b4853f5SAndroid Build Coastguard Worker``` 207*1b4853f5SAndroid Build Coastguard Worker 208*1b4853f5SAndroid Build Coastguard WorkerIf the output lines look something like 209*1b4853f5SAndroid Build Coastguard Worker 210*1b4853f5SAndroid Build Coastguard Worker```console 211*1b4853f5SAndroid Build Coastguard WorkerDriver Info: 212*1b4853f5SAndroid Build Coastguard Worker Driver name : uvcvideo 213*1b4853f5SAndroid Build Coastguard Worker Card type : <Camera name> 214*1b4853f5SAndroid Build Coastguard Worker``` 215*1b4853f5SAndroid Build Coastguard Worker 216*1b4853f5SAndroid Build Coastguard WorkerThen you have found the correct device. If not, replace `-d0` with `-d1`, `-d2`, 217*1b4853f5SAndroid Build Coastguard Worker... until you find a device which driver name is `uvcvideo`. 218*1b4853f5SAndroid Build Coastguard Worker 219*1b4853f5SAndroid Build Coastguard WorkerNow that we have found the device, we can start `crosvm` with a proxy device for 220*1b4853f5SAndroid Build Coastguard Workerit: 221*1b4853f5SAndroid Build Coastguard Worker 222*1b4853f5SAndroid Build Coastguard Worker```console 223*1b4853f5SAndroid Build Coastguard Worker./crosvm/target/release/crosvm run \ 224*1b4853f5SAndroid Build Coastguard Worker linux/build_virtio_media/arch/x86/boot/bzImage \ 225*1b4853f5SAndroid Build Coastguard Worker --rwdisk debian-12.img \ 226*1b4853f5SAndroid Build Coastguard Worker -p "root=/dev/vda1" \ 227*1b4853f5SAndroid Build Coastguard Worker --shared-dir "$PWD/virtio-media:vmedia:type=fs" \ 228*1b4853f5SAndroid Build Coastguard Worker --v4l2-proxy /dev/video0 229*1b4853f5SAndroid Build Coastguard Worker``` 230*1b4853f5SAndroid Build Coastguard Worker 231*1b4853f5SAndroid Build Coastguard WorkerThe `/dev/video0` assumes that the `-d0` argument of `v4l2-ctl` returned the 232*1b4853f5SAndroid Build Coastguard Workerright device - adjust the argument for the actual device on your host. 233*1b4853f5SAndroid Build Coastguard Worker 234*1b4853f5SAndroid Build Coastguard WorkerWith the guest booted, we can insert the `v4l2-media` module again: 235*1b4853f5SAndroid Build Coastguard Worker 236*1b4853f5SAndroid Build Coastguard Worker```console 237*1b4853f5SAndroid Build Coastguard Workerinsmod /root/vmedia/driver/virtio-media.ko 238*1b4853f5SAndroid Build Coastguard Worker``` 239*1b4853f5SAndroid Build Coastguard Worker 240*1b4853f5SAndroid Build Coastguard WorkerAnd check that our device is indeed recognized: 241*1b4853f5SAndroid Build Coastguard Worker 242*1b4853f5SAndroid Build Coastguard Worker```console 243*1b4853f5SAndroid Build Coastguard Workerv4l2-ctl -d0 --info 244*1b4853f5SAndroid Build Coastguard Worker``` 245*1b4853f5SAndroid Build Coastguard Worker 246*1b4853f5SAndroid Build Coastguard WorkerThis should return sensibly the same output as when the command was run on the 247*1b4853f5SAndroid Build Coastguard Workerhost, with the exception that the driver name is now `virtio_media`. 248*1b4853f5SAndroid Build Coastguard Worker 249*1b4853f5SAndroid Build Coastguard WorkerMost USB cameras support streaming into motion-JPEG, so let's try to capture a 250*1b4853f5SAndroid Build Coastguard Workerstream: 251*1b4853f5SAndroid Build Coastguard Worker 252*1b4853f5SAndroid Build Coastguard Worker```console 253*1b4853f5SAndroid Build Coastguard Workerv4l2-ctl -d0 --stream-mmap --set-fmt-video pixelformat=MJPG --stream-to /root/vmedia/out.mpg 254*1b4853f5SAndroid Build Coastguard Worker``` 255*1b4853f5SAndroid Build Coastguard Worker 256*1b4853f5SAndroid Build Coastguard WorkerUse `Ctrl-C` to stop the capture. The stream has been recorded into the 257*1b4853f5SAndroid Build Coastguard Workerdirectory shared with the host, so let's exit the guest in order to check it 258*1b4853f5SAndroid Build Coastguard Workerout: 259*1b4853f5SAndroid Build Coastguard Worker 260*1b4853f5SAndroid Build Coastguard Worker```console 261*1b4853f5SAndroid Build Coastguard Workerpoweroff 262*1b4853f5SAndroid Build Coastguard Worker``` 263*1b4853f5SAndroid Build Coastguard Worker 264*1b4853f5SAndroid Build Coastguard WorkerThen on the host, use your media player of choice to view the captured file: 265*1b4853f5SAndroid Build Coastguard Worker 266*1b4853f5SAndroid Build Coastguard Worker```console 267*1b4853f5SAndroid Build Coastguard Workerffplay virtio-media/out.mpg 268*1b4853f5SAndroid Build Coastguard Worker``` 269