From 7f4b252a2164a68ebd0ba27638ff4a031f04d6ab Mon Sep 17 00:00:00 2001 From: Luni-4 Date: Wed, 27 Nov 2019 13:58:37 +0100 Subject: [PATCH] Add cargo-c to metrics --- .github/workflows/ci-build.yml | 26 +- Cargo.lock | 170 ++++++------- av_metrics/Cargo.toml | 5 + av_metrics/c-example/test.c | 73 ++++++ av_metrics/cbindgen.toml | 7 + av_metrics/src/capi.rs | 381 +++++++++++++++++++++++++++++ av_metrics/src/lib.rs | 6 + av_metrics/src/video/decode/mod.rs | 4 + av_metrics/src/video/decode/y4m.rs | 14 ++ rustfmt.toml | 1 + 10 files changed, 600 insertions(+), 87 deletions(-) create mode 100644 av_metrics/c-example/test.c create mode 100644 av_metrics/cbindgen.toml create mode 100644 av_metrics/src/capi.rs create mode 100644 rustfmt.toml diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 076f7ef..02e7b0e 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -1,10 +1,10 @@ name: ci on: - pull_request: + push: branches: - master - push: + pull_request: branches: - master @@ -37,6 +37,28 @@ jobs: args: --all-features --tests --benches name: lint + cargo-c: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + - name: Install cargo-c + run: | + cargo install cargo-c + - name: Run cargo-c + run: | + cargo cinstall --all-features \ + --prefix=$HOME/av_metrics_deploy + - name: Build cargo-c tests + run: | + export PKG_CONFIG_PATH=$HOME/av_metrics_deploy/lib/pkgconfig + cd av_metrics/c-example + gcc test.c -o test `pkg-config --static --cflags --libs av_metrics` + - name: Run tests + run: | + export LD_LIBRARY_PATH=$HOME/av_metrics_deploy/lib/ + cd av_metrics/c-example + ./test + build: strategy: matrix: diff --git a/Cargo.lock b/Cargo.lock index cdbc225..c43e5b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,26 +8,18 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "arrayvec" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "atty" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "autocfg" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -38,6 +30,7 @@ dependencies = [ "err-derive 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "lab 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "y4m 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -63,7 +56,7 @@ dependencies = [ [[package]] name = "bitflags" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -84,8 +77,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cast" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "cfg-if" @@ -99,7 +95,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -112,7 +108,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "criterion-plot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -122,7 +118,7 @@ dependencies = [ "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -135,45 +131,46 @@ name = "criterion-plot" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-deque" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-epoch" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-queue" -version = "0.1.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-utils" -version = "0.6.6" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -186,7 +183,7 @@ dependencies = [ "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -209,23 +206,31 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "getrandom" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hermit-abi" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itertools" version = "0.8.2" @@ -251,7 +256,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.62" +version = "0.2.65" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -264,36 +269,32 @@ name = "memchr" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "memoffset" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "nodrop" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "num-traits" version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num_cpus" -version = "1.10.1" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -301,14 +302,14 @@ name = "proc-macro-error" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "proc-macro2" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -319,7 +320,7 @@ name = "quote" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -327,7 +328,7 @@ name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -335,7 +336,7 @@ name = "rand_os" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -349,24 +350,24 @@ dependencies = [ [[package]] name = "rayon" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rayon-core" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -387,7 +388,7 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -429,9 +430,9 @@ name = "serde_derive" version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -440,7 +441,7 @@ version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -451,22 +452,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "1.0.5" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "synstructure" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -551,49 +552,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" -"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" +"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" "checksum av-metrics 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0027ac3bfe1c66bca504615d567410a8bb7384dab735c9c18c99b88665e9bea" -"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2" +"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" -"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" +"checksum cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "938703e165481c8d612ea3479ac8342e5615185db37765162e762ec3523e2fc6" "checksum criterion-plot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eccdc6ce8bbe352ca89025bee672aa6d24f4eb8c53e3a8b5d1bc58011da072a2" -"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" -"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" -"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" -"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" +"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" +"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" +"checksum crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfd6515864a82d2f877b42813d4553292c6659498c9a2aa31bab5a15243c2700" +"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" "checksum csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37519ccdfd73a75821cac9319d4fce15a81b9fcf75f951df5b9988aa3a0af87d" "checksum csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9b5cadb6b25c77aeff80ba701712494213f4a8418fcda2ee11b6560c3ad0bf4c" "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" "checksum err-derive 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ead97ef6ef5530312e584d24b1ef31e96455bc2135945109fc737fe8b62ff4a5" -"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" +"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" +"checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" "checksum itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum lab 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bcb6fe1d958d9c2a4298cb5024381522038952ebd0fd3af60d00d3844813c93c" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" +"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" "checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" -"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" -"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" +"checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" "checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" -"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" +"checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" "checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" -"checksum proc-macro2 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afdc77cc74ec70ed262262942ebb7dac3d479e9e5cfa2da1841c0806f6cdabcc" +"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" "checksum rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a788ae3edb696cfcba1c19bfd388cc4b8c21f8a408432b199c072825084da58a" "checksum rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e18c91676f670f6f0312764c759405f13afb98d5d73819840cf72a518487bff" -"checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123" -"checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b" +"checksum rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43739f8831493b276363637423d3622d4bd6394ab6f0a9c4a552e208aeb7fddd" +"checksum rayon-core 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8bf17de6f23b05473c437eb958b9c850bfc8af0961fe17b4cc92d5a627b4791" "checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" +"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" "checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" @@ -602,8 +602,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "a8c6faef9a2e64b0064f48570289b4bf8823b7581f1d6157c1b52152306651d0" "checksum serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)" = "1a3351dcbc1f067e2c92ab7c3c1f288ad1a4cffc470b5aaddb4c2e0a3ae80043" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" -"checksum synstructure 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203" +"checksum syn 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "661641ea2aa15845cddeb97dad000d22070bb5c1fb456b96c1cba883ec691e92" +"checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4574b75faccaacddb9b284faecdf0b544b80b6b294f3d062d325c5726a209c20" "checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" diff --git a/av_metrics/Cargo.toml b/av_metrics/Cargo.toml index ef21454..c7513c4 100644 --- a/av_metrics/Cargo.toml +++ b/av_metrics/Cargo.toml @@ -11,6 +11,7 @@ repository = "https://github.com/rust-av/av-metrics" err-derive = "0.2.1" itertools = "0.8.2" lab = "0.7.2" +libc = "0.2" num-traits = "0.2" serde = { version = "1", features = ["derive"], optional = true } y4m = { version = "0.4", optional = true } @@ -27,3 +28,7 @@ bench = [] [[bench]] name = "bench" harness = false + +[lib] +name = "av_metrics" +crate-type = ["lib", "staticlib"] diff --git a/av_metrics/c-example/test.c b/av_metrics/c-example/test.c new file mode 100644 index 0000000..bf2005b --- /dev/null +++ b/av_metrics/c-example/test.c @@ -0,0 +1,73 @@ +#include + +#include + +#define CREATE_METRICS(func, metrics) \ + void test_ ## func(int frame) { \ + const char video_path1[] = "../testfiles/yuv444p8_input.y4m"; \ + const char video_path2[] = "../testfiles/yuv444p8_output.y4m"; \ + const MetricContext *val = calculate_ ## func(&video_path1[0], \ + &video_path2[0], frame); \ + \ + printf("%s - Y: %f U: %f V: %f Avg: %f\n", \ + metrics, val->y, val->u, val->v, val->avg); \ + \ + drop_context(val); \ + } + +#define CREATE_CIEDE_METRICS(func) \ + void test_ ## func(int frame) { \ + const char video_path1[] = "../testfiles/yuv444p8_input.y4m"; \ + const char video_path2[] = "../testfiles/yuv444p8_output.y4m"; \ + double val = calculate_ ## func(&video_path1[0], \ + &video_path2[0], frame); \ + \ + printf("CIEDE2000 - %f\n", val); \ + } + +#define TEST_VIDEO_METRICS(frame) \ + do { \ + printf("\n\nLimit: %d\n\n", frame); \ + test_video_psnr(frame); \ + test_video_apsnr(frame); \ + test_video_psnr_hvs(frame); \ + test_video_ssim(frame); \ + test_video_msssim(frame); \ + test_video_ciede(frame); \ + } while(0) + +#define TEST_FRAME_METRICS(frame) \ + do { \ + printf("\n\nFrame: %d\n\n", frame); \ + test_frame_psnr(frame); \ + test_frame_psnr_hvs(frame); \ + test_frame_ssim(frame); \ + test_frame_msssim(frame); \ + test_frame_ciede(frame); \ + } while(0) + +CREATE_METRICS(video_psnr, "PSNR"); +CREATE_METRICS(video_apsnr, "APSNR"); +CREATE_METRICS(video_psnr_hvs, "PSNR_HVS"); +CREATE_METRICS(video_ssim, "SSIM"); +CREATE_METRICS(video_msssim, "MSSSIM"); +CREATE_CIEDE_METRICS(video_ciede); + +CREATE_METRICS(frame_psnr, "PSNR"); +CREATE_METRICS(frame_psnr_hvs, "PSNR_HVS"); +CREATE_METRICS(frame_ssim, "SSIM"); +CREATE_METRICS(frame_msssim, "MSSSIM"); +CREATE_CIEDE_METRICS(frame_ciede); + +int main() { + + // Test metrics on videos + TEST_VIDEO_METRICS(0); + TEST_VIDEO_METRICS(2); + + // Test metrics on frames + TEST_FRAME_METRICS(0); + TEST_FRAME_METRICS(2); + + return 0; +} diff --git a/av_metrics/cbindgen.toml b/av_metrics/cbindgen.toml new file mode 100644 index 0000000..2dbf0fe --- /dev/null +++ b/av_metrics/cbindgen.toml @@ -0,0 +1,7 @@ +header = "// SPDX-License-Identifier: MIT" +sys_includes = ["stddef.h", "stdint.h", "stdlib.h"] +no_includes = true +include_guard = "AV_METRICS" +tab_width = 4 +style = "Type" +language = "C" diff --git a/av_metrics/src/capi.rs b/av_metrics/src/capi.rs new file mode 100644 index 0000000..c8463bd --- /dev/null +++ b/av_metrics/src/capi.rs @@ -0,0 +1,381 @@ +#![allow(dead_code)] + +extern crate libc; + +use libc::c_char; +use std::ffi::CStr; +use std::fs::File; +use std::path::{Path, PathBuf}; +use std::ptr::null; + +use crate::video::*; + +#[derive(Debug, Clone, Copy)] +enum InputType { + Video(VideoContainer), + Unknown, +} + +impl InputType { + pub fn detect>(filename: P) -> Self { + let ext = filename + .as_ref() + .extension() + .and_then(|ext| ext.to_str()) + .unwrap_or(""); + match ext.to_lowercase().as_str() { + "y4m" => InputType::Video(VideoContainer::Y4M), + _ => InputType::Unknown, + } + } +} + +#[derive(Debug, Clone, Copy)] +enum VideoContainer { + Y4M, +} + +impl VideoContainer { + pub fn get_decoder<'d>(&self, file: &'d mut File, metric: &str) -> y4m::Decoder<'d, File> { + match *self { + VideoContainer::Y4M => y4m::Decoder::new(file) + .expect(&("Failed to decode the ".to_owned() + metric + " y4m file")), + } + } +} + +#[inline(always)] +fn convert_c_string_into_path(c_buf: *const c_char) -> PathBuf { + let c_str = unsafe { CStr::from_ptr(c_buf) }; + Path::new(c_str.to_str().unwrap()).to_path_buf() +} + +#[inline(always)] +fn run_metric( + path1: *const c_char, + path2: *const c_char, + frame_limit: usize, + metric: &str, + is_frame: bool, +) -> (*const MetricContext, f64) { + if path1.is_null() || path2.is_null() { + return (null(), -1.0); + } + + let path1 = convert_c_string_into_path(path1); + let path2 = convert_c_string_into_path(path2); + + let input_type1 = InputType::detect(&path1); + let input_type2 = InputType::detect(&path2); + + match (input_type1, input_type2) { + (InputType::Video(c1), InputType::Video(c2)) => { + if is_frame { + return run_frame_metric(path1, c1, path2, c2, frame_limit, metric); + } else { + return run_video_metric(path1, c1, path2, c2, frame_limit, metric); + } + } + (InputType::Unknown, _) | (_, InputType::Unknown) => {} + } + + (null(), -1.0) +} + +#[inline(always)] +fn run_video_metric>( + path1: P, + container1: VideoContainer, + path2: P, + container2: VideoContainer, + frame_limit: usize, + metric: &str, +) -> (*const MetricContext, f64) { + let mut file1 = + File::open(path1).expect(&("Error opening the first ".to_owned() + metric + " video")); + let mut file2 = + File::open(path2).expect(&("Error opening the second ".to_owned() + metric + " video")); + + let mut dec1 = container1.get_decoder(&mut file1, &("first".to_owned() + metric)); + let mut dec2 = container2.get_decoder(&mut file2, &("second".to_owned() + metric)); + + let mut limit: Option = None; + if frame_limit > 0 { + limit = Some(frame_limit); + } + if metric == "ciede" { + let val = ciede::calculate_video_ciede(&mut dec1, &mut dec2, limit); + if let Ok(metric) = val { + return (null(), metric); + } + } + let val = match metric { + "psnr" => psnr::calculate_video_psnr(&mut dec1, &mut dec2, limit), + "apsnr" => psnr::calculate_video_apsnr(&mut dec1, &mut dec2, limit), + "psnr_hvs" => psnr_hvs::calculate_video_psnr_hvs(&mut dec1, &mut dec2, limit), + "ssim" => ssim::calculate_video_ssim(&mut dec1, &mut dec2, limit), + _ => ssim::calculate_video_msssim(&mut dec1, &mut dec2, limit), + }; + if let Ok(metric) = val { + let ctx = MetricContext { + y: metric.y, + u: metric.u, + v: metric.v, + avg: metric.avg, + }; + let boxed = Box::new(ctx); + return (Box::into_raw(boxed), 0.0); + } + (null(), -1.0) +} + +#[inline(always)] +fn run_frame_metric>( + path1: P, + container1: VideoContainer, + path2: P, + container2: VideoContainer, + frame_number: usize, + metric: &str, +) -> (*const MetricContext, f64) { + let mut file1 = + File::open(path1).expect(&("Error opening the first ".to_owned() + metric + " video")); + let mut file2 = + File::open(path2).expect(&("Error opening the second ".to_owned() + metric + " video")); + + let mut dec1 = container1.get_decoder(&mut file1, &("first".to_owned() + metric)); + let mut dec2 = container2.get_decoder(&mut file2, &("second".to_owned() + metric)); + + if dec1.get_bit_depth() > 8 { + let frame1 = dec1.read_specific_frame::(frame_number); + let frame2 = dec2.read_specific_frame::(frame_number); + if let Ok(frame1) = frame1 { + if let Ok(frame2) = frame2 { + if metric == "ciede" { + let val = ciede::calculate_frame_ciede(&frame1, &frame2); + if let Ok(metric) = val { + return (null(), metric); + } + } + let val = match metric { + "psnr" => psnr::calculate_frame_psnr(&frame1, &frame2), + "psnr_hvs" => psnr_hvs::calculate_frame_psnr_hvs(&frame1, &frame2), + "ssim" => ssim::calculate_frame_ssim(&frame1, &frame2), + _ => ssim::calculate_frame_msssim(&frame1, &frame2), + }; + if let Ok(metric) = val { + let ctx = MetricContext { + y: metric.y, + u: metric.u, + v: metric.v, + avg: metric.avg, + }; + let boxed = Box::new(ctx); + return (Box::into_raw(boxed), 0.0); + } + } + } + } else { + let frame1 = dec1.read_specific_frame::(frame_number); + let frame2 = dec2.read_specific_frame::(frame_number); + if let Ok(frame1) = frame1 { + if let Ok(frame2) = frame2 { + if metric == "ciede" { + let val = ciede::calculate_frame_ciede(&frame1, &frame2); + if let Ok(metric) = val { + return (null(), metric); + } + } + let val = match metric { + "psnr" => psnr::calculate_frame_psnr(&frame1, &frame2), + "psnr_hvs" => psnr_hvs::calculate_frame_psnr_hvs(&frame1, &frame2), + "ssim" => ssim::calculate_frame_ssim(&frame1, &frame2), + _ => ssim::calculate_frame_msssim(&frame1, &frame2), + }; + if let Ok(metric) = val { + let ctx = MetricContext { + y: metric.y, + u: metric.u, + v: metric.v, + avg: metric.avg, + }; + let boxed = Box::new(ctx); + return (Box::into_raw(boxed), 0.0); + } + } + } + } + (null(), -1.0) +} + +/// Metric Context +/// +/// This struct contains the data returned by a metric +#[repr(C)] +pub struct MetricContext { + /// Metric value for the Y plane. + pub y: f64, + /// Metric value for the U/Cb plane. + pub u: f64, + /// Metric value for the V/Cb plane. + pub v: f64, + /// Weighted average of the three planes. + pub avg: f64, +} + +/// Calculate the `psnr` metric between two videos +/// +/// Returns either `NULL` or a newly allocated `MetricContext` +#[no_mangle] +pub unsafe extern fn calculate_video_psnr( + video1_path: *const c_char, + video2_path: *const c_char, + frame_limit: usize, +) -> *const MetricContext { + let (metric, _) = run_metric(video1_path, video2_path, frame_limit, "psnr", false); + + metric +} + +/// Calculate the `apsnr` metric between two videos +/// +/// Returns either `NULL` or a newly allocated `MetricContext` +#[no_mangle] +pub unsafe extern fn calculate_video_apsnr( + video1_path: *const c_char, + video2_path: *const c_char, + frame_limit: usize, +) -> *const MetricContext { + let (metric, _) = run_metric(video1_path, video2_path, frame_limit, "apsnr", false); + + metric +} + +/// Calculate the `psnr_hvs` metric between two videos +/// +/// Returns either `NULL` or a newly allocated `MetricContext` +#[no_mangle] +pub unsafe extern fn calculate_video_psnr_hvs( + video1_path: *const c_char, + video2_path: *const c_char, + frame_limit: usize, +) -> *const MetricContext { + let (metric, _) = run_metric(video1_path, video2_path, frame_limit, "psnr_hvs", false); + + metric +} + +/// Calculate the `ssim` metric between two videos +/// +/// Returns either `NULL` or a newly allocated `MetricContext` +#[no_mangle] +pub unsafe extern fn calculate_video_ssim( + video1_path: *const c_char, + video2_path: *const c_char, + frame_limit: usize, +) -> *const MetricContext { + let (metric, _) = run_metric(video1_path, video2_path, frame_limit, "ssim", false); + + metric +} + +/// Calculate the `msssim` metric between two videos +/// +/// Returns either `NULL` or a newly allocated `MetricContext` +#[no_mangle] +pub unsafe extern fn calculate_video_msssim( + video1_path: *const c_char, + video2_path: *const c_char, + frame_limit: usize, +) -> *const MetricContext { + let (metric, _) = run_metric(video1_path, video2_path, frame_limit, "msssim", false); + + metric +} + +/// Calculate the `ciede` metric between two videos +/// +/// Returns the correct `ciede` value or `-1` on errors +#[no_mangle] +pub unsafe extern fn calculate_video_ciede( + video1_path: *const c_char, + video2_path: *const c_char, + frame_limit: usize, +) -> f64 { + let (_, value) = run_metric(video1_path, video2_path, frame_limit, "ciede", false); + + value +} + +/// Calculate the `psnr` metric between two frames +/// +/// Returns either `NULL` or a newly allocated `MetricContext` +#[no_mangle] +pub unsafe extern fn calculate_frame_psnr( + video1_path: *const c_char, + video2_path: *const c_char, + frame_number: usize, +) -> *const MetricContext { + let (metric, _) = run_metric(video1_path, video2_path, frame_number, "psnr", true); + metric +} + +/// Calculate the `psnr_hvs` metric between two frames +/// +/// Returns either `NULL` or a newly allocated `MetricContext` +#[no_mangle] +pub unsafe extern fn calculate_frame_psnr_hvs( + video1_path: *const c_char, + video2_path: *const c_char, + frame_number: usize, +) -> *const MetricContext { + let (metric, _) = run_metric(video1_path, video2_path, frame_number, "psnr_hvs", true); + metric +} + +/// Calculate the `ssim` metric between two frames +/// +/// Returns either `NULL` or a newly allocated `MetricContext` +#[no_mangle] +pub unsafe extern fn calculate_frame_ssim( + video1_path: *const c_char, + video2_path: *const c_char, + frame_number: usize, +) -> *const MetricContext { + let (metric, _) = run_metric(video1_path, video2_path, frame_number, "ssim", true); + metric +} + +/// Calculate the `msssim` metric between two frames +/// +/// Returns either `NULL` or a newly allocated `MetricContext` +#[no_mangle] +pub unsafe extern fn calculate_frame_msssim( + video1_path: *const c_char, + video2_path: *const c_char, + frame_number: usize, +) -> *const MetricContext { + let (metric, _) = run_metric(video1_path, video2_path, frame_number, "msssim", true); + metric +} + +/// Calculate the `ciede` metric between two frames +/// +/// Returns the correct `ciede` value or `-1` on errors +#[no_mangle] +pub unsafe extern fn calculate_frame_ciede( + video1_path: *const c_char, + video2_path: *const c_char, + frame_number: usize, +) -> f64 { + let (_, value) = run_metric(video1_path, video2_path, frame_number, "ciede", true); + value +} + +/// Drop the metric context +/// +/// This function drops the context and free the memory +#[no_mangle] +pub unsafe extern fn drop_context(ctx: *const MetricContext) { + std::mem::drop(Box::from_raw(ctx as *mut MetricContext)); +} diff --git a/av_metrics/src/lib.rs b/av_metrics/src/lib.rs index 67e9ca0..08fc868 100644 --- a/av_metrics/src/lib.rs +++ b/av_metrics/src/lib.rs @@ -14,6 +14,12 @@ extern crate itertools; pub mod video; +#[cfg(cargo_c)] +mod capi; + +#[cfg(cargo_c)] +pub use capi::*; + /// Possible errors that may occur during processing of a metric. /// /// This enum may be added to in the future and should not be assumed to be exhaustive. diff --git a/av_metrics/src/video/decode/mod.rs b/av_metrics/src/video/decode/mod.rs index 2669212..a6f1db5 100644 --- a/av_metrics/src/video/decode/mod.rs +++ b/av_metrics/src/video/decode/mod.rs @@ -17,6 +17,10 @@ pub trait Decoder { /// /// Expected to return `Err` if the end of the video is reached. fn read_video_frame(&mut self) -> Result, ()>; + /// Read a specific frame from the input video + /// + /// Expected to return `Err` if the frame is not found. + fn read_specific_frame(&mut self, frame_number: usize) -> Result, ()>; /// Get the bit depth of the video. fn get_bit_depth(&self) -> usize; } diff --git a/av_metrics/src/video/decode/y4m.rs b/av_metrics/src/video/decode/y4m.rs index 39b8381..e65700f 100644 --- a/av_metrics/src/video/decode/y4m.rs +++ b/av_metrics/src/video/decode/y4m.rs @@ -80,6 +80,20 @@ impl Decoder for y4m::Decoder<'_, R> { .map_err(|_| ()) } + fn read_specific_frame(&mut self, frame_number: usize) -> Result, ()> { + let mut frame_no = 0; + while frame_no <= frame_number { + let frame = self.read_video_frame(); + if frame_no == frame_number { + if let Ok(frame) = frame { + return Ok(frame); + } + } + frame_no += 1; + } + Err(()) + } + fn get_bit_depth(&self) -> usize { self.get_bit_depth() } diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..8dc0f76 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1 @@ +force_explicit_abi = false