From b9dca4b4f3ad83eefd7f12d20bd61af5a3d0d716 Mon Sep 17 00:00:00 2001 From: Troy Benson Date: Sat, 14 Dec 2024 04:46:45 +0000 Subject: [PATCH] image processor update --- .dockerignore | 4 + Cargo.lock | 199 ++-- Cargo.toml | 2 + apps/image-processor/Cargo.toml | 17 + apps/image-processor/Dockerfile | 48 +- crates/ffmpeg-sys/Cargo.toml | 113 ++ crates/ffmpeg-sys/README.md | 31 + crates/ffmpeg-sys/build.rs | 1384 ++++++++++++++++++++++ crates/ffmpeg-sys/channel_layout_fixed.h | 224 ++++ crates/ffmpeg-sys/src/avutil/error.rs | 69 ++ crates/ffmpeg-sys/src/avutil/macros.rs | 13 + crates/ffmpeg-sys/src/avutil/mod.rs | 14 + crates/ffmpeg-sys/src/avutil/pixfmt.rs | 236 ++++ crates/ffmpeg-sys/src/avutil/rational.rs | 35 + crates/ffmpeg-sys/src/avutil/util.rs | 8 + crates/ffmpeg-sys/src/lib.rs | 16 + crates/ffmpeg/Cargo.toml | 4 +- crates/ffmpeg/src/codec.rs | 2 +- crates/ffmpeg/src/decoder.rs | 2 +- crates/ffmpeg/src/dict.rs | 2 +- crates/ffmpeg/src/encoder.rs | 2 +- crates/ffmpeg/src/error.rs | 2 +- crates/ffmpeg/src/filter_graph.rs | 2 +- crates/ffmpeg/src/frame.rs | 2 +- crates/ffmpeg/src/io/input.rs | 2 +- crates/ffmpeg/src/io/internal.rs | 4 +- crates/ffmpeg/src/io/output.rs | 2 +- crates/ffmpeg/src/lib.rs | 2 +- crates/ffmpeg/src/limiter.rs | 2 +- crates/ffmpeg/src/log.rs | 2 +- crates/ffmpeg/src/packet.rs | 2 +- crates/ffmpeg/src/scalar.rs | 2 +- crates/ffmpeg/src/stream.rs | 2 +- crates/ffmpeg/src/utils.rs | 2 +- crates/workspace-hack/Cargo.toml | 2 - docker/ffmpeg.sh | 36 - docker/rust.sh | 9 - 37 files changed, 2312 insertions(+), 188 deletions(-) create mode 100644 crates/ffmpeg-sys/Cargo.toml create mode 100644 crates/ffmpeg-sys/README.md create mode 100644 crates/ffmpeg-sys/build.rs create mode 100644 crates/ffmpeg-sys/channel_layout_fixed.h create mode 100644 crates/ffmpeg-sys/src/avutil/error.rs create mode 100644 crates/ffmpeg-sys/src/avutil/macros.rs create mode 100644 crates/ffmpeg-sys/src/avutil/mod.rs create mode 100644 crates/ffmpeg-sys/src/avutil/pixfmt.rs create mode 100644 crates/ffmpeg-sys/src/avutil/rational.rs create mode 100644 crates/ffmpeg-sys/src/avutil/util.rs create mode 100644 crates/ffmpeg-sys/src/lib.rs delete mode 100755 docker/ffmpeg.sh delete mode 100755 docker/rust.sh diff --git a/.dockerignore b/.dockerignore index c8c6b5e7a..00e4b7f31 100644 --- a/.dockerignore +++ b/.dockerignore @@ -9,3 +9,7 @@ node_modules/ lcov.info local/ coverage/ +**/Dockerfile +**/.dockerignore +**/*.dockerfile +**/*.docker diff --git a/Cargo.lock b/Cargo.lock index 215d04507..62a912730 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -701,9 +701,9 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper 1.0.2", + "sync_wrapper", "tokio", - "tower 0.5.1", + "tower 0.5.2", "tower-layer", "tower-service", "tracing", @@ -724,7 +724,7 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 1.0.2", + "sync_wrapper", "tower-layer", "tower-service", "tracing", @@ -810,9 +810,9 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.70.1" +version = "0.71.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" +checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" dependencies = [ "bitflags 2.6.0", "cexpr", @@ -821,7 +821,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "rustc-hash 1.1.0", + "rustc-hash 2.1.0", "shlex", "syn 2.0.90", ] @@ -962,7 +962,7 @@ dependencies = [ "semver", "serde", "serde_json", - "thiserror 2.0.5", + "thiserror 2.0.7", ] [[package]] @@ -973,9 +973,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.3" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d" +checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf" dependencies = [ "jobserver", "libc", @@ -1021,9 +1021,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.38" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", @@ -1478,14 +1478,14 @@ dependencies = [ ] [[package]] -name = "derivative" -version = "2.2.0" +name = "derive-where" +version = "1.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.90", ] [[package]] @@ -1693,9 +1693,9 @@ dependencies = [ [[package]] name = "fast_image_resize" -version = "5.0.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66a61fbfc84ef99a839499cf9e5a7c2951d2da874ea00f29ee938bc50d1b396" +checksum = "ec7890c03bc18abd95e18d972f6f8f19ecc792cc01f208f060b3764a672de9e2" dependencies = [ "cfg-if", "document-features", @@ -1705,9 +1705,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fdeflate" @@ -1728,20 +1728,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "ffmpeg-sys-next" -version = "7.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc3234d0a4b2f7d083699d0860c6c9dd83713908771b60f94a96f8704adfe45" -dependencies = [ - "bindgen 0.70.1", - "cc", - "libc", - "num_cpus", - "pkg-config", - "vcpkg", -] - [[package]] name = "fiat-crypto" version = "0.2.9" @@ -2187,9 +2173,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hickory-proto" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07698b8420e2f0d6447a436ba999ec85d8fbf2a398bbd737b82cac4a2e96e512" +checksum = "447afdcdb8afb9d0a852af6dc65d9b285ce720ed7a59e42a8bf2e931c67bc1b5" dependencies = [ "async-trait", "cfg-if", @@ -2198,7 +2184,7 @@ dependencies = [ "futures-channel", "futures-io", "futures-util", - "idna 0.4.0", + "idna", "ipnet", "once_cell", "rand", @@ -2211,9 +2197,9 @@ dependencies = [ [[package]] name = "hickory-resolver" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28757f23aa75c98f254cf0405e6d8c25b831b32921b050a66692427679b1f243" +checksum = "0a2e2aba9c389ce5267d31cf1e4dace82390ae276b0b364ea55630b1fa1b44b4" dependencies = [ "cfg-if", "futures-util", @@ -2414,7 +2400,7 @@ dependencies = [ "http 1.2.0", "hyper 1.5.1", "hyper-util", - "rustls 0.23.19", + "rustls 0.23.20", "rustls-pki-types", "tokio", "tokio-rustls 0.26.1", @@ -2601,16 +2587,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" -[[package]] -name = "idna" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - [[package]] name = "idna" version = "1.0.3" @@ -2828,9 +2804,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.167" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "libdav1d-sys" @@ -3043,16 +3019,16 @@ dependencies = [ [[package]] name = "mongodb" -version = "3.1.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c857d71f918b38221baf2fdff7207fec9984b4504901544772b1edf0302d669f" +checksum = "ff1f6edf7fe8828429647a2200f684681ca6d5a33b45edc3140c81390d852301" dependencies = [ "async-trait", "base64 0.13.1", "bitflags 1.3.2", "bson", "chrono", - "derivative", + "derive-where", "derive_more 0.99.18", "futures-core", "futures-executor", @@ -3091,9 +3067,9 @@ dependencies = [ [[package]] name = "mongodb-internal-macros" -version = "3.1.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6dbc533e93429a71c44a14c04547ac783b56d3f22e6c4f12b1b994cf93844e" +checksum = "8b07bfd601af78e39384707a8e80041946c98260e3e0190e294ee7435823e6bf" dependencies = [ "proc-macro2", "quote", @@ -3515,7 +3491,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" dependencies = [ "memchr", - "thiserror 2.0.5", + "thiserror 2.0.7", "ucd-trie", ] @@ -3919,9 +3895,9 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash 2.1.0", - "rustls 0.23.19", + "rustls 0.23.20", "socket2", - "thiserror 2.0.5", + "thiserror 2.0.7", "tokio", "tracing", ] @@ -3937,11 +3913,11 @@ dependencies = [ "rand", "ring", "rustc-hash 2.1.0", - "rustls 0.23.19", + "rustls 0.23.20", "rustls-pki-types", "rustls-platform-verifier", "slab", - "thiserror 2.0.5", + "thiserror 2.0.7", "tinyvec", "tracing", "web-time", @@ -3949,9 +3925,9 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a626c6807713b15cac82a6acaccd6043c9a5408c24baae07611fec3f243da" +checksum = "52cd4b1eff68bf27940dd39811292c49e007f4d0b4c357358dc9b0197be6b527" dependencies = [ "cfg_aliases", "libc", @@ -4079,9 +4055,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags 2.6.0", ] @@ -4160,13 +4136,13 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.19", + "rustls 0.23.20", "rustls-pemfile 2.2.0", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.2", + "sync_wrapper", "tokio", "tokio-rustls 0.26.1", "tower-service", @@ -4294,15 +4270,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.41" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -4319,9 +4295,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.19" +version = "0.23.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "934b404430bb06b3fae2cba809eb45a1ab1aecd64491213d7c3301b88393f8d1" +checksum = "5065c3f250cbd332cd894be57c40fa52387247659b14a2d6041d121547903b1b" dependencies = [ "aws-lc-rs", "log", @@ -4390,9 +4366,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" dependencies = [ "web-time", ] @@ -4408,7 +4384,7 @@ dependencies = [ "jni", "log", "once_cell", - "rustls 0.23.19", + "rustls 0.23.20", "rustls-native-certs 0.7.3", "rustls-platform-verifier-android", "rustls-webpki 0.102.8", @@ -4578,7 +4554,7 @@ dependencies = [ "scuffle-http", "scuffle-pprof", "scuffle-workspace-hack", - "thiserror 2.0.5", + "thiserror 2.0.7", "tokio", "tracing", "tracing-opentelemetry", @@ -4602,13 +4578,26 @@ dependencies = [ "arc-swap", "bytes", "crossbeam-channel", - "ffmpeg-sys-next", "libc", + "scuffle-ffmpeg-sys", "scuffle-workspace-hack", "tokio", "tracing", ] +[[package]] +name = "scuffle-ffmpeg-sys" +version = "7.1.0" +dependencies = [ + "bindgen 0.71.1", + "cc", + "libc", + "num_cpus", + "pkg-config", + "scuffle-workspace-hack", + "vcpkg", +] + [[package]] name = "scuffle-h3-webtransport" version = "0.0.2" @@ -4642,14 +4631,14 @@ dependencies = [ "libc", "pin-project-lite", "quinn", - "rustls 0.23.19", + "rustls 0.23.20", "rustls-pemfile 2.2.0", "scuffle-context", "scuffle-h3-webtransport", "scuffle-workspace-hack", "smallvec", "spin", - "thiserror 2.0.5", + "thiserror 2.0.7", "tokio", "tokio-rustls 0.26.1", "tower-service", @@ -4706,6 +4695,7 @@ dependencies = [ "scuffle-bootstrap-telemetry", "scuffle-context", "scuffle-ffmpeg", + "scuffle-ffmpeg-sys", "scuffle-http", "scuffle-image-processor-proto", "scuffle-metrics", @@ -4716,7 +4706,7 @@ dependencies = [ "serde_json", "smart-default", "strfmt", - "thiserror 2.0.5", + "thiserror 2.0.7", "tokio", "tonic", "tracing", @@ -4793,7 +4783,7 @@ dependencies = [ "flate2", "pprof", "scuffle-workspace-hack", - "thiserror 2.0.5", + "thiserror 2.0.7", ] [[package]] @@ -4817,7 +4807,7 @@ dependencies = [ "scuffle-bootstrap", "scuffle-workspace-hack", "serde", - "thiserror 2.0.5", + "thiserror 2.0.7", ] [[package]] @@ -4862,7 +4852,6 @@ dependencies = [ "crossbeam-utils", "either", "fastrand", - "ffmpeg-sys-next", "futures-channel", "futures-core", "futures-executor", @@ -4894,7 +4883,7 @@ dependencies = [ "regex", "regex-automata 0.4.9", "regex-syntax 0.8.5", - "rustls 0.23.19", + "rustls 0.23.20", "rustls-webpki 0.102.8", "security-framework 2.11.1", "security-framework-sys", @@ -4907,12 +4896,12 @@ dependencies = [ "spin", "subtle", "syn 2.0.90", - "sync_wrapper 1.0.2", + "sync_wrapper", "tokio", "tokio-rustls 0.26.1", "tokio-stream", "tokio-util", - "tower 0.5.1", + "tower 0.5.2", "tracing", "tracing-core", "tracing-log", @@ -4974,18 +4963,18 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] @@ -5001,9 +4990,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", @@ -5353,12 +5342,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - [[package]] name = "sync_wrapper" version = "1.0.2" @@ -5440,11 +5423,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.5" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643caef17e3128658ff44d85923ef2d28af81bb71e0d67bbfe1d76f19a73e053" +checksum = "93605438cbd668185516ab499d589afb7ee1859ea3d5fc8f6b0755e1c7443767" dependencies = [ - "thiserror-impl 2.0.5", + "thiserror-impl 2.0.7", ] [[package]] @@ -5460,9 +5443,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.5" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "995d0bbc9995d1f19d28b7215a9352b0fc3cd3a2d2ec95c2cadc485cdedbcdde" +checksum = "e1d8749b4531af2117677a5fcd12b1348a3fe2b81e36e61ffeac5c4aa3273e36" dependencies = [ "proc-macro2", "quote", @@ -5599,7 +5582,7 @@ version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ - "rustls 0.23.19", + "rustls 0.23.20", "tokio", ] @@ -5749,14 +5732,14 @@ dependencies = [ [[package]] name = "tower" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" dependencies = [ "futures-core", "futures-util", "pin-project-lite", - "sync_wrapper 0.1.2", + "sync_wrapper", "tokio", "tower-layer", "tower-service", @@ -5954,7 +5937,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", - "idna 1.0.3", + "idna", "percent-encoding", "serde", ] diff --git a/Cargo.toml b/Cargo.toml index dc01c3230..8eed91d8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ members = [ "apps/image-processor/examples", "crates/workspace-hack", "dev-tools/xtask", + "crates/ffmpeg-sys", ] resolver = "2" @@ -48,6 +49,7 @@ scuffle-postcompile = { path = "crates/postcompile", version = "0.0.5" } scuffle-ffmpeg = { path = "crates/ffmpeg", version = "0.0.2" } scuffle-h3-webtransport = { path = "crates/h3-webtransport", version = "0.0.2" } scuffle-metrics-derive = { path = "crates/metrics/derive", version = "0.0.2" } +scuffle-ffmpeg-sys = { path = "crates/ffmpeg-sys", version = "7.1.0" } [profile.release-debug] inherits = "release" diff --git a/apps/image-processor/Cargo.toml b/apps/image-processor/Cargo.toml index 4be9e74b7..e0f5d05cf 100644 --- a/apps/image-processor/Cargo.toml +++ b/apps/image-processor/Cargo.toml @@ -58,3 +58,20 @@ scuffle-image-processor-proto = { workspace = true, features = ["server", "serde scuffle-metrics = { workspace = true } scuffle-settings = { workspace = true, features = ["full"] } scuffle-workspace-hack.workspace = true + +[dependencies.scuffle-ffmpeg-sys] +optional = true +workspace = true +features = [ + "build-lib-x264", + "build-lib-x265", + "build-lib-vpx", + "build-zlib", + "build-license-gpl", + "build-license-nonfree", + "build-license-version3", + "build-pic" +] + +[features] +build = ["scuffle-ffmpeg-sys", "scuffle-ffmpeg/build"] diff --git a/apps/image-processor/Dockerfile b/apps/image-processor/Dockerfile index 560da3a4b..3e4f811c9 100644 --- a/apps/image-processor/Dockerfile +++ b/apps/image-processor/Dockerfile @@ -1,21 +1,39 @@ -FROM bitnami/minideb as builder +FROM ubuntu:24.04 AS builder WORKDIR /tmp ENV CARGO_HOME=/usr/local/cargo \ PATH=/usr/local/cargo/bin:$PATH -RUN --mount=type=bind,src=docker/ffmpeg.sh,dst=/mount/ffmpeg.sh \ - /mount/ffmpeg.sh - -RUN --mount=type=bind,src=docker/rust.sh,dst=/mount/rust.sh \ - /mount/rust.sh - RUN apt-get update && \ - apt-get install -y --no-install-recommends \ - libclang-dev \ + apt-get install -y \ + --no-install-recommends \ + clang \ + curl \ + pkg-config \ + xz-utils \ + build-essential \ + curl \ + ca-certificates \ + meson \ + ninja-build \ + pkg-config \ + cmake \ + nasm \ + yasm \ protobuf-compiler \ - patchelf + libxv-dev \ + libc++-dev \ + libdrm2 \ + libasound2t64 \ + patchelf && \ + curl -L https://sourceforge.net/projects/avbuild/files/linux/ffmpeg-7.1-linux-clang-default.tar.xz/download -o ffmpeg.tar.xz && \ + tar -xvf ffmpeg.tar.xz && \ + mv ffmpeg-7.1-linux-clang-default/include/* /usr/include && \ + mv ffmpeg-7.1-linux-clang-default/lib/amd64/* /usr/local/lib && \ + mv ffmpeg-7.1-linux-clang-default/bin/amd64/* /usr/local/bin && \ + ldconfig && \ + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y COPY . . @@ -26,9 +44,9 @@ RUN cargo build --profile ${PROFILE} --bin scuffle-image-processor -p scuffle-im RUN mkdir /out && \ mv target/${PROFILE}/scuffle-image-processor /out/image-processor && \ ldd /out/image-processor | grep -o '/[^ ]*' | xargs -I '{}' cp {} /out && \ - patchelf --set-rpath '$ORIGIN' /out/image-processor + patchelf --set-rpath '$ORIGIN' /out/* -FROM gcr.io/distroless/base-nossl-debian12 +FROM ubuntu:24.04 LABEL org.opencontainers.image.source=https://github.com/scufflecloud/scuffle LABEL org.opencontainers.image.description="Scuffle Image Processor" @@ -36,7 +54,11 @@ LABEL org.opencontainers.image.licenses=AGPL-3.0 WORKDIR /app -ENV LD_LIBRARY_PATH=/app:$LD_LIBRARY_PATH +RUN apt-get update && \ + apt-get install -y --no-install-recommends \ + ca-certificates && \ + update-ca-certificates && \ + rm -rf /var/lib/apt/lists/* COPY --from=builder /out /app diff --git a/crates/ffmpeg-sys/Cargo.toml b/crates/ffmpeg-sys/Cargo.toml new file mode 100644 index 000000000..9c3cc7d1a --- /dev/null +++ b/crates/ffmpeg-sys/Cargo.toml @@ -0,0 +1,113 @@ +[package] +name = "scuffle-ffmpeg-sys" +version = "7.1.0" +build = "build.rs" +links = "ffmpeg" +edition = "2021" + +authors = ["meh. ", "Zhiming Wang "] +license = "WTFPL" + +description = "FFI bindings to FFmpeg" +repository = "https://github.com/zmwangx/rust-ffmpeg-sys" +keywords = ["audio", "video"] + +[lib] +# Disable doctests as a workaround for https://github.com/rust-lang/rust-bindgen/issues/1313 +doctest = false + +[dependencies] +libc = "0.2" +scuffle-workspace-hack.workspace = true + +[build-dependencies] +num_cpus = "1.16" +cc = "1.1" +pkg-config = "0.3" +bindgen = { version = "0.71.1", default-features = false, features = ["runtime"] } + +[target.'cfg(target_env = "msvc")'.build-dependencies] +vcpkg = "0.2" + +[features] +default = ["avcodec", "avdevice", "avfilter", "avformat", "swresample", "swscale"] + +static = [] +build = ["static"] + +# mark enums in generated bindings as #[non_exhaustive] +non-exhaustive-enums = [] + +# licensing +build-license-gpl = ["build"] +build-license-nonfree = ["build"] +build-license-version3 = ["build"] + +# misc +build-drm = ["build"] +build-nvenc = ["build"] +build-pic = ["build"] +build-zlib = ["build"] + +# ssl +build-lib-gnutls = ["build"] +build-lib-openssl = ["build"] + +# filters +build-lib-fontconfig = ["build"] +build-lib-frei0r = ["build"] +build-lib-ladspa = ["build"] +build-lib-ass = ["build"] +build-lib-freetype = ["build"] +build-lib-freebidi = ["build"] +build-lib-opencv = ["build"] +build-lib-vmaf = ["build"] + +# encoders/decoders +build-lib-aacplus = ["build"] +build-lib-celt = ["build"] +build-lib-dav1d = ["build"] +build-lib-dcadec = ["build"] +build-lib-faac = ["build"] +build-lib-fdk-aac = ["build"] +build-lib-gsm = ["build"] +build-lib-ilbc = ["build"] +build-lib-kvazaar = ["build"] +build-lib-mp3lame = ["build"] +build-lib-opencore-amrnb = ["build"] +build-lib-opencore-amrwb = ["build"] +build-lib-openh264 = ["build"] +build-lib-openjpeg = ["build"] +build-lib-opus = ["build"] +build-lib-schroedinger = ["build"] +build-lib-shine = ["build"] +build-lib-snappy = ["build"] +build-lib-speex = ["build"] +build-lib-stagefright-h264 = ["build"] +build-lib-theora = ["build"] +build-lib-twolame = ["build"] +build-lib-utvideo = ["build"] +build-lib-vo-aacenc = ["build"] +build-lib-vo-amrwbenc = ["build"] +build-lib-vorbis = ["build"] +build-lib-vpx = ["build"] +build-lib-wavpack = ["build"] +build-lib-webp = ["build"] +build-lib-x264 = ["build"] +build-lib-x265 = ["build"] +build-lib-avs = ["build"] +build-lib-xvid = ["build"] + +# protocols +build-lib-smbclient = ["build"] +build-lib-ssh = ["build"] + +# components +avcodec = [] +avdevice = ["avformat"] +avfilter = [] +avformat = ["avcodec"] +avresample = [] +postproc = [] +swresample = [] +swscale = [] diff --git a/crates/ffmpeg-sys/README.md b/crates/ffmpeg-sys/README.md new file mode 100644 index 000000000..9c7f02997 --- /dev/null +++ b/crates/ffmpeg-sys/README.md @@ -0,0 +1,31 @@ +[![ffmpeg-sys-next on crates.io](https://img.shields.io/crates/v/ffmpeg-sys-next?cacheSeconds=3600)](https://crates.io/crates/ffmpeg-sys-next) +[![build](https://github.com/zmwangx/rust-ffmpeg-sys/workflows/build/badge.svg)](https://github.com/zmwangx/rust-ffmpeg-sys/actions) + +This is a fork of the abandoned [ffmpeg-sys](https://github.com/meh/rust-ffmpeg-sys) crate. You can find this crate as [ffmpeg-sys-next](https://crates.io/crates/ffmpeg-sys-next) on crates.io. + +This crate contains low level bindings to FFmpeg. You're probably interested in the high level bindings instead: [ffmpeg-next](https://github.com/zmwangx/rust-ffmpeg). + +A word on versioning: major and minor versions track major and minor versions of FFmpeg, e.g. 4.2.x of this crate has been updated to support the 4.2.x series of FFmpeg. Patch level is reserved for bug fixes of this crate and does not track FFmpeg patch versions. + +## Feature flags + +In addition to feature flags declared in `Cargo.toml`, this crate performs various compile-time version and feature detections and exposes the results in additional flags. These flags are briefly documented below; run `cargo build -vv` to view more details. + +- `ffmpeg__` flags (new in v4.3.2), e.g. `ffmpeg_4_4`, indicating the FFmpeg installation being compiled against is at least version `.`. Currently available: + + - `ffmpeg_3_0` + - `ffmpeg_3_1` + - `ffmpeg_3_2` + - `ffmpeg_3_3` + - `ffmpeg_3_1` + - `ffmpeg_4_0` + - `ffmpeg_4_1` + - `ffmpeg_4_2` + - `ffmpeg_4_3` + - `ffmpeg_4_4` + +- `avcodec_version_greater_than__` (new in v4.3.2), e.g., `avcodec_version_greater_than_58_90`. The name should be self-explanatory. + +- `ff_api_`, e.g. `ff_api_vaapi`, corresponding to whether their respective uppercase deprecation guards evaluate to true. + +- `ff_api__is_defined`, e.g. `ff_api_vappi_is_defined`, similar to above except these are enabled as long as the corresponding deprecation guards are defined. diff --git a/crates/ffmpeg-sys/build.rs b/crates/ffmpeg-sys/build.rs new file mode 100644 index 000000000..25ae4a7c3 --- /dev/null +++ b/crates/ffmpeg-sys/build.rs @@ -0,0 +1,1384 @@ +extern crate bindgen; +extern crate cc; +extern crate num_cpus; +extern crate pkg_config; + +use std::env; +use std::fmt::Write as FmtWrite; +use std::fs::{self, File}; +use std::io::{self, BufRead, BufReader, Write}; +use std::path::PathBuf; +use std::process::Command; +use std::str; + +use bindgen::callbacks::{ + EnumVariantCustomBehavior, EnumVariantValue, IntKind, MacroParsingBehavior, ParseCallbacks, +}; + +#[derive(Debug)] +struct Library { + name: &'static str, + is_feature: bool, +} + +impl Library { + fn feature_name(&self) -> Option { + if self.is_feature { + Some("CARGO_FEATURE_".to_string() + &self.name.to_uppercase()) + } else { + None + } + } +} + +static LIBRARIES: &[Library] = &[ + Library { + name: "avcodec", + is_feature: true, + }, + Library { + name: "avdevice", + is_feature: true, + }, + Library { + name: "avfilter", + is_feature: true, + }, + Library { + name: "avformat", + is_feature: true, + }, + Library { + name: "avresample", + is_feature: true, + }, + Library { + name: "avutil", + is_feature: false, + }, + Library { + name: "postproc", + is_feature: true, + }, + Library { + name: "swresample", + is_feature: true, + }, + Library { + name: "swscale", + is_feature: true, + }, +]; + +#[derive(Debug)] +struct Callbacks; + +impl ParseCallbacks for Callbacks { + fn int_macro(&self, _name: &str, value: i64) -> Option { + let ch_layout_prefix = "AV_CH_"; + let codec_cap_prefix = "AV_CODEC_CAP_"; + let codec_flag_prefix = "AV_CODEC_FLAG_"; + let error_max_size = "AV_ERROR_MAX_STRING_SIZE"; + + if _name.starts_with(ch_layout_prefix) { + Some(IntKind::ULongLong) + } else if value >= i32::MIN as i64 + && value <= i32::MAX as i64 + && (_name.starts_with(codec_cap_prefix) || _name.starts_with(codec_flag_prefix)) + { + Some(IntKind::UInt) + } else if _name == error_max_size { + Some(IntKind::Custom { + name: "usize", + is_signed: false, + }) + } else if value >= i32::MIN as i64 && value <= i32::MAX as i64 { + Some(IntKind::Int) + } else { + None + } + } + + fn enum_variant_behavior( + &self, + _enum_name: Option<&str>, + original_variant_name: &str, + _variant_value: EnumVariantValue, + ) -> Option { + let dummy_codec_id_prefix = "AV_CODEC_ID_FIRST_"; + if original_variant_name.starts_with(dummy_codec_id_prefix) { + Some(EnumVariantCustomBehavior::Constify) + } else { + None + } + } + + // https://github.com/rust-lang/rust-bindgen/issues/687#issuecomment-388277405 + fn will_parse_macro(&self, name: &str) -> MacroParsingBehavior { + use MacroParsingBehavior::*; + + match name { + "FP_INFINITE" => Ignore, + "FP_NAN" => Ignore, + "FP_NORMAL" => Ignore, + "FP_SUBNORMAL" => Ignore, + "FP_ZERO" => Ignore, + _ => Default, + } + } +} + +fn version() -> String { + let major: u8 = env::var("CARGO_PKG_VERSION_MAJOR") + .unwrap() + .parse() + .unwrap(); + let minor: u8 = env::var("CARGO_PKG_VERSION_MINOR") + .unwrap() + .parse() + .unwrap(); + + format!("{}.{}", major, minor) +} + +fn output() -> PathBuf { + PathBuf::from(env::var("OUT_DIR").unwrap()) +} + +fn source() -> PathBuf { + output().join(format!("ffmpeg-{}", version())) +} + +fn search() -> PathBuf { + let mut absolute = env::current_dir().unwrap(); + absolute.push(output()); + absolute.push("dist"); + + absolute +} + +fn fetch() -> io::Result<()> { + let output_base_path = output(); + let clone_dest_dir = format!("ffmpeg-{}", version()); + let _ = std::fs::remove_dir_all(output_base_path.join(&clone_dest_dir)); + let status = Command::new("git") + .current_dir(&output_base_path) + .arg("clone") + .arg("--depth=1") + .arg("-b") + .arg(format!("release/{}", version())) + .arg("https://github.com/FFmpeg/FFmpeg") + .arg(&clone_dest_dir) + .status()?; + + if status.success() { + Ok(()) + } else { + Err(io::Error::new(io::ErrorKind::Other, "fetch failed")) + } +} + +fn switch(configure: &mut Command, feature: &str, name: &str) { + let arg = if env::var("CARGO_FEATURE_".to_string() + feature).is_ok() { + "--enable-" + } else { + "--disable-" + }; + configure.arg(arg.to_string() + name); +} + +fn get_ffmpet_target_os() -> String { + let cargo_target_os = env::var("CARGO_CFG_TARGET_OS").unwrap(); + match cargo_target_os.as_str() { + "ios" => "darwin".to_string(), + _ => cargo_target_os, + } +} + +fn build() -> io::Result<()> { + let source_dir = source(); + + // Command's path is not relative to command's current_dir + let configure_path = source_dir.join("configure"); + assert!(configure_path.exists()); + let mut configure = Command::new(&configure_path); + configure.current_dir(&source_dir); + + configure.arg(format!("--prefix={}", search().to_string_lossy())); + + let target = env::var("TARGET").unwrap(); + let host = env::var("HOST").unwrap(); + if target != host { + configure.arg("--enable-cross-compile"); + + // Rust targets are subtly different than naming scheme for compiler prefixes. + // The cc crate has the messy logic of guessing a working prefix, + // and this is a messy way of reusing that logic. + let cc = cc::Build::new(); + + // Apple-clang needs this, -arch is not enough. + let target_flag = format!("--target={}", target); + if cc.is_flag_supported(&target_flag).unwrap_or(false) { + configure.arg(format!("--extra-cflags={}", target_flag)); + configure.arg(format!("--extra-ldflags={}", target_flag)); + } + + let compiler = cc.get_compiler(); + let compiler = compiler.path().file_stem().unwrap().to_str().unwrap(); + if let Some(suffix_pos) = compiler.rfind('-') { + let prefix = compiler[0..suffix_pos].trim_end_matches("-wr"); // "wr-c++" compiler + configure.arg(format!("--cross-prefix={}-", prefix)); + } + configure.arg(format!( + "--arch={}", + env::var("CARGO_CFG_TARGET_ARCH").unwrap() + )); + configure.arg(format!("--target_os={}", get_ffmpet_target_os())); + } + + // control debug build + if env::var("DEBUG").is_ok() { + configure.arg("--enable-debug"); + configure.arg("--disable-stripping"); + } else { + configure.arg("--disable-debug"); + configure.arg("--enable-stripping"); + } + + // make it static + configure.arg("--enable-static"); + configure.arg("--disable-shared"); + configure.arg("--enable-pthreads"); + + configure.arg("--enable-pic"); + + // stop autodetected libraries enabling themselves, causing linking errors + configure.arg("--disable-autodetect"); + + // do not build programs since we don't need them + configure.arg("--disable-programs"); + + macro_rules! enable { + ($conf:expr, $feat:expr, $name:expr) => { + if env::var(concat!("CARGO_FEATURE_", $feat)).is_ok() { + $conf.arg(concat!("--enable-", $name)); + } + }; + } + + // macro_rules! disable { + // ($conf:expr, $feat:expr, $name:expr) => ( + // if env::var(concat!("CARGO_FEATURE_", $feat)).is_err() { + // $conf.arg(concat!("--disable-", $name)); + // } + // ) + // } + + // the binary using ffmpeg-sys must comply with GPL + switch(&mut configure, "BUILD_LICENSE_GPL", "gpl"); + + // the binary using ffmpeg-sys must comply with (L)GPLv3 + switch(&mut configure, "BUILD_LICENSE_VERSION3", "version3"); + + // the binary using ffmpeg-sys cannot be redistributed + switch(&mut configure, "BUILD_LICENSE_NONFREE", "nonfree"); + + let ffmpeg_major_version: u32 = env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap(); + + // configure building libraries based on features + for lib in LIBRARIES + .iter() + .filter(|lib| lib.is_feature) + .filter(|lib| !(lib.name == "avresample" && ffmpeg_major_version >= 5)) + { + switch(&mut configure, &lib.name.to_uppercase(), lib.name); + } + + // configure external SSL libraries + enable!(configure, "BUILD_LIB_GNUTLS", "gnutls"); + enable!(configure, "BUILD_LIB_OPENSSL", "openssl"); + + // configure external filters + enable!(configure, "BUILD_LIB_FONTCONFIG", "fontconfig"); + enable!(configure, "BUILD_LIB_FREI0R", "frei0r"); + enable!(configure, "BUILD_LIB_LADSPA", "ladspa"); + enable!(configure, "BUILD_LIB_ASS", "libass"); + enable!(configure, "BUILD_LIB_FREETYPE", "libfreetype"); + enable!(configure, "BUILD_LIB_FRIBIDI", "libfribidi"); + enable!(configure, "BUILD_LIB_OPENCV", "libopencv"); + enable!(configure, "BUILD_LIB_VMAF", "libvmaf"); + + // configure external encoders/decoders + enable!(configure, "BUILD_LIB_AACPLUS", "libaacplus"); + enable!(configure, "BUILD_LIB_CELT", "libcelt"); + enable!(configure, "BUILD_LIB_DCADEC", "libdcadec"); + enable!(configure, "BUILD_LIB_DAV1D", "libdav1d"); + enable!(configure, "BUILD_LIB_FAAC", "libfaac"); + enable!(configure, "BUILD_LIB_FDK_AAC", "libfdk-aac"); + enable!(configure, "BUILD_LIB_GSM", "libgsm"); + enable!(configure, "BUILD_LIB_ILBC", "libilbc"); + enable!(configure, "BUILD_LIB_VAZAAR", "libvazaar"); + enable!(configure, "BUILD_LIB_MP3LAME", "libmp3lame"); + enable!(configure, "BUILD_LIB_OPENCORE_AMRNB", "libopencore-amrnb"); + enable!(configure, "BUILD_LIB_OPENCORE_AMRWB", "libopencore-amrwb"); + enable!(configure, "BUILD_LIB_OPENH264", "libopenh264"); + enable!(configure, "BUILD_LIB_OPENH265", "libopenh265"); + enable!(configure, "BUILD_LIB_OPENJPEG", "libopenjpeg"); + enable!(configure, "BUILD_LIB_OPUS", "libopus"); + enable!(configure, "BUILD_LIB_SCHROEDINGER", "libschroedinger"); + enable!(configure, "BUILD_LIB_SHINE", "libshine"); + enable!(configure, "BUILD_LIB_SNAPPY", "libsnappy"); + enable!(configure, "BUILD_LIB_SPEEX", "libspeex"); + enable!( + configure, + "BUILD_LIB_STAGEFRIGHT_H264", + "libstagefright-h264" + ); + enable!(configure, "BUILD_LIB_THEORA", "libtheora"); + enable!(configure, "BUILD_LIB_TWOLAME", "libtwolame"); + enable!(configure, "BUILD_LIB_UTVIDEO", "libutvideo"); + enable!(configure, "BUILD_LIB_VO_AACENC", "libvo-aacenc"); + enable!(configure, "BUILD_LIB_VO_AMRWBENC", "libvo-amrwbenc"); + enable!(configure, "BUILD_LIB_VORBIS", "libvorbis"); + enable!(configure, "BUILD_LIB_VPX", "libvpx"); + enable!(configure, "BUILD_LIB_WAVPACK", "libwavpack"); + enable!(configure, "BUILD_LIB_WEBP", "libwebp"); + enable!(configure, "BUILD_LIB_X264", "libx264"); + enable!(configure, "BUILD_LIB_X265", "libx265"); + enable!(configure, "BUILD_LIB_AVS", "libavs"); + enable!(configure, "BUILD_LIB_XVID", "libxvid"); + + // other external libraries + enable!(configure, "BUILD_LIB_DRM", "libdrm"); + enable!(configure, "BUILD_NVENC", "nvenc"); + + // configure external protocols + enable!(configure, "BUILD_LIB_SMBCLIENT", "libsmbclient"); + enable!(configure, "BUILD_LIB_SSH", "libssh"); + + // configure misc build options + enable!(configure, "BUILD_PIC", "pic"); + + println!("cargo-rerun-if-env-changed=FFMPEG_SYS_NEXT_BUILD_EXTRA_ARGS"); + + if let Ok(extra_args) = env::var("FFMPEG_SYS_NEXT_BUILD_EXTRA_ARGS") { + for arg in extra_args.split_whitespace() { + configure.arg(arg); + } + } + + // run ./configure + let output = configure + .output() + .unwrap_or_else(|_| panic!("{:?} failed", configure)); + if !output.status.success() { + println!("configure: {}", String::from_utf8_lossy(&output.stdout)); + + return Err(io::Error::new( + io::ErrorKind::Other, + format!( + "configure failed {}", + String::from_utf8_lossy(&output.stderr) + ), + )); + } + + // run make + if !Command::new("make") + .arg("-j") + .arg(num_cpus::get().to_string()) + .current_dir(source()) + .status()? + .success() + { + return Err(io::Error::new(io::ErrorKind::Other, "make failed")); + } + + // run make install + if !Command::new("make") + .current_dir(source()) + .arg("install") + .status()? + .success() + { + return Err(io::Error::new(io::ErrorKind::Other, "make install failed")); + } + + Ok(()) +} + +#[cfg(not(target_env = "msvc"))] +fn try_vcpkg(_statik: bool) -> Option> { + None +} + +#[cfg(target_env = "msvc")] +fn try_vcpkg(statik: bool) -> Option> { + if !statik { + env::set_var("VCPKGRS_DYNAMIC", "1"); + } + + vcpkg::find_package("ffmpeg") + .map_err(|e| { + println!("Could not find ffmpeg with vcpkg: {}", e); + }) + .map(|library| library.include_paths) + .ok() +} + +fn check_features( + include_paths: Vec, + infos: &[(&'static str, Option<&'static str>, &'static str)], +) { + let mut includes_code = String::new(); + let mut main_code = String::new(); + + for &(header, feature, var) in infos { + if let Some(feature) = feature { + if env::var(format!("CARGO_FEATURE_{}", feature.to_uppercase())).is_err() { + continue; + } + } + + let include = format!("#include <{}>", header); + if !includes_code.contains(&include) { + includes_code.push_str(&include); + includes_code.push('\n'); + } + let _ = write!( + includes_code, + r#" + #ifndef {var}_is_defined + #ifndef {var} + #define {var} 0 + #define {var}_is_defined 0 + #else + #define {var}_is_defined 1 + #endif + #endif + "#, + var = var + ); + + let _ = write!( + main_code, + r#"printf("[{var}]%d%d\n", {var}, {var}_is_defined); + "#, + var = var + ); + } + + let version_check_info = [("avcodec", 56, 62, 0, 108)]; + for &(lib, begin_version_major, end_version_major, begin_version_minor, end_version_minor) in + version_check_info.iter() + { + for version_major in begin_version_major..end_version_major { + for version_minor in begin_version_minor..end_version_minor { + let _ = write!( + main_code, + r#"printf("[{lib}_version_greater_than_{version_major}_{version_minor}]%d\n", LIB{lib_uppercase}_VERSION_MAJOR > {version_major} || (LIB{lib_uppercase}_VERSION_MAJOR == {version_major} && LIB{lib_uppercase}_VERSION_MINOR > {version_minor})); + "#, + lib = lib, + lib_uppercase = lib.to_uppercase(), + version_major = version_major, + version_minor = version_minor + ); + } + } + } + + let out_dir = output(); + + write!( + File::create(out_dir.join("check.c")).expect("Failed to create file"), + r#" + #include + {includes_code} + + int main() + {{ + {main_code} + return 0; + }} + "#, + includes_code = includes_code, + main_code = main_code + ) + .expect("Write failed"); + + let executable = out_dir.join(if cfg!(windows) { "check.exe" } else { "check" }); + let mut compiler = cc::Build::new() + .target(&env::var("HOST").unwrap()) // don't cross-compile this + .get_compiler() + .to_command(); + + for dir in include_paths { + compiler.arg("-I"); + compiler.arg(dir.to_string_lossy().into_owned()); + } + if !compiler + .current_dir(&out_dir) + .arg("-o") + .arg(&executable) + .arg("check.c") + .status() + .expect("Command failed") + .success() + { + panic!("Compile failed"); + } + + let check_output = Command::new(out_dir.join(&executable)) + .current_dir(&out_dir) + .output() + .expect("Check failed"); + if !check_output.status.success() { + panic!( + "{} failed: {}\n{}", + executable.display(), + String::from_utf8_lossy(&check_output.stdout), + String::from_utf8_lossy(&check_output.stderr) + ); + } + + let stdout = str::from_utf8(&check_output.stdout).unwrap(); + + println!("stdout of {}={}", executable.display(), stdout); + + for &(_, feature, var) in infos { + if let Some(feature) = feature { + if env::var(format!("CARGO_FEATURE_{}", feature.to_uppercase())).is_err() { + continue; + } + } + // Here so the features are listed for rust-ffmpeg at build time. Does + // NOT represent activated features, just features that exist (hence the + // lack of "=true" at the end) + println!(r#"cargo:{}="#, var); + + let var_str = format!("[{var}]", var = var); + let pos = var_str.len() + + stdout + .find(&var_str) + .unwrap_or_else(|| panic!("Variable '{}' not found in stdout output", var_str)); + if &stdout[pos..pos + 1] == "1" { + println!(r#"cargo:rustc-cfg=feature="{}""#, var.to_lowercase()); + println!(r#"cargo:{}=true"#, var.to_lowercase()); + } + + // Also find out if defined or not (useful for cases where only the definition of a macro + // can be used as distinction) + if &stdout[pos + 1..pos + 2] == "1" { + println!( + r#"cargo:rustc-cfg=feature="{}_is_defined""#, + var.to_lowercase() + ); + println!(r#"cargo:{}_is_defined=true"#, var.to_lowercase()); + } + } + + for &(lib, begin_version_major, end_version_major, begin_version_minor, end_version_minor) in + version_check_info.iter() + { + for version_major in begin_version_major..end_version_major { + for version_minor in begin_version_minor..end_version_minor { + let search_str = format!( + "[{lib}_version_greater_than_{version_major}_{version_minor}]", + version_major = version_major, + version_minor = version_minor, + lib = lib + ); + let pos = stdout + .find(&search_str) + .expect("Variable not found in output") + + search_str.len(); + + if &stdout[pos..pos + 1] == "1" { + println!( + r#"cargo:rustc-cfg=feature="{}""#, + &search_str[1..(search_str.len() - 1)] + ); + println!(r#"cargo:{}=true"#, &search_str[1..(search_str.len() - 1)]); + } + } + } + } + + let ffmpeg_lavc_versions = [ + ("ffmpeg_3_0", 57, 24), + ("ffmpeg_3_1", 57, 48), + ("ffmpeg_3_2", 57, 64), + ("ffmpeg_3_3", 57, 89), + ("ffmpeg_3_1", 57, 107), + ("ffmpeg_4_0", 58, 18), + ("ffmpeg_4_1", 58, 35), + ("ffmpeg_4_2", 58, 54), + ("ffmpeg_4_3", 58, 91), + ("ffmpeg_4_4", 58, 100), + ("ffmpeg_5_0", 59, 18), + ("ffmpeg_5_1", 59, 37), + ("ffmpeg_6_0", 60, 3), + ("ffmpeg_6_1", 60, 31), + ("ffmpeg_7_0", 61, 3), + ("ffmpeg_7_1", 61, 19), + ]; + for &(ffmpeg_version_flag, lavc_version_major, lavc_version_minor) in + ffmpeg_lavc_versions.iter() + { + let search_str = format!( + "[avcodec_version_greater_than_{lavc_version_major}_{lavc_version_minor}]", + lavc_version_major = lavc_version_major, + lavc_version_minor = lavc_version_minor - 1 + ); + let pos = stdout + .find(&search_str) + .expect("Variable not found in output") + + search_str.len(); + if &stdout[pos..pos + 1] == "1" { + println!(r#"cargo:rustc-cfg=feature="{}""#, ffmpeg_version_flag); + println!(r#"cargo:{}=true"#, ffmpeg_version_flag); + } else { + println!(r#"cargo:{}="#, ffmpeg_version_flag); + } + } +} + +fn search_include(include_paths: &[PathBuf], header: &str) -> String { + for dir in include_paths { + let include = dir.join(header); + if fs::metadata(&include).is_ok() { + return include.as_path().to_str().unwrap().to_string(); + } + } + format!("/usr/include/{}", header) +} + +fn maybe_search_include(include_paths: &[PathBuf], header: &str) -> Option { + let path = search_include(include_paths, header); + if fs::metadata(&path).is_ok() { + Some(path) + } else { + None + } +} + +fn link_to_libraries(statik: bool) { + let ffmpeg_ty = if statik { "static" } else { "dylib" }; + for lib in LIBRARIES { + let feat_is_enabled = lib.feature_name().and_then(|f| env::var(f).ok()).is_some(); + if !lib.is_feature || feat_is_enabled { + println!("cargo:rustc-link-lib={}={}", ffmpeg_ty, lib.name); + } + } + if env::var("CARGO_FEATURE_BUILD_ZLIB").is_ok() && cfg!(target_os = "linux") { + println!("cargo:rustc-link-lib=z"); + } +} + +fn main() { + let statik = env::var("CARGO_FEATURE_STATIC").is_ok(); + let ffmpeg_major_version: u32 = env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap(); + + let include_paths: Vec = if env::var("CARGO_FEATURE_BUILD").is_ok() { + println!( + "cargo:rustc-link-search=native={}", + search().join("lib").to_string_lossy() + ); + link_to_libraries(statik); + if fs::metadata(search().join("lib").join("libavutil.a")).is_err() { + fs::create_dir_all(output()).expect("failed to create build directory"); + fetch().unwrap(); + build().unwrap(); + } + + // Check additional required libraries. + { + let config_mak = source().join("ffbuild/config.mak"); + let file = File::open(config_mak).unwrap(); + let reader = BufReader::new(file); + let extra_linker_args = reader + .lines() + .filter_map(|line| { + let line = line.as_ref().ok()?; + + if line.starts_with("EXTRALIBS") { + Some( + line.split('=') + .last() + .unwrap() + .split(' ') + .map(|s| s.to_string()) + .collect::>(), + ) + } else { + None + } + }) + .flatten() + .collect::>(); + + extra_linker_args + .iter() + .filter(|flag| flag.starts_with("-l")) + .map(|lib| &lib[2..]) + .for_each(|lib| println!("cargo:rustc-link-lib={}", lib)); + + extra_linker_args + .iter() + .filter(|v| v.starts_with("-L")) + .map(|flag| { + let path = &flag[2..]; + if path.starts_with('/') { + PathBuf::from(path) + } else { + source().join(path) + } + }) + .for_each(|lib_search_path| { + println!( + "cargo:rustc-link-search=native={}", + lib_search_path.to_str().unwrap() + ); + }) + } + + vec![search().join("include")] + } + // Use prebuilt library + else if let Ok(ffmpeg_dir) = env::var("FFMPEG_DIR") { + let ffmpeg_dir = PathBuf::from(ffmpeg_dir); + if ffmpeg_dir.join("lib/amd64").exists() + && env::var("CARGO_CFG_TARGET_ARCH").as_deref() == Ok("x86_64") + { + println!( + "cargo:rustc-link-search=native={}", + ffmpeg_dir.join("lib/amd64").to_string_lossy() + ); + } else if ffmpeg_dir.join("lib/armhf").exists() + && env::var("CARGO_CFG_TARGET_ARCH").as_deref() == Ok("arm") + { + println!( + "cargo:rustc-link-search=native={}", + ffmpeg_dir.join("lib/armhf").to_string_lossy() + ); + } else if ffmpeg_dir.join("lib/arm64").exists() + && env::var("CARGO_CFG_TARGET_ARCH").as_deref() == Ok("aarch64") + { + println!( + "cargo:rustc-link-search=native={}", + ffmpeg_dir.join("lib/arm64").to_string_lossy() + ); + } else { + println!( + "cargo:rustc-link-search=native={}", + ffmpeg_dir.join("lib").to_string_lossy() + ); + } + link_to_libraries(statik); + vec![ffmpeg_dir.join("include")] + } else if let Some(paths) = try_vcpkg(statik) { + // vcpkg doesn't detect the "system" dependencies + if statik { + if cfg!(feature = "avcodec") || cfg!(feature = "avdevice") { + println!("cargo:rustc-link-lib=ole32"); + } + + if cfg!(feature = "avformat") { + println!("cargo:rustc-link-lib=secur32"); + println!("cargo:rustc-link-lib=ws2_32"); + } + + // avutil depdendencies + println!("cargo:rustc-link-lib=bcrypt"); + println!("cargo:rustc-link-lib=user32"); + } + + paths + } + // Fallback to pkg-config + else { + pkg_config::Config::new() + .statik(statik) + .probe("libavutil") + .unwrap(); + + let mut libs = vec![ + ("libavformat", "AVFORMAT"), + ("libavfilter", "AVFILTER"), + ("libavdevice", "AVDEVICE"), + ("libswscale", "SWSCALE"), + ("libswresample", "SWRESAMPLE"), + ]; + if ffmpeg_major_version < 5 { + libs.push(("libavresample", "AVRESAMPLE")); + } + + for (lib_name, env_variable_name) in libs.iter() { + if env::var(format!("CARGO_FEATURE_{}", env_variable_name)).is_ok() { + pkg_config::Config::new() + .statik(statik) + .probe(lib_name) + .unwrap(); + } + } + + pkg_config::Config::new() + .statik(statik) + .probe("libavcodec") + .unwrap() + .include_paths + }; + + if statik && cfg!(target_os = "macos") { + let frameworks = vec![ + "AppKit", + "AudioToolbox", + "AVFoundation", + "CoreFoundation", + "CoreGraphics", + "CoreMedia", + "CoreServices", + "CoreVideo", + "Foundation", + "OpenCL", + "OpenGL", + "QTKit", + "QuartzCore", + "Security", + "VideoDecodeAcceleration", + "VideoToolbox", + ]; + for f in frameworks { + println!("cargo:rustc-link-lib=framework={}", f); + } + } + + check_features( + include_paths.clone(), + &[ + ("libavutil/avutil.h", None, "FF_API_OLD_AVOPTIONS"), + ("libavutil/avutil.h", None, "FF_API_PIX_FMT"), + ("libavutil/avutil.h", None, "FF_API_CONTEXT_SIZE"), + ("libavutil/avutil.h", None, "FF_API_PIX_FMT_DESC"), + ("libavutil/avutil.h", None, "FF_API_AV_REVERSE"), + ("libavutil/avutil.h", None, "FF_API_AUDIOCONVERT"), + ("libavutil/avutil.h", None, "FF_API_CPU_FLAG_MMX2"), + ("libavutil/avutil.h", None, "FF_API_LLS_PRIVATE"), + ("libavutil/avutil.h", None, "FF_API_AVFRAME_LAVC"), + ("libavutil/avutil.h", None, "FF_API_VDPAU"), + ( + "libavutil/avutil.h", + None, + "FF_API_GET_CHANNEL_LAYOUT_COMPAT", + ), + ("libavutil/avutil.h", None, "FF_API_XVMC"), + ("libavutil/avutil.h", None, "FF_API_OPT_TYPE_METADATA"), + ("libavutil/avutil.h", None, "FF_API_DLOG"), + ("libavutil/avutil.h", None, "FF_API_HMAC"), + ("libavutil/avutil.h", None, "FF_API_VAAPI"), + ("libavutil/avutil.h", None, "FF_API_PKT_PTS"), + ("libavutil/avutil.h", None, "FF_API_ERROR_FRAME"), + ("libavutil/avutil.h", None, "FF_API_FRAME_QP"), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_VIMA_DECODER", + ), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_REQUEST_CHANNELS", + ), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_OLD_DECODE_AUDIO", + ), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_OLD_ENCODE_AUDIO", + ), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_OLD_ENCODE_VIDEO", + ), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_CODEC_ID"), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_AUDIO_CONVERT", + ), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_AVCODEC_RESAMPLE", + ), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_DEINTERLACE", + ), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_DESTRUCT_PACKET", + ), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_GET_BUFFER"), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_MISSING_SAMPLE", + ), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_LOWRES"), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_CAP_VDPAU"), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_BUFS_VDPAU"), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_VOXWARE"), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_SET_DIMENSIONS", + ), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_DEBUG_MV"), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_AC_VLC"), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_OLD_MSMPEG4", + ), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_ASPECT_EXTENDED", + ), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_THREAD_OPAQUE", + ), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_CODEC_PKT"), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_ARCH_ALPHA"), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_ERROR_RATE"), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_QSCALE_TYPE", + ), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_MB_TYPE"), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_MAX_BFRAMES", + ), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_NEG_LINESIZES", + ), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_EMU_EDGE"), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_ARCH_SH4"), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_ARCH_SPARC"), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_UNUSED_MEMBERS", + ), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_IDCT_XVIDMMX", + ), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_INPUT_PRESERVED", + ), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_NORMALIZE_AQP", + ), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_GMC"), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_MV0"), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_CODEC_NAME"), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_AFD"), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_VISMV"), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_DV_FRAME_PROFILE", + ), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_AUDIOENC_DELAY", + ), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_VAAPI_CONTEXT", + ), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_AVCTX_TIMEBASE", + ), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_MPV_OPT"), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_STREAM_CODEC_TAG", + ), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_QUANT_BIAS"), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_RC_STRATEGY", + ), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_CODED_FRAME", + ), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_MOTION_EST"), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_WITHOUT_PREFIX", + ), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_CONVERGENCE_DURATION", + ), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_PRIVATE_OPT", + ), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_CODER_TYPE"), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_RTP_CALLBACK", + ), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_STAT_BITS"), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_VBV_DELAY"), + ( + "libavcodec/avcodec.h", + Some("avcodec"), + "FF_API_SIDEDATA_ONLY_PKT", + ), + ("libavcodec/avcodec.h", Some("avcodec"), "FF_API_AVPICTURE"), + ( + "libavformat/avformat.h", + Some("avformat"), + "FF_API_LAVF_BITEXACT", + ), + ( + "libavformat/avformat.h", + Some("avformat"), + "FF_API_LAVF_FRAC", + ), + ( + "libavformat/avformat.h", + Some("avformat"), + "FF_API_URL_FEOF", + ), + ( + "libavformat/avformat.h", + Some("avformat"), + "FF_API_PROBESIZE_32", + ), + ( + "libavformat/avformat.h", + Some("avformat"), + "FF_API_LAVF_AVCTX", + ), + ( + "libavformat/avformat.h", + Some("avformat"), + "FF_API_OLD_OPEN_CALLBACKS", + ), + ( + "libavfilter/avfilter.h", + Some("avfilter"), + "FF_API_AVFILTERPAD_PUBLIC", + ), + ( + "libavfilter/avfilter.h", + Some("avfilter"), + "FF_API_FOO_COUNT", + ), + ( + "libavfilter/avfilter.h", + Some("avfilter"), + "FF_API_OLD_FILTER_OPTS", + ), + ( + "libavfilter/avfilter.h", + Some("avfilter"), + "FF_API_OLD_FILTER_OPTS_ERROR", + ), + ( + "libavfilter/avfilter.h", + Some("avfilter"), + "FF_API_AVFILTER_OPEN", + ), + ( + "libavfilter/avfilter.h", + Some("avfilter"), + "FF_API_OLD_FILTER_REGISTER", + ), + ( + "libavfilter/avfilter.h", + Some("avfilter"), + "FF_API_OLD_GRAPH_PARSE", + ), + ( + "libavfilter/avfilter.h", + Some("avfilter"), + "FF_API_NOCONST_GET_NAME", + ), + ( + "libavresample/avresample.h", + Some("avresample"), + "FF_API_RESAMPLE_CLOSE_OPEN", + ), + ( + "libswscale/swscale.h", + Some("swscale"), + "FF_API_SWS_CPU_CAPS", + ), + ("libswscale/swscale.h", Some("swscale"), "FF_API_ARCH_BFIN"), + ], + ); + + let clang_includes = include_paths + .iter() + .map(|include| format!("-I{}", include.to_string_lossy())); + + // The bindgen::Builder is the main entry point + // to bindgen, and lets you build up options for + // the resulting bindings. + let mut builder = bindgen::Builder::default() + .clang_args(clang_includes) + .ctypes_prefix("libc") + // https://github.com/rust-lang/rust-bindgen/issues/550 + .blocklist_type("max_align_t") + .blocklist_function("_.*") + // Blocklist functions with u128 in signature. + // https://github.com/zmwangx/rust-ffmpeg-sys/issues/1 + // https://github.com/rust-lang/rust-bindgen/issues/1549 + .blocklist_function("acoshl") + .blocklist_function("acosl") + .blocklist_function("asinhl") + .blocklist_function("asinl") + .blocklist_function("atan2l") + .blocklist_function("atanhl") + .blocklist_function("atanl") + .blocklist_function("cbrtl") + .blocklist_function("ceill") + .blocklist_function("copysignl") + .blocklist_function("coshl") + .blocklist_function("cosl") + .blocklist_function("dreml") + .blocklist_function("ecvt_r") + .blocklist_function("erfcl") + .blocklist_function("erfl") + .blocklist_function("exp2l") + .blocklist_function("expl") + .blocklist_function("expm1l") + .blocklist_function("fabsl") + .blocklist_function("fcvt_r") + .blocklist_function("fdiml") + .blocklist_function("finitel") + .blocklist_function("floorl") + .blocklist_function("fmal") + .blocklist_function("fmaxl") + .blocklist_function("fminl") + .blocklist_function("fmodl") + .blocklist_function("frexpl") + .blocklist_function("gammal") + .blocklist_function("hypotl") + .blocklist_function("ilogbl") + .blocklist_function("isinfl") + .blocklist_function("isnanl") + .blocklist_function("j0l") + .blocklist_function("j1l") + .blocklist_function("jnl") + .blocklist_function("ldexpl") + .blocklist_function("lgammal") + .blocklist_function("lgammal_r") + .blocklist_function("llrintl") + .blocklist_function("llroundl") + .blocklist_function("log10l") + .blocklist_function("log1pl") + .blocklist_function("log2l") + .blocklist_function("logbl") + .blocklist_function("logl") + .blocklist_function("lrintl") + .blocklist_function("lroundl") + .blocklist_function("modfl") + .blocklist_function("nanl") + .blocklist_function("nearbyintl") + .blocklist_function("nextafterl") + .blocklist_function("nexttoward") + .blocklist_function("nexttowardf") + .blocklist_function("nexttowardl") + .blocklist_function("powl") + .blocklist_function("qecvt") + .blocklist_function("qecvt_r") + .blocklist_function("qfcvt") + .blocklist_function("qfcvt_r") + .blocklist_function("qgcvt") + .blocklist_function("remainderl") + .blocklist_function("remquol") + .blocklist_function("rintl") + .blocklist_function("roundl") + .blocklist_function("scalbl") + .blocklist_function("scalblnl") + .blocklist_function("scalbnl") + .blocklist_function("significandl") + .blocklist_function("sinhl") + .blocklist_function("sinl") + .blocklist_function("sqrtl") + .blocklist_function("strtold") + .blocklist_function("tanhl") + .blocklist_function("tanl") + .blocklist_function("tgammal") + .blocklist_function("truncl") + .blocklist_function("y0l") + .blocklist_function("y1l") + .blocklist_function("ynl") + .opaque_type("__mingw_ldbl_type_t") + .default_enum_style(bindgen::EnumVariation::Rust { + non_exhaustive: env::var("CARGO_FEATURE_NON_EXHAUSTIVE_ENUMS").is_ok(), + }) + .prepend_enum_name(false) + .derive_eq(true) + .size_t_is_usize(true) + .parse_callbacks(Box::new(Callbacks)); + + // The input headers we would like to generate + // bindings for. + if env::var("CARGO_FEATURE_AVCODEC").is_ok() { + builder = builder + .header(search_include(&include_paths, "libavcodec/avcodec.h")) + .header(search_include(&include_paths, "libavcodec/dv_profile.h")) + .header(search_include(&include_paths, "libavcodec/avfft.h")) + .header(search_include(&include_paths, "libavcodec/vorbis_parser.h")); + + if ffmpeg_major_version < 5 { + builder = builder.header(search_include(&include_paths, "libavcodec/vaapi.h")) + } + } + + if env::var("CARGO_FEATURE_AVDEVICE").is_ok() { + builder = builder.header(search_include(&include_paths, "libavdevice/avdevice.h")); + } + + if env::var("CARGO_FEATURE_AVFILTER").is_ok() { + builder = builder + .header(search_include(&include_paths, "libavfilter/buffersink.h")) + .header(search_include(&include_paths, "libavfilter/buffersrc.h")) + .header(search_include(&include_paths, "libavfilter/avfilter.h")); + } + + if env::var("CARGO_FEATURE_AVFORMAT").is_ok() { + builder = builder + .header(search_include(&include_paths, "libavformat/avformat.h")) + .header(search_include(&include_paths, "libavformat/avio.h")); + } + + if env::var("CARGO_FEATURE_AVRESAMPLE").is_ok() { + builder = builder.header(search_include(&include_paths, "libavresample/avresample.h")); + } + + builder = builder + .header(search_include(&include_paths, "libavutil/adler32.h")) + .header(search_include(&include_paths, "libavutil/aes.h")) + .header(search_include(&include_paths, "libavutil/audio_fifo.h")) + .header(search_include(&include_paths, "libavutil/base64.h")) + .header(search_include(&include_paths, "libavutil/blowfish.h")) + .header(search_include(&include_paths, "libavutil/bprint.h")) + .header(search_include(&include_paths, "libavutil/buffer.h")) + .header(search_include(&include_paths, "libavutil/camellia.h")) + .header(search_include(&include_paths, "libavutil/cast5.h")) + .header(search_include(&include_paths, "libavutil/channel_layout.h")) + // Here until https://github.com/rust-lang/rust-bindgen/issues/2192 / + // https://github.com/rust-lang/rust-bindgen/issues/258 is fixed. + .header("channel_layout_fixed.h") + .header(search_include(&include_paths, "libavutil/cpu.h")) + .header(search_include(&include_paths, "libavutil/crc.h")) + .header(search_include(&include_paths, "libavutil/dict.h")) + .header(search_include(&include_paths, "libavutil/display.h")) + .header(search_include(&include_paths, "libavutil/downmix_info.h")) + .header(search_include(&include_paths, "libavutil/error.h")) + .header(search_include(&include_paths, "libavutil/eval.h")) + .header(search_include(&include_paths, "libavutil/fifo.h")) + .header(search_include(&include_paths, "libavutil/file.h")) + .header(search_include(&include_paths, "libavutil/frame.h")) + .header(search_include(&include_paths, "libavutil/hash.h")) + .header(search_include(&include_paths, "libavutil/hmac.h")) + .header(search_include(&include_paths, "libavutil/hwcontext.h")) + .header(search_include(&include_paths, "libavutil/imgutils.h")) + .header(search_include(&include_paths, "libavutil/lfg.h")) + .header(search_include(&include_paths, "libavutil/log.h")) + .header(search_include(&include_paths, "libavutil/lzo.h")) + .header(search_include(&include_paths, "libavutil/macros.h")) + .header(search_include(&include_paths, "libavutil/mathematics.h")) + .header(search_include(&include_paths, "libavutil/md5.h")) + .header(search_include(&include_paths, "libavutil/mem.h")) + .header(search_include(&include_paths, "libavutil/motion_vector.h")) + .header(search_include(&include_paths, "libavutil/murmur3.h")) + .header(search_include(&include_paths, "libavutil/opt.h")) + .header(search_include(&include_paths, "libavutil/parseutils.h")) + .header(search_include(&include_paths, "libavutil/pixdesc.h")) + .header(search_include(&include_paths, "libavutil/pixfmt.h")) + .header(search_include(&include_paths, "libavutil/random_seed.h")) + .header(search_include(&include_paths, "libavutil/rational.h")) + .header(search_include(&include_paths, "libavutil/replaygain.h")) + .header(search_include(&include_paths, "libavutil/ripemd.h")) + .header(search_include(&include_paths, "libavutil/samplefmt.h")) + .header(search_include(&include_paths, "libavutil/sha.h")) + .header(search_include(&include_paths, "libavutil/sha512.h")) + .header(search_include(&include_paths, "libavutil/stereo3d.h")) + .header(search_include(&include_paths, "libavutil/avstring.h")) + .header(search_include(&include_paths, "libavutil/threadmessage.h")) + .header(search_include(&include_paths, "libavutil/time.h")) + .header(search_include(&include_paths, "libavutil/timecode.h")) + .header(search_include(&include_paths, "libavutil/twofish.h")) + .header(search_include(&include_paths, "libavutil/avutil.h")) + .header(search_include(&include_paths, "libavutil/xtea.h")); + + if env::var("CARGO_FEATURE_POSTPROC").is_ok() { + builder = builder.header(search_include(&include_paths, "libpostproc/postprocess.h")); + } + + if env::var("CARGO_FEATURE_SWRESAMPLE").is_ok() { + builder = builder.header(search_include(&include_paths, "libswresample/swresample.h")); + } + + if env::var("CARGO_FEATURE_SWSCALE").is_ok() { + builder = builder.header(search_include(&include_paths, "libswscale/swscale.h")); + } + + if let Some(hwcontext_drm_header) = + maybe_search_include(&include_paths, "libavutil/hwcontext_drm.h") + { + builder = builder.header(hwcontext_drm_header); + } + + // Finish the builder and generate the bindings. + let bindings = builder + .generate() + // Unwrap the Result and panic on failure. + .expect("Unable to generate bindings"); + + // Write the bindings to the $OUT_DIR/bindings.rs file. + bindings + .write_to_file(output().join("bindings.rs")) + .expect("Couldn't write bindings!"); +} diff --git a/crates/ffmpeg-sys/channel_layout_fixed.h b/crates/ffmpeg-sys/channel_layout_fixed.h new file mode 100644 index 000000000..d92a60d06 --- /dev/null +++ b/crates/ffmpeg-sys/channel_layout_fixed.h @@ -0,0 +1,224 @@ +// Here until https://github.com/rust-lang/rust-bindgen/issues/2192 / +// https://github.com/rust-lang/rust-bindgen/issues/258 is fixed. +#include + +#if (LIBAVUTIL_VERSION_MAJOR >= 57 && LIBAVUTIL_VERSION_MINOR >= 28) || LIBAVUTIL_VERSION_MAJOR >= 58 + +#undef AV_CH_FRONT_LEFT +#undef AV_CH_FRONT_RIGHT +#undef AV_CH_FRONT_CENTER +#undef AV_CH_LOW_FREQUENCY +#undef AV_CH_BACK_LEFT +#undef AV_CH_BACK_RIGHT +#undef AV_CH_FRONT_LEFT_OF_CENTER +#undef AV_CH_FRONT_RIGHT_OF_CENTER +#undef AV_CH_BACK_CENTER +#undef AV_CH_SIDE_LEFT +#undef AV_CH_SIDE_RIGHT +#undef AV_CH_TOP_CENTER +#undef AV_CH_TOP_FRONT_LEFT +#undef AV_CH_TOP_FRONT_CENTER +#undef AV_CH_TOP_FRONT_RIGHT +#undef AV_CH_TOP_BACK_LEFT +#undef AV_CH_TOP_BACK_CENTER +#undef AV_CH_TOP_BACK_RIGHT +#undef AV_CH_STEREO_LEFT +#undef AV_CH_STEREO_RIGHT +#undef AV_CH_WIDE_LEFT +#undef AV_CH_WIDE_RIGHT +#undef AV_CH_SURROUND_DIRECT_LEFT +#undef AV_CH_SURROUND_DIRECT_RIGHT +#undef AV_CH_LOW_FREQUENCY_2 +#undef AV_CH_TOP_SIDE_LEFT +#undef AV_CH_TOP_SIDE_RIGHT +#undef AV_CH_BOTTOM_FRONT_CENTER +#undef AV_CH_BOTTOM_FRONT_LEFT +#undef AV_CH_BOTTOM_FRONT_RIGHT + +const unsigned long long AV_CH_FRONT_LEFT = (1ULL << AV_CHAN_FRONT_LEFT); +const unsigned long long AV_CH_FRONT_RIGHT = (1ULL << AV_CHAN_FRONT_RIGHT); +const unsigned long long AV_CH_FRONT_CENTER = + (1ULL << AV_CHAN_FRONT_CENTER); +const unsigned long long AV_CH_LOW_FREQUENCY = + (1ULL << AV_CHAN_LOW_FREQUENCY); +const unsigned long long AV_CH_BACK_LEFT = (1ULL << AV_CHAN_BACK_LEFT); +const unsigned long long AV_CH_BACK_RIGHT = (1ULL << AV_CHAN_BACK_RIGHT); +const unsigned long long AV_CH_FRONT_LEFT_OF_CENTER = + (1ULL << AV_CHAN_FRONT_LEFT_OF_CENTER); +const unsigned long long AV_CH_FRONT_RIGHT_OF_CENTER = + (1ULL << AV_CHAN_FRONT_RIGHT_OF_CENTER); +const unsigned long long AV_CH_BACK_CENTER = (1ULL << AV_CHAN_BACK_CENTER); +const unsigned long long AV_CH_SIDE_LEFT = (1ULL << AV_CHAN_SIDE_LEFT); +const unsigned long long AV_CH_SIDE_RIGHT = (1ULL << AV_CHAN_SIDE_RIGHT); +const unsigned long long AV_CH_TOP_CENTER = (1ULL << AV_CHAN_TOP_CENTER); +const unsigned long long AV_CH_TOP_FRONT_LEFT = + (1ULL << AV_CHAN_TOP_FRONT_LEFT); +const unsigned long long AV_CH_TOP_FRONT_CENTER = + (1ULL << AV_CHAN_TOP_FRONT_CENTER); +const unsigned long long AV_CH_TOP_FRONT_RIGHT = + (1ULL << AV_CHAN_TOP_FRONT_RIGHT); +const unsigned long long AV_CH_TOP_BACK_LEFT = + (1ULL << AV_CHAN_TOP_BACK_LEFT); +const unsigned long long AV_CH_TOP_BACK_CENTER = + (1ULL << AV_CHAN_TOP_BACK_CENTER); +const unsigned long long AV_CH_TOP_BACK_RIGHT = + (1ULL << AV_CHAN_TOP_BACK_RIGHT); +const unsigned long long AV_CH_STEREO_LEFT = (1ULL << AV_CHAN_STEREO_LEFT); +const unsigned long long AV_CH_STEREO_RIGHT = + (1ULL << AV_CHAN_STEREO_RIGHT); +const unsigned long long AV_CH_WIDE_LEFT = (1ULL << AV_CHAN_WIDE_LEFT); +const unsigned long long AV_CH_WIDE_RIGHT = (1ULL << AV_CHAN_WIDE_RIGHT); +const unsigned long long AV_CH_SURROUND_DIRECT_LEFT = + (1ULL << AV_CHAN_SURROUND_DIRECT_LEFT); +const unsigned long long AV_CH_SURROUND_DIRECT_RIGHT = + (1ULL << AV_CHAN_SURROUND_DIRECT_RIGHT); +const unsigned long long AV_CH_LOW_FREQUENCY_2 = + (1ULL << AV_CHAN_LOW_FREQUENCY_2); +const unsigned long long AV_CH_TOP_SIDE_LEFT = + (1ULL << AV_CHAN_TOP_SIDE_LEFT); +const unsigned long long AV_CH_TOP_SIDE_RIGHT = + (1ULL << AV_CHAN_TOP_SIDE_RIGHT); +const unsigned long long AV_CH_BOTTOM_FRONT_CENTER = + (1ULL << AV_CHAN_BOTTOM_FRONT_CENTER); +const unsigned long long AV_CH_BOTTOM_FRONT_LEFT = + (1ULL << AV_CHAN_BOTTOM_FRONT_LEFT); +const unsigned long long AV_CH_BOTTOM_FRONT_RIGHT = + (1ULL << AV_CHAN_BOTTOM_FRONT_RIGHT); + +#undef AV_CH_LAYOUT_MONO +#undef AV_CH_LAYOUT_STEREO +#undef AV_CH_LAYOUT_2POINT1 +#undef AV_CH_LAYOUT_2_1 +#undef AV_CH_LAYOUT_SURROUND +#undef AV_CH_LAYOUT_3POINT1 +#undef AV_CH_LAYOUT_4POINT0 +#undef AV_CH_LAYOUT_4POINT1 +#undef AV_CH_LAYOUT_2_2 +#undef AV_CH_LAYOUT_QUAD +#undef AV_CH_LAYOUT_5POINT0 +#undef AV_CH_LAYOUT_5POINT1 +#undef AV_CH_LAYOUT_5POINT0_BACK +#undef AV_CH_LAYOUT_5POINT1_BACK +#undef AV_CH_LAYOUT_6POINT0 +#undef AV_CH_LAYOUT_6POINT0_FRONT +#undef AV_CH_LAYOUT_HEXAGONAL +#undef AV_CH_LAYOUT_6POINT1 +#undef AV_CH_LAYOUT_6POINT1_BACK +#undef AV_CH_LAYOUT_6POINT1_FRONT +#undef AV_CH_LAYOUT_7POINT0 +#undef AV_CH_LAYOUT_7POINT0_FRONT +#undef AV_CH_LAYOUT_7POINT1 +#undef AV_CH_LAYOUT_7POINT1_WIDE +#undef AV_CH_LAYOUT_7POINT1_WIDE_BACK +#undef AV_CH_LAYOUT_OCTAGONAL +#undef AV_CH_LAYOUT_HEXADECAGONAL +#undef AV_CH_LAYOUT_STEREO_DOWNMIX +#undef AV_CH_LAYOUT_22POINT2 +#undef AV_CH_LAYOUT_CUBE + +const unsigned long long AV_CH_LAYOUT_MONO = (AV_CH_FRONT_CENTER); +const unsigned long long AV_CH_LAYOUT_STEREO = + (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT); +const unsigned long long AV_CH_LAYOUT_2POINT1 = + (AV_CH_LAYOUT_STEREO | AV_CH_LOW_FREQUENCY); +const unsigned long long AV_CH_LAYOUT_2_1 = + (AV_CH_LAYOUT_STEREO | AV_CH_BACK_CENTER); +const unsigned long long AV_CH_LAYOUT_SURROUND = + (AV_CH_LAYOUT_STEREO | AV_CH_FRONT_CENTER); +const unsigned long long AV_CH_LAYOUT_3POINT1 = + (AV_CH_LAYOUT_SURROUND | AV_CH_LOW_FREQUENCY); +const unsigned long long AV_CH_LAYOUT_4POINT0 = + (AV_CH_LAYOUT_SURROUND | AV_CH_BACK_CENTER); +const unsigned long long AV_CH_LAYOUT_4POINT1 = + (AV_CH_LAYOUT_4POINT0 | AV_CH_LOW_FREQUENCY); +const unsigned long long AV_CH_LAYOUT_2_2 = + (AV_CH_LAYOUT_STEREO | AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT); +const unsigned long long AV_CH_LAYOUT_QUAD = + (AV_CH_LAYOUT_STEREO | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT); +const unsigned long long AV_CH_LAYOUT_5POINT0 = + (AV_CH_LAYOUT_SURROUND | AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT); +const unsigned long long AV_CH_LAYOUT_5POINT1 = + (AV_CH_LAYOUT_5POINT0 | AV_CH_LOW_FREQUENCY); +const unsigned long long AV_CH_LAYOUT_5POINT0_BACK = + (AV_CH_LAYOUT_SURROUND | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT); +const unsigned long long AV_CH_LAYOUT_5POINT1_BACK = + (AV_CH_LAYOUT_5POINT0_BACK | AV_CH_LOW_FREQUENCY); +const unsigned long long AV_CH_LAYOUT_6POINT0 = + (AV_CH_LAYOUT_5POINT0 | AV_CH_BACK_CENTER); +const unsigned long long AV_CH_LAYOUT_6POINT0_FRONT = + (AV_CH_LAYOUT_2_2 | AV_CH_FRONT_LEFT_OF_CENTER | + AV_CH_FRONT_RIGHT_OF_CENTER); +const unsigned long long AV_CH_LAYOUT_HEXAGONAL = + (AV_CH_LAYOUT_5POINT0_BACK | AV_CH_BACK_CENTER); +const unsigned long long AV_CH_LAYOUT_6POINT1 = + (AV_CH_LAYOUT_5POINT1 | AV_CH_BACK_CENTER); +const unsigned long long AV_CH_LAYOUT_6POINT1_BACK = + (AV_CH_LAYOUT_5POINT1_BACK | AV_CH_BACK_CENTER); +const unsigned long long AV_CH_LAYOUT_6POINT1_FRONT = + (AV_CH_LAYOUT_6POINT0_FRONT | AV_CH_LOW_FREQUENCY); +const unsigned long long AV_CH_LAYOUT_7POINT0 = + (AV_CH_LAYOUT_5POINT0 | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT); +const unsigned long long AV_CH_LAYOUT_7POINT0_FRONT = + (AV_CH_LAYOUT_5POINT0 | AV_CH_FRONT_LEFT_OF_CENTER | + AV_CH_FRONT_RIGHT_OF_CENTER); +const unsigned long long AV_CH_LAYOUT_7POINT1 = + (AV_CH_LAYOUT_5POINT1 | AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT); +const unsigned long long AV_CH_LAYOUT_7POINT1_WIDE = + (AV_CH_LAYOUT_5POINT1 | AV_CH_FRONT_LEFT_OF_CENTER | + AV_CH_FRONT_RIGHT_OF_CENTER); +const unsigned long long AV_CH_LAYOUT_7POINT1_WIDE_BACK = + (AV_CH_LAYOUT_5POINT1_BACK | AV_CH_FRONT_LEFT_OF_CENTER | + AV_CH_FRONT_RIGHT_OF_CENTER); +const unsigned long long AV_CH_LAYOUT_OCTAGONAL = + (AV_CH_LAYOUT_5POINT0 | AV_CH_BACK_LEFT | AV_CH_BACK_CENTER | + AV_CH_BACK_RIGHT); +const unsigned long long AV_CH_LAYOUT_HEXADECAGONAL = + (AV_CH_LAYOUT_OCTAGONAL | AV_CH_WIDE_LEFT | AV_CH_WIDE_RIGHT | + AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT | AV_CH_TOP_BACK_CENTER | + AV_CH_TOP_FRONT_CENTER | AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT); +const unsigned long long AV_CH_LAYOUT_STEREO_DOWNMIX = + (AV_CH_STEREO_LEFT | AV_CH_STEREO_RIGHT); +const unsigned long long AV_CH_LAYOUT_22POINT2 = + (AV_CH_LAYOUT_5POINT1_BACK | AV_CH_FRONT_LEFT_OF_CENTER | + AV_CH_FRONT_RIGHT_OF_CENTER | AV_CH_BACK_CENTER | AV_CH_LOW_FREQUENCY_2 | + AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT | AV_CH_TOP_FRONT_LEFT | + AV_CH_TOP_FRONT_RIGHT | AV_CH_TOP_FRONT_CENTER | AV_CH_TOP_CENTER | + AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT | AV_CH_TOP_SIDE_LEFT | + AV_CH_TOP_SIDE_RIGHT | AV_CH_TOP_BACK_CENTER | AV_CH_BOTTOM_FRONT_CENTER | + AV_CH_BOTTOM_FRONT_LEFT | AV_CH_BOTTOM_FRONT_RIGHT); +const unsigned long long AV_CH_LAYOUT_CUBE = + (AV_CH_LAYOUT_QUAD | AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT | AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT); +#endif + +#if (LIBAVUTIL_VERSION_MAJOR >= 58 && LIBAVUTIL_VERSION_MINOR >= 29) || LIBAVUTIL_VERSION_MAJOR >= 59 + +#undef AV_CH_LAYOUT_3POINT1POINT2 +#undef AV_CH_LAYOUT_5POINT1POINT2_BACK +#undef AV_CH_LAYOUT_5POINT1POINT4_BACK +#undef AV_CH_LAYOUT_7POINT1POINT2 +#undef AV_CH_LAYOUT_7POINT1POINT4_BACK + +const unsigned long long AV_CH_LAYOUT_3POINT1POINT2 = + (AV_CH_LAYOUT_3POINT1 | AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT); +const unsigned long long AV_CH_LAYOUT_5POINT1POINT2_BACK = + (AV_CH_LAYOUT_5POINT1_BACK | AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT); +const unsigned long long AV_CH_LAYOUT_5POINT1POINT4_BACK = + (AV_CH_LAYOUT_5POINT1POINT2_BACK | AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT); +const unsigned long long AV_CH_LAYOUT_7POINT1POINT2 = + (AV_CH_LAYOUT_7POINT1 | AV_CH_TOP_FRONT_LEFT | AV_CH_TOP_FRONT_RIGHT); +const unsigned long long AV_CH_LAYOUT_7POINT1POINT4_BACK = + (AV_CH_LAYOUT_7POINT1POINT2 | AV_CH_TOP_BACK_LEFT | AV_CH_TOP_BACK_RIGHT); + +#endif + +#if (LIBAVUTIL_VERSION_MAJOR >= 59) + +#undef AV_CH_LAYOUT_7POINT2POINT3 +#undef AV_CH_LAYOUT_9POINT1POINT4_BACK + +const unsigned long long AV_CH_LAYOUT_7POINT2POINT3 = + (AV_CH_LAYOUT_7POINT1POINT2 | AV_CH_TOP_BACK_CENTER | AV_CH_LOW_FREQUENCY_2); +const unsigned long long AV_CH_LAYOUT_9POINT1POINT4_BACK = + (AV_CH_LAYOUT_7POINT1POINT4_BACK | AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER); + +#endif diff --git a/crates/ffmpeg-sys/src/avutil/error.rs b/crates/ffmpeg-sys/src/avutil/error.rs new file mode 100644 index 000000000..7a41d8e98 --- /dev/null +++ b/crates/ffmpeg-sys/src/avutil/error.rs @@ -0,0 +1,69 @@ +use libc::{c_char, c_int, size_t}; + +// Note: FFmpeg's AVERROR and AVUNERROR are conditionally defined based on +// whether EDOM is positive, claiming that "Some platforms have E* and errno +// already negated". This can be traced to a commit in 2007 where "some +// platforms" were specifically identified as BeOS (so maybe also Haiku?): +// https://github.com/FFmpeg/FFmpeg/commit/8fa36ae09dddb1b639b4df5d505c0dbcf4e916e4 +// constness is more valuable than BeOS support, so if someone really needs it, +// send a patch with cfg_attr. + +#[inline(always)] +pub const fn AVERROR(e: c_int) -> c_int { + -e +} + +#[inline(always)] +pub const fn AVUNERROR(e: c_int) -> c_int { + -e +} + +macro_rules! FFERRTAG { + ($a:expr, $b:expr, $c:expr, $d:expr) => { + -MKTAG!($a, $b, $c, $d) as c_int + }; +} + +pub const AVERROR_BSF_NOT_FOUND: c_int = FFERRTAG!(0xF8, b'B', b'S', b'F'); +pub const AVERROR_BUG: c_int = FFERRTAG!(b'B', b'U', b'G', b'!'); +pub const AVERROR_BUFFER_TOO_SMALL: c_int = FFERRTAG!(b'B', b'U', b'F', b'S'); +pub const AVERROR_DECODER_NOT_FOUND: c_int = FFERRTAG!(0xF8, b'D', b'E', b'C'); +pub const AVERROR_DEMUXER_NOT_FOUND: c_int = FFERRTAG!(0xF8, b'D', b'E', b'M'); +pub const AVERROR_ENCODER_NOT_FOUND: c_int = FFERRTAG!(0xF8, b'E', b'N', b'C'); +pub const AVERROR_EOF: c_int = FFERRTAG!(b'E', b'O', b'F', b' '); +pub const AVERROR_EXIT: c_int = FFERRTAG!(b'E', b'X', b'I', b'T'); +pub const AVERROR_EXTERNAL: c_int = FFERRTAG!(b'E', b'X', b'T', b' '); +pub const AVERROR_FILTER_NOT_FOUND: c_int = FFERRTAG!(0xF8, b'F', b'I', b'L'); +pub const AVERROR_INVALIDDATA: c_int = FFERRTAG!(b'I', b'N', b'D', b'A'); +pub const AVERROR_MUXER_NOT_FOUND: c_int = FFERRTAG!(0xF8, b'M', b'U', b'X'); +pub const AVERROR_OPTION_NOT_FOUND: c_int = FFERRTAG!(0xF8, b'O', b'P', b'T'); +pub const AVERROR_PATCHWELCOME: c_int = FFERRTAG!(b'P', b'A', b'W', b'E'); +pub const AVERROR_PROTOCOL_NOT_FOUND: c_int = FFERRTAG!(0xF8, b'P', b'R', b'O'); + +pub const AVERROR_STREAM_NOT_FOUND: c_int = FFERRTAG!(0xF8, b'S', b'T', b'R'); + +pub const AVERROR_BUG2: c_int = FFERRTAG!(b'B', b'U', b'G', b' '); +pub const AVERROR_UNKNOWN: c_int = FFERRTAG!(b'U', b'N', b'K', b'N'); + +pub const AVERROR_HTTP_BAD_REQUEST: c_int = FFERRTAG!(0xF8, b'4', b'0', b'0'); +pub const AVERROR_HTTP_UNAUTHORIZED: c_int = FFERRTAG!(0xF8, b'4', b'0', b'1'); +pub const AVERROR_HTTP_FORBIDDEN: c_int = FFERRTAG!(0xF8, b'4', b'0', b'3'); +pub const AVERROR_HTTP_NOT_FOUND: c_int = FFERRTAG!(0xF8, b'4', b'0', b'4'); +pub const AVERROR_HTTP_TOO_MANY_REQUESTS: c_int = FFERRTAG!(0xF8, b'4', b'2', b'9'); +pub const AVERROR_HTTP_OTHER_4XX: c_int = FFERRTAG!(0xF8, b'4', b'X', b'X'); +pub const AVERROR_HTTP_SERVER_ERROR: c_int = FFERRTAG!(0xF8, b'5', b'X', b'X'); + +#[inline(always)] +pub unsafe fn av_make_error_string( + errbuf: *mut c_char, + errbuf_size: size_t, + errnum: c_int, +) -> *mut c_char { + av_strerror(errnum, errbuf, errbuf_size); + + errbuf +} + +extern "C" { + pub fn av_strerror(errnum: c_int, errbuf: *mut c_char, errbuf_size: size_t) -> c_int; +} diff --git a/crates/ffmpeg-sys/src/avutil/macros.rs b/crates/ffmpeg-sys/src/avutil/macros.rs new file mode 100644 index 000000000..a50636e9b --- /dev/null +++ b/crates/ffmpeg-sys/src/avutil/macros.rs @@ -0,0 +1,13 @@ +#[macro_export] +macro_rules! MKBETAG { + ($a:expr, $b:expr, $c:expr, $d:expr) => { + ($d as isize) | (($c as isize) << 8) | (($b as isize) << 16) | (($a as isize) << 24) + }; +} + +#[macro_export] +macro_rules! MKTAG { + ($a:expr, $b:expr, $c:expr, $d:expr) => { + ($a as isize) | (($b as isize) << 8) | (($c as isize) << 16) | (($d as isize) << 24) + }; +} diff --git a/crates/ffmpeg-sys/src/avutil/mod.rs b/crates/ffmpeg-sys/src/avutil/mod.rs new file mode 100644 index 000000000..af8aaf265 --- /dev/null +++ b/crates/ffmpeg-sys/src/avutil/mod.rs @@ -0,0 +1,14 @@ +#[macro_use] +mod macros; + +mod error; +pub use self::error::*; + +mod util; +pub use self::util::*; + +mod rational; +pub use self::rational::*; + +mod pixfmt; +pub use self::pixfmt::*; diff --git a/crates/ffmpeg-sys/src/avutil/pixfmt.rs b/crates/ffmpeg-sys/src/avutil/pixfmt.rs new file mode 100644 index 000000000..b927bbf8b --- /dev/null +++ b/crates/ffmpeg-sys/src/avutil/pixfmt.rs @@ -0,0 +1,236 @@ +use crate::AVPixelFormat; +use crate::AVPixelFormat::*; + +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_RGB32: AVPixelFormat = AV_PIX_FMT_BGRA; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_RGB32_1: AVPixelFormat = AV_PIX_FMT_ABGR; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_BGR32: AVPixelFormat = AV_PIX_FMT_RGBA; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_BGR32_1: AVPixelFormat = AV_PIX_FMT_ARGB; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_0RGB32: AVPixelFormat = AV_PIX_FMT_BGR0; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_0BGR32: AVPixelFormat = AV_PIX_FMT_RGB0; + +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_GRAY16: AVPixelFormat = AV_PIX_FMT_GRAY16LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YA16: AVPixelFormat = AV_PIX_FMT_YA16LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_RGB48: AVPixelFormat = AV_PIX_FMT_RGB48LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_RGB565: AVPixelFormat = AV_PIX_FMT_RGB565LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_RGB555: AVPixelFormat = AV_PIX_FMT_RGB555LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_RGB444: AVPixelFormat = AV_PIX_FMT_RGB444LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_BGR48: AVPixelFormat = AV_PIX_FMT_BGR48LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_BGR565: AVPixelFormat = AV_PIX_FMT_BGR565LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_BGR555: AVPixelFormat = AV_PIX_FMT_BGR555LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_BGR444: AVPixelFormat = AV_PIX_FMT_BGR444LE; + +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUV420P9: AVPixelFormat = AV_PIX_FMT_YUV420P9LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUV422P9: AVPixelFormat = AV_PIX_FMT_YUV422P9LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUV444P9: AVPixelFormat = AV_PIX_FMT_YUV444P9LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUV420P10: AVPixelFormat = AV_PIX_FMT_YUV420P10LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUV422P10: AVPixelFormat = AV_PIX_FMT_YUV422P10LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUV440P10: AVPixelFormat = AV_PIX_FMT_YUV440P10LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUV444P10: AVPixelFormat = AV_PIX_FMT_YUV444P10LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUV420P12: AVPixelFormat = AV_PIX_FMT_YUV420P12LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUV422P12: AVPixelFormat = AV_PIX_FMT_YUV422P12LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUV440P12: AVPixelFormat = AV_PIX_FMT_YUV440P12LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUV444P12: AVPixelFormat = AV_PIX_FMT_YUV444P12LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUV420P14: AVPixelFormat = AV_PIX_FMT_YUV420P14LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUV422P14: AVPixelFormat = AV_PIX_FMT_YUV422P14LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUV444P14: AVPixelFormat = AV_PIX_FMT_YUV444P14LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUV420P16: AVPixelFormat = AV_PIX_FMT_YUV420P16LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUV422P16: AVPixelFormat = AV_PIX_FMT_YUV422P16LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUV444P16: AVPixelFormat = AV_PIX_FMT_YUV444P16LE; + +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_GBRP9: AVPixelFormat = AV_PIX_FMT_GBRP9LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_GBRP10: AVPixelFormat = AV_PIX_FMT_GBRP10LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_GBRP12: AVPixelFormat = AV_PIX_FMT_GBRP12LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_GBRP14: AVPixelFormat = AV_PIX_FMT_GBRP14LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_GBRP16: AVPixelFormat = AV_PIX_FMT_GBRP16LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_GBRAP16: AVPixelFormat = AV_PIX_FMT_GBRAP16LE; + +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_BAYER_BGGR16: AVPixelFormat = AV_PIX_FMT_BAYER_BGGR16LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_BAYER_RGGB16: AVPixelFormat = AV_PIX_FMT_BAYER_RGGB16LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_BAYER_GBRG16: AVPixelFormat = AV_PIX_FMT_BAYER_GBRG16LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_BAYER_GRBG16: AVPixelFormat = AV_PIX_FMT_BAYER_GRBG16LE; + +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUVA420P9: AVPixelFormat = AV_PIX_FMT_YUVA420P9LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUVA422P9: AVPixelFormat = AV_PIX_FMT_YUVA422P9LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUVA444P9: AVPixelFormat = AV_PIX_FMT_YUVA444P9LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUVA420P10: AVPixelFormat = AV_PIX_FMT_YUVA420P10LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUVA422P10: AVPixelFormat = AV_PIX_FMT_YUVA422P10LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUVA444P10: AVPixelFormat = AV_PIX_FMT_YUVA444P10LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUVA420P16: AVPixelFormat = AV_PIX_FMT_YUVA420P16LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUVA422P16: AVPixelFormat = AV_PIX_FMT_YUVA422P16LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_YUVA444P16: AVPixelFormat = AV_PIX_FMT_YUVA444P16LE; + +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_XYZ12: AVPixelFormat = AV_PIX_FMT_XYZ12LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_NV20: AVPixelFormat = AV_PIX_FMT_NV20LE; +#[cfg(target_endian = "little")] +pub const AV_PIX_FMT_AYUV64: AVPixelFormat = AV_PIX_FMT_AYUV64LE; + +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_RGB32: AVPixelFormat = AV_PIX_FMT_ARGB; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_RGB32_1: AVPixelFormat = AV_PIX_FMT_RGBA; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_BGR32: AVPixelFormat = AV_PIX_FMT_ABGR; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_BGR32_1: AVPixelFormat = AV_PIX_FMT_BGRA; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_0RGB32: AVPixelFormat = AV_PIX_FMT_0RGB; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_0BGR32: AVPixelFormat = AV_PIX_FMT_0BGR; + +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_GRAY16: AVPixelFormat = AV_PIX_FMT_GRAY16BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YA16: AVPixelFormat = AV_PIX_FMT_YA16BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_RGB48: AVPixelFormat = AV_PIX_FMT_RGB48BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_RGB565: AVPixelFormat = AV_PIX_FMT_RGB565BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_RGB555: AVPixelFormat = AV_PIX_FMT_RGB555BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_RGB444: AVPixelFormat = AV_PIX_FMT_RGB444BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_BGR48: AVPixelFormat = AV_PIX_FMT_BGR48BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_BGR565: AVPixelFormat = AV_PIX_FMT_BGR565BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_BGR555: AVPixelFormat = AV_PIX_FMT_BGR555BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_BGR444: AVPixelFormat = AV_PIX_FMT_BGR444BE; + +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUV420P9: AVPixelFormat = AV_PIX_FMT_YUV420P9BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUV422P9: AVPixelFormat = AV_PIX_FMT_YUV422P9BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUV444P9: AVPixelFormat = AV_PIX_FMT_YUV444P9BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUV420P10: AVPixelFormat = AV_PIX_FMT_YUV420P10BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUV422P10: AVPixelFormat = AV_PIX_FMT_YUV422P10BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUV440P10: AVPixelFormat = AV_PIX_FMT_YUV440P10BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUV444P10: AVPixelFormat = AV_PIX_FMT_YUV444P10BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUV420P12: AVPixelFormat = AV_PIX_FMT_YUV420P12BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUV422P12: AVPixelFormat = AV_PIX_FMT_YUV422P12BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUV440P12: AVPixelFormat = AV_PIX_FMT_YUV440P12BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUV444P12: AVPixelFormat = AV_PIX_FMT_YUV444P12BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUV420P14: AVPixelFormat = AV_PIX_FMT_YUV420P14BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUV422P14: AVPixelFormat = AV_PIX_FMT_YUV422P14BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUV444P14: AVPixelFormat = AV_PIX_FMT_YUV444P14BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUV420P16: AVPixelFormat = AV_PIX_FMT_YUV420P16BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUV422P16: AVPixelFormat = AV_PIX_FMT_YUV422P16BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUV444P16: AVPixelFormat = AV_PIX_FMT_YUV444P16BE; + +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_GBRP9: AVPixelFormat = AV_PIX_FMT_GBRP9BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_GBRP10: AVPixelFormat = AV_PIX_FMT_GBRP10BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_GBRP12: AVPixelFormat = AV_PIX_FMT_GBRP12BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_GBRP14: AVPixelFormat = AV_PIX_FMT_GBRP14BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_GBRP16: AVPixelFormat = AV_PIX_FMT_GBRP16BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_GBRAP16: AVPixelFormat = AV_PIX_FMT_GBRAP16BE; + +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_BAYER_BGGR16: AVPixelFormat = AV_PIX_FMT_BAYER_BGGR16BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_BAYER_RGGB16: AVPixelFormat = AV_PIX_FMT_BAYER_RGGB16BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_BAYER_GBRG16: AVPixelFormat = AV_PIX_FMT_BAYER_GBRG16BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_BAYER_GRBG16: AVPixelFormat = AV_PIX_FMT_BAYER_GRBG16BE; + +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUVA420P9: AVPixelFormat = AV_PIX_FMT_YUVA420P9BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUVA422P9: AVPixelFormat = AV_PIX_FMT_YUVA422P9BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUVA444P9: AVPixelFormat = AV_PIX_FMT_YUVA444P9BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUVA420P10: AVPixelFormat = AV_PIX_FMT_YUVA420P10BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUVA422P10: AVPixelFormat = AV_PIX_FMT_YUVA422P10BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUVA444P10: AVPixelFormat = AV_PIX_FMT_YUVA444P10BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUVA420P16: AVPixelFormat = AV_PIX_FMT_YUVA420P16BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUVA422P16: AVPixelFormat = AV_PIX_FMT_YUVA422P16BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_YUVA444P16: AVPixelFormat = AV_PIX_FMT_YUVA444P16BE; + +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_XYZ12: AVPixelFormat = AV_PIX_FMT_XYZ12BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_NV20: AVPixelFormat = AV_PIX_FMT_NV20BE; +#[cfg(target_endian = "big")] +pub const AV_PIX_FMT_AYUV64: AVPixelFormat = AV_PIX_FMT_AYUV64BE; diff --git a/crates/ffmpeg-sys/src/avutil/rational.rs b/crates/ffmpeg-sys/src/avutil/rational.rs new file mode 100644 index 000000000..04124c8e1 --- /dev/null +++ b/crates/ffmpeg-sys/src/avutil/rational.rs @@ -0,0 +1,35 @@ +use libc::{c_double, c_int}; +use crate::AVRational; + +#[inline(always)] +pub unsafe fn av_make_q(num: c_int, den: c_int) -> AVRational { + AVRational { num, den } +} + +#[inline(always)] +pub unsafe fn av_cmp_q(a: AVRational, b: AVRational) -> c_int { + let tmp = i64::from(a.num) * i64::from(b.den) - i64::from(b.num) * i64::from(a.den); + + if tmp != 0 { + (((tmp ^ i64::from(a.den) ^ i64::from(b.den)) >> 63) | 1) as c_int + } else if b.den != 0 && a.den != 0 { + 0 + } else if a.num != 0 && b.num != 0 { + ((i64::from(a.num) >> 31) - (i64::from(b.num) >> 31)) as c_int + } else { + c_int::MIN + } +} + +#[inline(always)] +pub unsafe fn av_q2d(a: AVRational) -> c_double { + f64::from(a.num) / f64::from(a.den) +} + +#[inline(always)] +pub unsafe fn av_inv_q(q: AVRational) -> AVRational { + AVRational { + num: q.den, + den: q.num, + } +} diff --git a/crates/ffmpeg-sys/src/avutil/util.rs b/crates/ffmpeg-sys/src/avutil/util.rs new file mode 100644 index 000000000..22a310cfd --- /dev/null +++ b/crates/ffmpeg-sys/src/avutil/util.rs @@ -0,0 +1,8 @@ +use libc::c_int; +use crate::{AVRational, AV_TIME_BASE}; + +pub const AV_NOPTS_VALUE: i64 = 0x8000000000000000u64 as i64; +pub const AV_TIME_BASE_Q: AVRational = AVRational { + num: 1, + den: AV_TIME_BASE as c_int, +}; diff --git a/crates/ffmpeg-sys/src/lib.rs b/crates/ffmpeg-sys/src/lib.rs new file mode 100644 index 000000000..532f134fb --- /dev/null +++ b/crates/ffmpeg-sys/src/lib.rs @@ -0,0 +1,16 @@ +#![allow(non_upper_case_globals)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(clippy::approx_constant)] +#![allow(clippy::missing_safety_doc)] +#![allow(clippy::redundant_static_lifetimes)] +#![allow(clippy::too_many_arguments)] +#![allow(clippy::type_complexity)] + +extern crate libc; + +include!(concat!(env!("OUT_DIR"), "/bindings.rs")); + +#[macro_use] +mod avutil; +pub use avutil::*; diff --git a/crates/ffmpeg/Cargo.toml b/crates/ffmpeg/Cargo.toml index 355dfc1f0..dc3e49b9b 100644 --- a/crates/ffmpeg/Cargo.toml +++ b/crates/ffmpeg/Cargo.toml @@ -11,13 +11,13 @@ description = "FFmpeg bindings for Rust." keywords = ["ffmpeg", "video", "audio", "media"] [dependencies] -ffmpeg-sys-next = "7.1" libc = "0.2" bytes = { optional = true, version = "1" } tokio = { optional = true, version = "1" } crossbeam-channel = { optional = true, version = "0.5.13" } tracing = { optional = true, version = "0.1" } arc-swap = { version = "1.7" } +scuffle-ffmpeg-sys.workspace = true scuffle-workspace-hack.workspace = true [features] @@ -25,7 +25,7 @@ channel = ["dep:bytes"] tokio-channel = ["channel", "dep:tokio"] crossbeam-channel = ["channel", "dep:crossbeam-channel"] tracing = ["dep:tracing"] -build = ["ffmpeg-sys-next/build"] +build = ["scuffle-ffmpeg-sys/build"] [package.metadata.xtask] # Note: build is not an addative feature because it changes the build.rs and therefore diff --git a/crates/ffmpeg/src/codec.rs b/crates/ffmpeg/src/codec.rs index a88634de2..7d46a9d62 100644 --- a/crates/ffmpeg/src/codec.rs +++ b/crates/ffmpeg/src/codec.rs @@ -1,4 +1,4 @@ -use ffmpeg_sys_next::*; +use scuffle_ffmpeg_sys::*; #[derive(Clone, Copy, PartialEq, Eq)] pub struct DecoderCodec(*const AVCodec); diff --git a/crates/ffmpeg/src/decoder.rs b/crates/ffmpeg/src/decoder.rs index 16c6d054c..92c951a06 100644 --- a/crates/ffmpeg/src/decoder.rs +++ b/crates/ffmpeg/src/decoder.rs @@ -1,4 +1,4 @@ -use ffmpeg_sys_next::*; +use scuffle_ffmpeg_sys::*; use crate::codec::DecoderCodec; use crate::error::{FfmpegError, AVERROR_EAGAIN}; diff --git a/crates/ffmpeg/src/dict.rs b/crates/ffmpeg/src/dict.rs index 90e8ade13..b67749f3a 100644 --- a/crates/ffmpeg/src/dict.rs +++ b/crates/ffmpeg/src/dict.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use std::ffi::{CStr, CString}; -use ffmpeg_sys_next::*; +use scuffle_ffmpeg_sys::*; use crate::error::FfmpegError; use crate::smart_object::SmartPtr; diff --git a/crates/ffmpeg/src/encoder.rs b/crates/ffmpeg/src/encoder.rs index d08ab5603..dc94aabda 100644 --- a/crates/ffmpeg/src/encoder.rs +++ b/crates/ffmpeg/src/encoder.rs @@ -1,4 +1,4 @@ -use ffmpeg_sys_next::*; +use scuffle_ffmpeg_sys::*; use crate::codec::EncoderCodec; use crate::dict::Dictionary; diff --git a/crates/ffmpeg/src/error.rs b/crates/ffmpeg/src/error.rs index afbd65141..d47d8f162 100644 --- a/crates/ffmpeg/src/error.rs +++ b/crates/ffmpeg/src/error.rs @@ -1,4 +1,4 @@ -use ffmpeg_sys_next::*; +use scuffle_ffmpeg_sys::*; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum FfmpegError { diff --git a/crates/ffmpeg/src/filter_graph.rs b/crates/ffmpeg/src/filter_graph.rs index d3f391cf9..c756b2ca8 100644 --- a/crates/ffmpeg/src/filter_graph.rs +++ b/crates/ffmpeg/src/filter_graph.rs @@ -1,7 +1,7 @@ use std::ffi::CString; use std::ptr::NonNull; -use ffmpeg_sys_next::*; +use scuffle_ffmpeg_sys::*; use crate::error::{FfmpegError, AVERROR_EAGAIN}; use crate::frame::Frame; diff --git a/crates/ffmpeg/src/frame.rs b/crates/ffmpeg/src/frame.rs index 41ec7d6e0..f36cd9a00 100644 --- a/crates/ffmpeg/src/frame.rs +++ b/crates/ffmpeg/src/frame.rs @@ -1,4 +1,4 @@ -use ffmpeg_sys_next::*; +use scuffle_ffmpeg_sys::*; use crate::error::FfmpegError; use crate::smart_object::SmartPtr; diff --git a/crates/ffmpeg/src/io/input.rs b/crates/ffmpeg/src/io/input.rs index e7a5c92c5..7d9aef320 100644 --- a/crates/ffmpeg/src/io/input.rs +++ b/crates/ffmpeg/src/io/input.rs @@ -1,6 +1,6 @@ use std::ffi::CStr; -use ffmpeg_sys_next::*; +use scuffle_ffmpeg_sys::*; use super::internal::{read_packet, seek, Inner, InnerOptions}; use crate::consts::{Const, DEFAULT_BUFFER_SIZE}; diff --git a/crates/ffmpeg/src/io/internal.rs b/crates/ffmpeg/src/io/internal.rs index b27ad25ea..cc70a0997 100644 --- a/crates/ffmpeg/src/io/internal.rs +++ b/crates/ffmpeg/src/io/internal.rs @@ -1,5 +1,5 @@ -use ffmpeg_sys_next::*; -use libc::c_void; +use scuffle_ffmpeg_sys::*; +use libc::{c_void, SEEK_CUR, SEEK_END, SEEK_SET}; use crate::error::FfmpegError; use crate::smart_object::SmartPtr; diff --git a/crates/ffmpeg/src/io/output.rs b/crates/ffmpeg/src/io/output.rs index d2214b24a..ec4d8a7d8 100644 --- a/crates/ffmpeg/src/io/output.rs +++ b/crates/ffmpeg/src/io/output.rs @@ -1,4 +1,4 @@ -use ffmpeg_sys_next::*; +use scuffle_ffmpeg_sys::*; use super::internal::{seek, write_packet, Inner, InnerOptions}; use crate::consts::DEFAULT_BUFFER_SIZE; diff --git a/crates/ffmpeg/src/lib.rs b/crates/ffmpeg/src/lib.rs index e261f5e32..9b4c068d3 100644 --- a/crates/ffmpeg/src/lib.rs +++ b/crates/ffmpeg/src/lib.rs @@ -16,6 +16,6 @@ pub mod scalar; pub mod stream; pub mod utils; -pub use ffmpeg_sys_next as ffi; +pub use scuffle_ffmpeg_sys as ffi; mod smart_object; diff --git a/crates/ffmpeg/src/limiter.rs b/crates/ffmpeg/src/limiter.rs index 8cb274894..9e57e7b3e 100644 --- a/crates/ffmpeg/src/limiter.rs +++ b/crates/ffmpeg/src/limiter.rs @@ -1,4 +1,4 @@ -use ffmpeg_sys_next::AVRational; +use scuffle_ffmpeg_sys::AVRational; use crate::frame::Frame; diff --git a/crates/ffmpeg/src/log.rs b/crates/ffmpeg/src/log.rs index 8b392420f..4971a401e 100644 --- a/crates/ffmpeg/src/log.rs +++ b/crates/ffmpeg/src/log.rs @@ -2,7 +2,7 @@ use std::ffi::CStr; use std::sync::Arc; use arc_swap::ArcSwap; -use ffmpeg_sys_next::*; +use scuffle_ffmpeg_sys::*; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[repr(i32)] diff --git a/crates/ffmpeg/src/packet.rs b/crates/ffmpeg/src/packet.rs index b2ad2137b..4c009e111 100644 --- a/crates/ffmpeg/src/packet.rs +++ b/crates/ffmpeg/src/packet.rs @@ -1,4 +1,4 @@ -use ffmpeg_sys_next::*; +use scuffle_ffmpeg_sys::*; use crate::error::FfmpegError; use crate::smart_object::SmartPtr; diff --git a/crates/ffmpeg/src/scalar.rs b/crates/ffmpeg/src/scalar.rs index 34bae5f7c..3c6666c92 100644 --- a/crates/ffmpeg/src/scalar.rs +++ b/crates/ffmpeg/src/scalar.rs @@ -1,4 +1,4 @@ -use ffmpeg_sys_next::*; +use scuffle_ffmpeg_sys::*; use crate::error::FfmpegError; use crate::frame::{Frame, VideoFrame}; diff --git a/crates/ffmpeg/src/stream.rs b/crates/ffmpeg/src/stream.rs index c4308b5df..1db5dda99 100644 --- a/crates/ffmpeg/src/stream.rs +++ b/crates/ffmpeg/src/stream.rs @@ -1,4 +1,4 @@ -use ffmpeg_sys_next::*; +use scuffle_ffmpeg_sys::*; use crate::consts::{Const, Mut}; use crate::dict::Dictionary; diff --git a/crates/ffmpeg/src/utils.rs b/crates/ffmpeg/src/utils.rs index b0f71a0e8..bbdacb46b 100644 --- a/crates/ffmpeg/src/utils.rs +++ b/crates/ffmpeg/src/utils.rs @@ -1,4 +1,4 @@ -use ffmpeg_sys_next::*; +use scuffle_ffmpeg_sys::*; pub fn check_i64(val: i64) -> Option { if val == AV_NOPTS_VALUE { diff --git a/crates/workspace-hack/Cargo.toml b/crates/workspace-hack/Cargo.toml index 87b99878f..1dbe71ce8 100644 --- a/crates/workspace-hack/Cargo.toml +++ b/crates/workspace-hack/Cargo.toml @@ -27,7 +27,6 @@ config = { version = "0.14", default-features = false, features = ["ini", "json" crossbeam-utils = { version = "0.8" } either = { version = "1", default-features = false, features = ["use_std"] } fastrand = { version = "2" } -ffmpeg-sys-next = { version = "7", features = ["build"] } futures-channel = { version = "0.3", features = ["sink"] } futures-core = { version = "0.3" } futures-executor = { version = "0.3" } @@ -93,7 +92,6 @@ config = { version = "0.14", default-features = false, features = ["ini", "json" crossbeam-utils = { version = "0.8" } either = { version = "1", default-features = false, features = ["use_std"] } fastrand = { version = "2" } -ffmpeg-sys-next = { version = "7", features = ["build"] } futures-channel = { version = "0.3", features = ["sink"] } futures-core = { version = "0.3" } futures-executor = { version = "0.3" } diff --git a/docker/ffmpeg.sh b/docker/ffmpeg.sh deleted file mode 100755 index c647ad0d2..000000000 --- a/docker/ffmpeg.sh +++ /dev/null @@ -1,36 +0,0 @@ -set -ex - -apt-get update -apt-get install -y --no-install-recommends \ - tar \ - make \ - zip \ - unzip \ - curl \ - wget \ - git \ - ssh \ - ca-certificates \ - pkg-config \ - gnupg2 \ - cmake \ - clang-format \ - ninja-build \ - nasm \ - yasm \ - meson \ - libtool \ - autoconf \ - automake \ - build-essential \ - libpng-dev \ - libjpeg-dev \ - libtiff-dev \ - libpng16-16 \ - libjpeg62 \ - libtiff6 - - -git clone https://github.com/scufflecloud/external.git --depth 1 --recurse-submodule --shallow-submodules /tmp/external -/tmp/external/build.sh --prefix /usr/local --build "x264 x265 svt-av1 libvpx dav1d ffmpeg" -ldconfig diff --git a/docker/rust.sh b/docker/rust.sh deleted file mode 100755 index 42709394a..000000000 --- a/docker/rust.sh +++ /dev/null @@ -1,9 +0,0 @@ -set -ex - -apt-get update -apt-get install -y --no-install-recommends \ - build-essential \ - curl \ - ca-certificates - -curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile minimal