virtio: video: make libvda a selectable feature

For the crosvm externalization project, we want to be able to compile
video support without libvda, which is only supported on Chrome OS.

Add an explicit "libvda" feature to crosvm and make all the libvda code
depend on that feature, so any trace of libvda can effectively be
compiled out.

For compatibility, the "libvda" feature is selected by the
"video-decoder" or "video-encoder" features.

BUG=b:161774071
BUG=b:169295147
TEST=`cargo build --features="video-decoder,video-encoder"` results in a
     crosvm binary with libvda enabled.

Change-Id: Ice3d3089b73b77f6b009400953063f2cf8f385da
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3026351
Reviewed-by: Keiichi Watanabe <keiichiw@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Alexandre Courbot <acourbot@chromium.org>
diff --git a/Cargo.toml b/Cargo.toml
index 0ff4a49..70ec58f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -101,12 +101,13 @@
 gdb = ["gdbstub", "gdbstub_arch", "arch/gdb", "vm_control/gdb", "x86_64/gdb"]
 gfxstream = ["devices/gfxstream"]
 gpu = ["devices/gpu"]
+libvda = ["devices/libvda"]
 plugin = ["protos/plugin", "crosvm_plugin", "kvm", "kvm_sys", "protobuf"]
 power-monitor-powerd = ["arch/power-monitor-powerd"]
 tpm = ["devices/tpm"]
 usb = ["devices/usb"]
-video-decoder = ["devices/video-decoder"]
-video-encoder = ["devices/video-encoder"]
+video-decoder = ["devices/video-decoder", "libvda"]
+video-encoder = ["devices/video-encoder", "libvda"]
 virgl_renderer = ["devices/virgl_renderer"]
 virgl_renderer_next = ["rutabaga_gfx/virgl_renderer_next"]
 wl-dmabuf = ["devices/minigbm"]
diff --git a/devices/Cargo.toml b/devices/Cargo.toml
index 9db4035..9bf43bb 100644
--- a/devices/Cargo.toml
+++ b/devices/Cargo.toml
@@ -12,8 +12,8 @@
 gpu = ["gpu_display","rutabaga_gfx"]
 tpm = ["tpm2"]
 usb = []
-video-decoder = ["libvda"]
-video-encoder = ["libvda"]
+video-decoder = []
+video-encoder = []
 minigbm = ["rutabaga_gfx/minigbm"]
 x = ["gpu_display/x"]
 virgl_renderer = ["gpu", "rutabaga_gfx/virgl_renderer"]
diff --git a/devices/src/virtio/video/decoder/backend/mod.rs b/devices/src/virtio/video/decoder/backend/mod.rs
index 7b1eacb..a415643 100644
--- a/devices/src/virtio/video/decoder/backend/mod.rs
+++ b/devices/src/virtio/video/decoder/backend/mod.rs
@@ -13,6 +13,7 @@
 };
 use base::AsRawDescriptor;
 
+#[cfg(feature = "libvda")]
 pub mod vda;
 
 /// Contains the device's state for one playback session, i.e. one stream.
diff --git a/devices/src/virtio/video/encoder/backend/mod.rs b/devices/src/virtio/video/encoder/backend/mod.rs
index acbf6b1..d4147fb 100644
--- a/devices/src/virtio/video/encoder/backend/mod.rs
+++ b/devices/src/virtio/video/encoder/backend/mod.rs
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#[cfg(feature = "libvda")]
 pub mod vda;
 
 use base::AsRawDescriptor;
diff --git a/devices/src/virtio/video/format.rs b/devices/src/virtio/video/format.rs
index 4e20815..03bf734 100644
--- a/devices/src/virtio/video/format.rs
+++ b/devices/src/virtio/video/format.rs
@@ -46,6 +46,7 @@
 impl_try_from_le32_for_enumn!(Profile, "profile");
 
 impl Profile {
+    #[cfg(any(feature = "video-encoder", feature = "libvda"))]
     pub fn to_format(&self) -> Format {
         use Profile::*;
         match self {
diff --git a/devices/src/virtio/video/mod.rs b/devices/src/virtio/video/mod.rs
index e114977..0250e00 100644
--- a/devices/src/virtio/video/mod.rs
+++ b/devices/src/virtio/video/mod.rs
@@ -39,6 +39,13 @@
 mod response;
 mod worker;
 
+#[cfg(all(feature = "video-decoder", not(feature = "libvda")))]
+compile_error!("The \"video-decoder\" feature requires \"libvda\" to also be enabled.");
+
+#[cfg(all(feature = "video-encoder", not(feature = "libvda")))]
+compile_error!("The \"video-encoder\" feature requires \"libvda\" to also be enabled.");
+
+#[cfg(feature = "libvda")]
 mod vda;
 
 use command::ReadCmdError;
@@ -121,6 +128,7 @@
 
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum VideoBackendType {
+    #[cfg(feature = "libvda")]
     Libvda,
 }
 
@@ -220,6 +228,7 @@
                 .name("virtio video decoder".to_owned())
                 .spawn(move || {
                     let device: Box<dyn Device> = match backend {
+                        #[cfg(feature = "libvda")]
                         VideoBackendType::Libvda => {
                             let vda = match decoder::backend::vda::LibvdaDecoder::new() {
                                 Ok(vda) => vda,
@@ -242,6 +251,7 @@
                 .name("virtio video encoder".to_owned())
                 .spawn(move || {
                     let device: Box<dyn Device> = match backend {
+                        #[cfg(feature = "libvda")]
                         VideoBackendType::Libvda => {
                             let vda = match encoder::backend::vda::LibvdaEncoder::new() {
                                 Ok(vda) => vda,
diff --git a/src/linux.rs b/src/linux.rs
index 947e78f..be59e2e 100644
--- a/src/linux.rs
+++ b/src/linux.rs
@@ -954,6 +954,7 @@
                 "size=67108864",
             )?;
 
+            #[cfg(feature = "libvda")]
             // Render node for libvda.
             if backend == VideoBackendType::Libvda {
                 let dev_dri_path = Path::new("/dev/dri/renderD128");
diff --git a/src/main.rs b/src/main.rs
index 7b99f96..3aaf469 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -460,10 +460,15 @@
 
 #[cfg(any(feature = "video-decoder", feature = "video-encoder"))]
 fn parse_video_options(s: Option<&str>) -> argument::Result<VideoBackendType> {
-    const VALID_VIDEO_BACKENDS: &[&str] = &["libvda"];
+    const VALID_VIDEO_BACKENDS: &[&str] = &[
+        #[cfg(feature = "libvda")]
+        "libvda",
+    ];
 
     match s {
+        #[cfg(feature = "libvda")]
         None => Ok(VideoBackendType::Libvda),
+        #[cfg(feature = "libvda")]
         Some("libvda") => Ok(VideoBackendType::Libvda),
         Some(s) => Err(argument::Error::InvalidValue {
             value: s.to_owned(),