media: ffmpeg: generate bindings in build.rs

Generate bindings for the installed version of the ffmpeg libraries at
build time instead of checking in a static version of the bindings.

BUG=b:309563850
TEST=cargo build --features=ffmpeg

Change-Id: I38d922dd7332c4385ae6a0ae93e893538c3b1cce
Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/5027711
Reviewed-by: Dennis Kempin <denniskempin@google.com>
Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
This commit is contained in:
Daniel Verkamp 2023-11-14 15:37:42 -08:00 committed by crosvm LUCI
parent 9aab2b6647
commit 324877dbd8
9 changed files with 43 additions and 4210 deletions

1
Cargo.lock generated
View file

@ -1050,6 +1050,7 @@ name = "ffmpeg"
version = "0.1.0"
dependencies = [
"anyhow",
"bindgen 0.63.0",
"libc",
"pkg-config",
"thiserror",

View file

@ -10,4 +10,5 @@ libc = "*"
thiserror = "*"
[build-dependencies]
bindgen = "0.63"
pkg-config = "*"

View file

@ -1,14 +1,12 @@
# FFmpeg wrapper
This is a minimal FFmpeg 5.0 wrapper for use with the virtio-video device, allowing to run a virtual
video device backed by software decoding or encoding. This is useful for development and testing in
situations where no supported video acceleration is available on the host.
This is a minimal FFmpeg 5.0+ wrapper for use with the virtio-video device, allowing to run a
virtual video device backed by software decoding or encoding. This is useful for development and
testing in situations where no supported video acceleration is available on the host.
Although several FFmpeg binding crates exist, most of them are not able to link against the system
FFmpeg, and [the only one that does](https://crates.io/crates/ffmpeg-sys) is released under a
software license that makes our lawyers nervous. Also they all run bindgen at build time, which is
not possible to do under the ChromeOS build system and would require to patch the crate with fully
generated bindings.
software license that makes our lawyers nervous.
So taking this in consideration, as well as the extra work that it is to depend on external Rust
crates in ChromeOS, it is preferable to add our own simple bindings here that cover just the parts
@ -17,8 +15,7 @@ of FFmpeg that we need.
This crate has minimal dependencies ; on the FFmpeg side, it just uses `libavcodec`, `libavutil` and
`libswscale`.
The bindings can be updated using the `bindgen.sh` script. A few elements that bindgen cannot
generate because they are behind C macros are re-defined in `avutil.rs` and `error.rs`, as well as
tests to ensure their correctness.
A few elements that bindgen cannot generate because they are behind C macros are re-defined in
`avutil.rs` and `error.rs`, as well as tests to ensure their correctness.
And that's about it.

View file

@ -1,4 +0,0 @@
# These version numbers are updated by the bindgen.sh script
avcodec: 60.3.100
avutil: 58.2.100
swscale: 7.1.100

View file

@ -1,35 +0,0 @@
#!/usr/bin/env bash
# Copyright 2022 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# Regenerate ffmpeg bindgen bindings.
set -euo pipefail
cd "$(dirname "${BASH_SOURCE[0]}")/../.."
VERSIONS="media/ffmpeg/VERSIONS"
source tools/impl/bindgen-common.sh
bindgen_generate \
--allowlist-function "av_.*" \
--allowlist-function "avcodec_.*" \
--allowlist-function "sws_.*" \
--allowlist-function "av_image_.*" \
--allowlist-var "FF_PROFILE.*" \
--allowlist-var "AV_.*" \
--allowlist-var "AVERROR_.*" \
media/ffmpeg/src/bindings.h \
> media/ffmpeg/src/ffmpeg.rs
echo "# These version numbers are updated by the bindgen.sh script" >$VERSIONS
echo "avcodec: `pkg-config --modversion libavcodec`" >>$VERSIONS
echo "avutil: `pkg-config --modversion libavutil`" >>$VERSIONS
echo "swscale: `pkg-config --modversion libswscale`" >>$VERSIONS
if ! git --no-pager diff --exit-code $VERSIONS; then
echo "Libraries versions updated in the $VERSIONS file."
echo "Please check the minimum required versions in build.rs and make sure that"
echo "the major number is the same"
fi

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use std::path::PathBuf;
use pkg_config::Config;
fn main() {
@ -15,17 +17,37 @@ fn main() {
return;
}
// Match all ffmpeg 6.0 versions with which our generated bindings are compatible.
// Match all ffmpeg 6.0+ versions.
Config::new()
.range_version("60".."61")
.atleast_version("60")
.probe("libavcodec")
.unwrap();
Config::new()
.range_version("58".."59")
.atleast_version("58")
.probe("libavutil")
.unwrap();
Config::new()
.range_version("7".."8")
.atleast_version("7")
.probe("libswscale")
.unwrap();
let bindings = bindgen::Builder::default()
.header("src/bindings.h")
.allowlist_function("av_.*")
.allowlist_function("avcodec_.*")
.allowlist_function("sws_.*")
.allowlist_function("av_image_.*")
.allowlist_var("FF_PROFILE.*")
.allowlist_var("AV_.*")
.allowlist_var("AVERROR_.*")
// Skip va_list and functions that use it to avoid ABI problems on aarch64.
.blocklist_type(".*va_list.*")
.blocklist_function("av_log_.*")
.blocklist_function("av_vlog")
.generate()
.expect("failed to generate bindings");
let out_path = PathBuf::from(std::env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("writing bindings to file failed");
}

File diff suppressed because it is too large Load diff

View file

@ -9,8 +9,15 @@ mod avutil;
pub use avutil::*;
mod error;
pub use error::*;
mod ffmpeg;
use crate::ffmpeg as ffi;
mod ffi {
#![allow(clippy::missing_safety_doc)]
#![allow(clippy::upper_case_acronyms)]
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
}
pub mod swscale;
pub use ffi::AVPictureType_AV_PICTURE_TYPE_I;

View file

@ -22,7 +22,6 @@ dirs=(
io_uring
kernel_loader
kvm_sys
media/ffmpeg
media/libvda
net_sys
vfio_sys