xref: /aosp_15_r20/external/crosvm/docs/book/src/devices/video.md (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1# Video (experimental)
2
3The virtio video decoder and encoder devices allow a guest to leverage the host's
4hardware-accelerated video decoding and encoding capabilities. The specification ([v3], [v5]) for
5these devices is still a work-in-progress, so testing them requires an out-of-tree kernel driver on
6the guest.
7
8The virtio-video host device uses backends to perform the actual decoding. The currently supported
9backends are:
10
11- `libvda`, a hardware-accelerated backend that supports both decoding and encoding by delegating
12  the work to a running instance of Chrome. It can only be built and used in a ChromeOS environment.
13- `ffmpeg`, a software-based backend that supports encoding and decoding. It exists to make testing
14  and development of virtio-video easier, as it does not require any particular hardware and is
15  based on a reliable codec library.
16
17The rest of this document will solely focus on the `ffmpeg` backend. More accelerated backends will
18be added in the future.
19
20## Guest kernel requirements
21
22The `virtio_video` branch of this [kernel git repository](https://github.com/Gnurou/linux) contains
23a work-in-progress version of the `virtio-video` guest kernel driver, based on a (hopefully) recent
24version of mainline Linux. If you use this as your guest kernel, the `virtio_video_defconfig`
25configuration should allow you to easily boot from crosvm, with the video (and a few other) virtio
26devices support built-in.
27
28Quick building guide after checking out this branch:
29
30```sh
31mkdir build_crosvm_x86
32make O=build_crosvm_x86 virtio_video_defconfig
33make O=build_crosvm_x86 -j16
34```
35
36The resulting kernel image that can be passed to `crosvm` will be in
37`build_crosvm_x86/arch/x86/boot/bzImage`.
38
39## Crosvm requirements
40
41The virtio-video support is experimental and needs to be opted-in through the `"video-decoder"` or
42`"video-encoder"` Cargo feature. In the instruction below we'll be using the FFmpeg backend which
43requires the `"ffmpeg"` feature to be enabled as well.
44
45The following example builds crosvm with FFmpeg encoder and decoder backend support:
46
47```sh
48cargo build --features "video-encoder,video-decoder,ffmpeg"
49```
50
51To enable the **decoder** device, start crosvm with the `--video-decoder=ffmpeg` command-line
52argument:
53
54```sh
55crosvm run --disable-sandbox --video-decoder=ffmpeg -c 4 -m 2048 --block /path/to/disk.img,root --serial type=stdout,hardware=virtio-console,console=true,stdin=true /path/to/bzImage
56```
57
58Alternatively, to enable the **encoder** device, start crosvm with the `--video-encoder=ffmpeg`
59command-line argument:
60
61```sh
62crosvm run --disable-sandbox --video-encoder=ffmpeg -c 4 -m 2048 --block /path/to/disk.img,root --serial type=stdout,hardware=virtio-console,console=true,stdin=true /path/to/bzImage
63```
64
65If the guest kernel includes the virtio-video driver, then the device should be probed and show up.
66
67## Testing the device from the guest
68
69Video capabilities are exposed to the guest using V4L2. The encoder or decoder device should appear
70as `/dev/videoX`, probably `/dev/video0` if there are no additional V4L2 devices.
71
72### Checking capabilities and formats
73
74`v4l2-ctl`, part of the `v4l-utils` package, can be used to test the device's existence.
75
76Example output for the decoder is shown below.
77
78```sh
79v4l2-ctl -d/dev/video0 --info
80Driver Info:
81        Driver name      : virtio-video
82        Card type        : ffmpeg
83        Bus info         : virtio:stateful-decoder
84        Driver version   : 5.17.0
85        Capabilities     : 0x84204000
86                Video Memory-to-Memory Multiplanar
87                Streaming
88                Extended Pix Format
89                Device Capabilities
90        Device Caps      : 0x04204000
91                Video Memory-to-Memory Multiplanar
92                Streaming
93                Extended Pix Format
94```
95
96Note that the `Card type` is `ffmpeg`, indicating that decoding will be performed in software on the
97host. We can then query the support input (`OUTPUT` in V4L2-speak) formats, i.e. the encoded formats
98we can send to the decoder:
99
100```sh
101v4l2-ctl -d/dev/video0 --list-formats-out
102ioctl: VIDIOC_ENUM_FMT
103        Type: Video Output Multiplanar
104
105        [0]: 'VP90' (VP9, compressed)
106        [1]: 'VP80' (VP8, compressed)
107        [2]: 'HEVC' (HEVC, compressed)
108        [3]: 'H264' (H.264, compressed)
109```
110
111Similarly, you can check the supported output (or CAPTURE) pixel formats for decoded frames:
112
113```sh
114v4l2-ctl -d/dev/video0 --list-formats
115ioctl: VIDIOC_ENUM_FMT
116        Type: Video Capture Multiplanar
117
118        [0]: 'NV12' (Y/CbCr 4:2:0)
119```
120
121### Test decoding with ffmpeg
122
123[FFmpeg](https://ffmpeg.org/) can be used to decode video streams with the virtio-video device.
124
125Simple VP8 stream:
126
127```sh
128wget https://github.com/chromium/chromium/raw/main/media/test/data/test-25fps.vp8
129ffmpeg -codec:v vp8_v4l2m2m -i test-25fps.vp8 test-25fps-%d.png
130```
131
132This should create 250 PNG files each containing a decoded frame from the stream.
133
134WEBM VP9 stream:
135
136```sh
137wget https://test-videos.co.uk/vids/bigbuckbunny/webm/vp9/720/Big_Buck_Bunny_720_10s_1MB.webm
138ffmpeg -codec:v vp9_v4l2m2m -i Big_Buck_Bunny_720_10s_1MB.webm Big_Buck_Bunny-%d.png
139```
140
141Should create 300 PNG files at 720p resolution.
142
143### Test decoding with v4l2r
144
145The [v4l2r](https://github.com/Gnurou/v4l2r) Rust crate also features an example program that can
146use this driver to decode simple H.264 streams:
147
148```sh
149git clone https://github.com/Gnurou/v4l2r
150cd v4l2r
151wget https://github.com/chromium/chromium/raw/main/media/test/data/test-25fps.h264
152cargo run --example simple_decoder test-25fps.h264 /dev/video0 --input_format h264 --save test-25fps.nv12
153```
154
155This will decode `test-25fps.h264` and write the raw decoded frames in `NV12` format into
156`test-25fps.nv12`. You can check the result with e.g. [YUView](https://github.com/IENT/YUView).
157
158### Test encoding with ffmpeg
159
160[FFmpeg](https://ffmpeg.org/) can be used to encode video streams with the virtio-video device.
161
162The following examples generates a test clip through libavfilter and encode it using the virtual
163H.264, H.265 and VP8 encoder, respectively. (VP9 v4l2m2m support is missing in FFmpeg for some
164reason.)
165
166```sh
167# H264
168ffmpeg -f lavfi -i smptebars=duration=10:size=640x480:rate=30 \
169  -pix_fmt nv12 -c:v h264_v4l2m2m smptebars.h264.mp4
170# H265
171ffmpeg -f lavfi -i smptebars=duration=10:size=640x480:rate=30 \
172  -pix_fmt yuv420p -c:v hevc_v4l2m2m smptebars.h265.mp4
173# VP8
174ffmpeg -f lavfi -i smptebars=duration=10:size=640x480:rate=30 \
175  -pix_fmt yuv420p -c:v vp8_v4l2m2m smptebars.vp8.webm
176```
177
178[v3]: https://markmail.org/message/dmw3pr4fuajvarth
179[v5]: https://markmail.org/message/zqxmuf5x7aosbmmm
180