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