diff --git a/ffmpeg-sys-the-third/build.rs b/ffmpeg-sys-the-third/build.rs index 6377690..57bc006 100644 --- a/ffmpeg-sys-the-third/build.rs +++ b/ffmpeg-sys-the-third/build.rs @@ -17,30 +17,53 @@ use bindgen::callbacks::{ #[derive(Debug)] struct Library { name: &'static str, - is_feature: bool, + optional: bool, features: &'static [AVFeature], + headers: &'static [AVHeader], } impl Library { - const fn new(name: &'static str, is_feature: bool, features: &'static [AVFeature]) -> Self { + const fn required( + name: &'static str, + features: &'static [AVFeature], + headers: &'static [AVHeader], + ) -> Self { Self { name, - is_feature, + optional: false, features, + headers, } } + + const fn optional( + name: &'static str, + features: &'static [AVFeature], + headers: &'static [AVHeader], + ) -> Self { + Self { + name, + optional: true, + features, + headers, + } + } + + fn enabled(&self) -> bool { + !self.optional || cargo_feature_enabled(self.name) + } } static LIBRARIES: &[Library] = &[ - Library::new("avutil", false, AVUTIL_FEATURES), - Library::new("avcodec", true, AVCODEC_FEATURES), - Library::new("avformat", true, AVFORMAT_FEATURES), - Library::new("avdevice", true, AVDEVICE_FEATURES), - Library::new("avfilter", true, AVFILTER_FEATURES), - Library::new("avresample", true, AVRESAMPLE_FEATURES), - Library::new("swscale", true, SWSCALE_FEATURES), - Library::new("swresample", true, SWRESAMPLE_FEATURES), - Library::new("postproc", true, POSTPROC_FEATURES), + Library::required("avutil", AVUTIL_FEATURES, AVUTIL_HEADERS), + Library::optional("avcodec", AVCODEC_FEATURES, AVCODEC_HEADERS), + Library::optional("avformat", AVFORMAT_FEATURES, AVFORMAT_HEADERS), + Library::optional("avdevice", AVDEVICE_FEATURES, AVDEVICE_HEADERS), + Library::optional("avfilter", AVFILTER_FEATURES, AVFILTER_HEADERS), + Library::optional("avresample", AVRESAMPLE_FEATURES, AVRESAMPLE_HEADERS), + Library::optional("swscale", SWSCALE_FEATURES, SWSCALE_HEADERS), + Library::optional("swresample", SWRESAMPLE_FEATURES, SWRESAMPLE_HEADERS), + Library::optional("postproc", POSTPROC_FEATURES, POSTPROC_HEADERS), ]; #[derive(Debug)] @@ -225,6 +248,89 @@ static SWRESAMPLE_FEATURES: &[AVFeature] = &[]; static POSTPROC_FEATURES: &[AVFeature] = &[]; +#[derive(Debug)] +struct AVHeader { + name: &'static str, +} + +impl AVHeader { + const fn new(name: &'static str) -> Self { + Self { name } + } +} + +static AVUTIL_HEADERS: &[AVHeader] = &[ + AVHeader::new("adler32.h"), + AVHeader::new("aes.h"), + AVHeader::new("audio_fifo.h"), + AVHeader::new("base64.h"), + AVHeader::new("blowfish.h"), + AVHeader::new("bprint.h"), + AVHeader::new("buffer.h"), + AVHeader::new("camellia.h"), + AVHeader::new("cast5.h"), + AVHeader::new("channel_layout.h"), + AVHeader::new("cpu.h"), + AVHeader::new("crc.h"), + AVHeader::new("dict.h"), + AVHeader::new("display.h"), + AVHeader::new("downmix_info.h"), + AVHeader::new("error.h"), + AVHeader::new("eval.h"), + AVHeader::new("fifo.h"), + AVHeader::new("file.h"), + AVHeader::new("frame.h"), + AVHeader::new("hash.h"), + AVHeader::new("hmac.h"), + AVHeader::new("hwcontext.h"), + AVHeader::new("imgutils.h"), + AVHeader::new("lfg.h"), + AVHeader::new("log.h"), + AVHeader::new("lzo.h"), + AVHeader::new("macros.h"), + AVHeader::new("mathematics.h"), + AVHeader::new("md5.h"), + AVHeader::new("mem.h"), + AVHeader::new("motion_vector.h"), + AVHeader::new("murmur3.h"), + AVHeader::new("opt.h"), + AVHeader::new("parseutils.h"), + AVHeader::new("pixdesc.h"), + AVHeader::new("pixfmt.h"), + AVHeader::new("random_seed.h"), + AVHeader::new("rational.h"), + AVHeader::new("replaygain.h"), + AVHeader::new("ripemd.h"), + AVHeader::new("samplefmt.h"), + AVHeader::new("sha.h"), + AVHeader::new("sha512.h"), + AVHeader::new("stereo3d.h"), + AVHeader::new("avstring.h"), + AVHeader::new("threadmessage.h"), + AVHeader::new("time.h"), + AVHeader::new("timecode.h"), + AVHeader::new("twofish.h"), + AVHeader::new("avutil.h"), + AVHeader::new("xtea.h"), +]; +static AVCODEC_HEADERS: &[AVHeader] = &[ + AVHeader::new("avcodec.h"), + AVHeader::new("dv_profile.h"), + AVHeader::new("avfft.h"), + AVHeader::new("vorbis_parser.h"), +]; +static AVFORMAT_HEADERS: &[AVHeader] = &[AVHeader::new("avformat.h"), AVHeader::new("avio.h")]; +static AVDEVICE_HEADERS: &[AVHeader] = &[AVHeader::new("avdevice.h")]; +static AVFILTER_HEADERS: &[AVHeader] = &[ + AVHeader::new("buffersink.h"), + AVHeader::new("buffersrc.h"), + AVHeader::new("avfilter.h"), +]; +static AVRESAMPLE_HEADERS: &[AVHeader] = &[AVHeader::new("avresample.h")]; +static SWSCALE_HEADERS: &[AVHeader] = &[AVHeader::new("swscale.h")]; +static SWRESAMPLE_HEADERS: &[AVHeader] = &[AVHeader::new("swresample.h")]; +static POSTPROC_HEADERS: &[AVHeader] = &[AVHeader::new("postprocess.h")]; + #[derive(Debug)] struct Callbacks; @@ -481,7 +587,7 @@ fn build() -> io::Result<()> { // configure building libraries based on features for lib in LIBRARIES .iter() - .filter(|lib| lib.is_feature) + .filter(|lib| lib.optional) .filter(|lib| !(lib.name == "avresample" && ffmpeg_major_version >= 5)) { configure.switch(&lib.name.to_uppercase(), lib.name); @@ -586,11 +692,7 @@ fn check_features(include_paths: &[PathBuf]) { let mut includes_code = String::new(); let mut main_code = String::new(); - for lib in LIBRARIES { - if lib.is_feature && !cargo_feature_enabled(lib.name) { - continue; - } - + for lib in LIBRARIES.iter().filter(|lib| lib.enabled()) { let header = format!("lib{}/{}.h", lib.name, lib.name); for feature in lib.features { let var = format!("FF_API_{}", feature.name); @@ -700,11 +802,7 @@ fn check_features(include_paths: &[PathBuf]) { println!("stdout of {}={}", executable.display(), stdout); - for lib in LIBRARIES { - if lib.is_feature && !cargo_feature_enabled(lib.name) { - continue; - } - + for lib in LIBRARIES.iter().filter(|lib| lib.enabled()) { for feature in lib.features { let var = format!("FF_API_{}", feature.name); let var_str = format!("[{var}]"); @@ -812,10 +910,8 @@ fn maybe_search_include(include_paths: &[PathBuf], header: &str) -> Option