From fb5c3aff6d87d0636dd136c8cf3b705c4d4f2f55 Mon Sep 17 00:00:00 2001 From: "Hirokazu Honda (a.k.a hiroh)" Date: Fri, 22 Nov 2024 08:00:23 -0800 Subject: [PATCH] build.rs: Detect libva version and enable any libva headers >= 1.20.0 (#21) --- README.md | 8 ++--- lib/Android.bp | 4 +++ lib/Cargo.toml | 3 +- lib/build.rs | 76 +++++++++++++++++++++++++++++++++++++++++-- lib/src/buffer/av1.rs | 28 ++++++++++++++-- 5 files changed, 108 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 691aaae..da3e73c 100644 --- a/README.md +++ b/README.md @@ -9,10 +9,10 @@ usable anywhere. The native [libva](https://github.com/intel/libva) library is required at link time, so make sure to have the `libva-dev` or equivalent package for your -distribution installed. The compatible libva version is 1.22.0. The VA-API -driver corresponding to your hardware is also required: for Intel hardware it -will be [intel-media-driver](https://github.com/intel/media-driver), whereas AMD -hardware relies on [Mesa](https://gitlab.freedesktop.org/mesa/mesa). +distribution installed. The libva version needs to be 1.20.0 or newer. The +VA-API driver corresponding to your hardware is also required: for Intel +hardware it will be [intel-media-driver](https://github.com/intel/media-driver), +whereas AMD hardware relies on [Mesa](https://gitlab.freedesktop.org/mesa/mesa). An easy way to see whether everything is in order is to run the `vainfo` utility packaged with `libva-utils` or as a standalone package in some diff --git a/lib/Android.bp b/lib/Android.bp index 88fff61..92a62cb 100644 --- a/lib/Android.bp +++ b/lib/Android.bp @@ -56,6 +56,10 @@ rust_library { "//apex_available:anyapex", ], + cfgs: [ + "libva_1_21_or_higher", + ], + vendor: true, enabled: false, arch: { diff --git a/lib/Cargo.toml b/lib/Cargo.toml index df66f93..c689909 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -16,7 +16,8 @@ log = { version = "0", features = ["release_max_level_debug"] } [build-dependencies] bindgen = "0.70.1" -pkg-config = "0.3.26" +pkg-config = "0.3.31" +regex = "1.11.1" [dev-dependencies] crc32fast = "1.2.1" diff --git a/lib/build.rs b/lib/build.rs index 160accf..7c56157 100644 --- a/lib/build.rs +++ b/lib/build.rs @@ -2,7 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +use regex::Regex; +use std::env::VarError; use std::env::{self}; +use std::fs::read_to_string; use std::path::{Path, PathBuf}; mod bindgen_gen; @@ -16,13 +19,70 @@ const CROS_LIBVA_LIB_PATH_ENV: &str = "CROS_LIBVA_LIB_PATH"; /// Wrapper file to use as input of bindgen. const WRAPPER_PATH: &str = "libva-wrapper.h"; +// Return VA_MAJOR_VERSION and VA_MINOR_VERSION from va_version.h. +fn get_va_version(va_h_path: &str) -> (u32, u32) { + let va_version_h_path = Path::new(va_h_path).join("va/va_version.h"); + assert!( + va_version_h_path.exists(), + "{} doesn't exist", + va_version_h_path.display() + ); + let header_content = read_to_string(va_version_h_path).unwrap(); + let lines = header_content.lines(); + + const VERSION_REGEX_STRINGS: [&str; 2] = [ + r"#define VA_MAJOR_VERSION\s*[0-9]+", + r"#define VA_MINOR_VERSION\s*[0-9]+", + ]; + let mut numbers: [u32; 2] = [0; 2]; + for i in 0..2 { + let re = Regex::new(VERSION_REGEX_STRINGS[i]).unwrap(); + let match_line = lines + .clone() + .filter(|&s| re.is_match(s)) + .collect::>(); + assert_eq!( + match_line.len(), + 1, + "unexpected match for {}: {:?}", + VERSION_REGEX_STRINGS[i], + match_line + ); + let number_str = Regex::new(r"[0-9]+") + .unwrap() + .find(match_line[0]) + .unwrap() + .as_str(); + numbers[i] = number_str.parse::().unwrap(); + } + + (numbers[0], numbers[1]) +} + fn main() { // Do not require dependencies when generating docs. if std::env::var("CARGO_DOC").is_ok() || std::env::var("DOCS_RS").is_ok() { return; } - let va_h_path = env::var(CROS_LIBVA_H_PATH_ENV).unwrap_or_default(); + let va_h_path = env::var(CROS_LIBVA_H_PATH_ENV) + .or_else(|e| { + if let VarError::NotPresent = e { + let libva_library = pkg_config::probe_library("libva"); + match libva_library { + Ok(_) => Ok(libva_library.unwrap().include_paths[0] + .clone() + .into_os_string() + .into_string() + .unwrap()), + Err(e) => panic!("libva is not found in system: {}", e), + } + } else { + Err(e) + } + }) + .expect("libva header location is unknown"); + let va_lib_path = env::var(CROS_LIBVA_LIB_PATH_ENV).unwrap_or_default(); // Check the path exists. if !va_h_path.is_empty() { @@ -33,11 +93,21 @@ fn main() { ); } + let (major, minor) = get_va_version(&va_h_path); + println!("libva {}.{} is used to generate bindings", major, minor); + let va_check_version = |desired_major: u32, desired_minor: u32| { + major > desired_major || (major == desired_major && minor >= desired_minor) + }; + + if va_check_version(1, 21) { + println!("cargo::rustc-cfg=libva_1_21_or_higher"); + } + if !va_lib_path.is_empty() { assert!( - Path::new(&va_h_path).exists(), + Path::new(&va_lib_path).exists(), "{} doesn't exist", - va_h_path + va_lib_path ); println!("cargo:rustc-link-arg=-Wl,-rpath={}", va_lib_path); } diff --git a/lib/src/buffer/av1.rs b/lib/src/buffer/av1.rs index 6b21c0c..a600f98 100644 --- a/lib/src/buffer/av1.rs +++ b/lib/src/buffer/av1.rs @@ -736,10 +736,11 @@ impl AV1EncPictureFlags { let disable_frame_recon = disable_frame_recon as u32; let allow_intrabc = allow_intrabc as u32; let palette_mode_enable = palette_mode_enable as u32; - let allow_screen_content_tools = allow_screen_content_tools as u32; - let force_integer_mv = force_integer_mv as u32; - let _bitfield_1 = + #[cfg(libva_1_21_or_higher)] + let _bitfield_1 = { + let allow_screen_content_tools = allow_screen_content_tools as u32; + let force_integer_mv = force_integer_mv as u32; bindings::_VAEncPictureParameterBufferAV1__bindgen_ty_1__bindgen_ty_1::new_bitfield_1( frame_type, error_resilient_mode, @@ -757,6 +758,27 @@ impl AV1EncPictureFlags { allow_screen_content_tools, force_integer_mv, Default::default(), + ) + }; + #[cfg(not(libva_1_21_or_higher))] + let _bitfield_1 = + bindings::_VAEncPictureParameterBufferAV1__bindgen_ty_1__bindgen_ty_1::new_bitfield_1( + frame_type, + error_resilient_mode, + disable_cdf_update, + use_superres, + allow_high_precision_mv, + use_ref_frame_mvs, + disable_frame_end_update_cdf, + reduced_tx_set, + enable_frame_obu, + long_term_reference, + disable_frame_recon, + allow_intrabc, + palette_mode_enable, + //allow_screen_content_tools, + //force_integer_mv, + Default::default(), ); Self(bindings::_VAEncPictureParameterBufferAV1__bindgen_ty_1 {