Video (experimental)
The virtio video decoder and encoder devices allow a guest to leverage the host's hardware-accelerated video decoding and encoding capabilities. The specification (v3, v5) for these devices is still a work-in-progress, so testing them requires an out-of-tree kernel driver on the guest.
The virtio-video host device uses backends to perform the actual decoding. The currently supported backends are:
libvda, a hardware-accelerated backend that supports both decoding and encoding by delegating the work to a running instance of Chrome. It can only be built and used in a ChromeOS environment.ffmpeg, a software-based backend that supports encoding and decoding. It exists to make testing and development of virtio-video easier, as it does not require any particular hardware and is based on a reliable codec library.
The rest of this document will solely focus on the ffmpeg backend. More accelerated backends will be added in the future.
Guest kernel requirements
The virtio_video branch of this kernel git repository contains a work-in-progress version of the virtio-video guest kernel driver, based on a (hopefully) recent version of mainline Linux. If you use this as your guest kernel, the virtio_video_defconfig configuration should allow you to easily boot from crosvm, with the video (and a few other) virtio devices support built-in.
Quick building guide after checking out this branch:
The resulting kernel image that can be passed to crosvm will be in build_crosvm_x86/arch/x86/boot/bzImage.
Crosvm requirements
The virtio-video support is experimental and needs to be opted-in through the "video-decoder" or "video-encoder" Cargo feature. In the instruction below we'll be using the FFmpeg backend which requires the "ffmpeg" feature to be enabled as well.
The following example builds crosvm with FFmpeg encoder and decoder backend support:
To enable the decoder device, start crosvm with the --video-decoder=ffmpeg command-line argument:
Alternatively, to enable the encoder device, start crosvm with the --video-encoder=ffmpeg command-line argument:
If the guest kernel includes the virtio-video driver, then the device should be probed and show up.
Testing the device from the guest
Video capabilities are exposed to the guest using V4L2. The encoder or decoder device should appear as /dev/videoX, probably /dev/video0 if there are no additional V4L2 devices.
Checking capabilities and formats
v4l2-ctl, part of the v4l-utils package, can be used to test the device's existence.
Example output for the decoder is shown below.
Note that the Card type is ffmpeg, indicating that decoding will be performed in software on the host. We can then query the support input (OUTPUT in V4L2-speak) formats, i.e. the encoded formats we can send to the decoder:
Similarly, you can check the supported output (or CAPTURE) pixel formats for decoded frames:
Test decoding with ffmpeg
FFmpeg can be used to decode video streams with the virtio-video device.
Simple VP8 stream:
This should create 250 PNG files each containing a decoded frame from the stream.
WEBM VP9 stream:
Should create 300 PNG files at 720p resolution.
Test decoding with v4l2r
The v4l2r Rust crate also features an example program that can use this driver to decode simple H.264 streams:
This will decode test-25fps.h264 and write the raw decoded frames in NV12 format into test-25fps.nv12. You can check the result with e.g. YUView.
Test encoding with ffmpeg
FFmpeg can be used to encode video streams with the virtio-video device.
The following examples generates a test clip through libavfilter and encode it using the virtual H.264, H.265 and VP8 encoder, respectively. (VP9 v4l2m2m support is missing in FFmpeg for some reason.)