diff --git a/.cargo/config b/.cargo/config deleted file mode 100644 index d47f983..0000000 --- a/.cargo/config +++ /dev/null @@ -1,11 +0,0 @@ -[target.x86_64-apple-darwin] -rustflags = [ - "-C", "link-arg=-undefined", - "-C", "link-arg=dynamic_lookup", -] - -[target.aarch64-apple-darwin] -rustflags = [ - "-C", "link-arg=-undefined", - "-C", "link-arg=dynamic_lookup", -] diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..cc23b24 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,150 @@ +# This file is autogenerated by maturin v1.10.2 +# To update, run +# +# maturin generate-ci github --zig --platform manylinux macos -o .github/workflows/ci.yaml +# +name: CI + +on: + push: + branches: + - main + - master + tags: + - '*' + pull_request: + workflow_dispatch: + +permissions: + contents: read + +jobs: + linux: + runs-on: ${{ matrix.platform.runner }} + strategy: + matrix: + platform: + - runner: ubuntu-22.04 + target: x86_64 + - runner: ubuntu-22.04 + target: aarch64 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: 3.x + - name: Install FFmpeg 7.1.0 from source + run: | + sudo apt update + sudo apt install -y build-essential python3-dev python3-setuptools make cmake nasm yasm pkg-config + wget https://ffmpeg.org/releases/ffmpeg-7.1.tar.gz + tar -xzf ffmpeg-7.1.tar.gz + cd ffmpeg-7.1 + ./configure --prefix=/usr/local --enable-shared --disable-static + make -j$(nproc) + sudo make install + sudo ldconfig + cd .. + rm -rf ffmpeg-7.1 ffmpeg-7.1.tar.gz + - name: Build wheels + uses: PyO3/maturin-action@v1 + with: + target: ${{ matrix.platform.target }} + args: --release --out dist --zig + sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} + manylinux: auto + - name: Build free-threaded wheels + uses: PyO3/maturin-action@v1 + with: + target: ${{ matrix.platform.target }} + args: --release --out dist --zig -i python3.13t + sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} + manylinux: auto + - name: Upload wheels + uses: actions/upload-artifact@v4 + with: + name: wheels-linux-${{ matrix.platform.target }} + path: dist + + macos: + runs-on: ${{ matrix.platform.runner }} + strategy: + matrix: + platform: + - runner: macos-14 + target: aarch64 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: 3.x + - name: Install FFmpeg 7.1.0 from source + run: | + brew install nasm pkg-config + wget https://ffmpeg.org/releases/ffmpeg-7.1.tar.gz + tar -xzf ffmpeg-7.1.tar.gz + cd ffmpeg-7.1 + ./configure --prefix=/usr/local --enable-shared --disable-static + make -j$(sysctl -n hw.ncpu) + sudo make install + cd .. + rm -rf ffmpeg-7.1 ffmpeg-7.1.tar.gz + - name: Build wheels + uses: PyO3/maturin-action@v1 + with: + target: ${{ matrix.platform.target }} + args: --release --out dist + sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} + - name: Build free-threaded wheels + uses: PyO3/maturin-action@v1 + with: + target: ${{ matrix.platform.target }} + args: --release --out dist -i python3.13t + sccache: ${{ !startsWith(github.ref, 'refs/tags/') }} + - name: Upload wheels + uses: actions/upload-artifact@v4 + with: + name: wheels-macos-${{ matrix.platform.target }} + path: dist + + sdist: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Build sdist + uses: PyO3/maturin-action@v1 + with: + command: sdist + args: --out dist + - name: Upload sdist + uses: actions/upload-artifact@v4 + with: + name: wheels-sdist + path: dist + + release: + name: Release + runs-on: ubuntu-latest + if: ${{ startsWith(github.ref, 'refs/tags/') || github.event_name == 'workflow_dispatch' }} + needs: [linux, macos, sdist] + permissions: + # Use to sign the release artifacts + id-token: write + # Used to upload release artifacts + contents: write + # Used to generate artifact attestation + attestations: write + steps: + - uses: actions/download-artifact@v4 + - name: Generate artifact attestation + uses: actions/attest-build-provenance@v2 + with: + subject-path: 'wheels-*/*' + - name: Publish to PyPI + if: ${{ startsWith(github.ref, 'refs/tags/') }} + uses: PyO3/maturin-action@v1 + env: + MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_API_TOKEN }} + with: + command: upload + args: --non-interactive --skip-existing wheels-*/* diff --git a/.gitignore b/.gitignore index 00fbe40..2ff07d3 100644 --- a/.gitignore +++ b/.gitignore @@ -153,3 +153,6 @@ dmypy.json # Cython debug symbols cython_debug/ + +# MacOS files +.DS_Store diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6e14996..d29ae63 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,19 +1,23 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.2.0 + rev: v6.0.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer - id: check-yaml - id: check-toml - id: check-added-large-files + - id: mixed-line-ending + args: [ --fix=lf ] + exclude: "make.bat" - repo: https://github.com/doublify/pre-commit-rust rev: v1.0 hooks: - id: fmt - id: cargo-check - - repo: https://github.com/psf/black - rev: 22.3.0 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.14.10 hooks: - - id: black - language_version: python3 + - id: ruff + args: [--fix, --select, I] # I = isort (import sorting) + - id: ruff-format diff --git a/Cargo.lock b/Cargo.lock index 84163d6..17708f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,71 +1,76 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] [[package]] name = "autocfg" -version = "1.0.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "bindgen" -version = "0.54.0" +version = "0.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66c0bb6167449588ff70803f4127f0684f9063097eca5016f37eb52b92c2cf36" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" dependencies = [ "bitflags", "cexpr", - "cfg-if 0.1.10", "clang-sys", - "lazy_static", - "lazycell", - "peeking_take_while", + "itertools", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", + "syn", ] [[package]] name = "bitflags" -version = "1.3.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "cc" -version = "1.0.72" +version = "1.2.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +checksum = "7a0aeaff4ff1a90589618835a598e545176939b97874f7abc7851caa0618f203" +dependencies = [ + "find-msvc-tools", + "shlex", +] [[package]] name = "cexpr" -version = "0.4.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ "nom", ] [[package]] name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - -[[package]] -name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "clang-sys" -version = "0.29.3" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe6837df1d5cba2397b835c8530f51723267e16abbf83892e9e5af4f0e5dd10a" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", @@ -74,11 +79,10 @@ dependencies = [ [[package]] name = "crossbeam" -version = "0.8.1" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae5588f6b3c3cb05239e90bd110f257254aecd01e4635400391aeae07497845" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" dependencies = [ - "cfg-if 1.0.0", "crossbeam-channel", "crossbeam-deque", "crossbeam-epoch", @@ -88,63 +92,58 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.2" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e54ea8bc3fb1ee042f5aace6e3c6e025d3874866da222930f70ce62aceba0bfa" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ - "cfg-if 1.0.0", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.1" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ - "cfg-if 1.0.0", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.6" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97242a70df9b89a65d0b6df3c4bf5b9ce03c5b7309019777fbde37e7537f8762" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "cfg-if 1.0.0", "crossbeam-utils", - "lazy_static", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.3" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b979d76c9fcb84dffc80a73f7290da0f83e4c95773494674cb44b76d13a7a110" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ - "cfg-if 1.0.0", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.6" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcae03edb34f947e64acdb1c33ec169824e20657e9ecb61cef6c8c74dcb8120" -dependencies = [ - "cfg-if 1.0.0", - "lazy_static", -] +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" [[package]] name = "ffmpeg-next" -version = "4.4.0" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4676cda947a87a1e8a42e154059c567e75de64860252cce52c684acd8c074fa0" +checksum = "da02698288e0275e442a47fc12ca26d50daf0d48b15398ba5906f20ac2e2a9f9" dependencies = [ "bitflags", "ffmpeg-sys-next", @@ -153,9 +152,9 @@ dependencies = [ [[package]] name = "ffmpeg-sys-next" -version = "4.4.0" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de57234f2c49c6e093fe67bbbaa9142c228f6e2d5533ef27980993d5b6adef2a" +checksum = "f9e9c75ebd4463de9d8998fb134ba26347fe5faee62fabf0a4b4d41bd500b4ad" dependencies = [ "bindgen", "cc", @@ -166,55 +165,41 @@ dependencies = [ ] [[package]] -name = "glob" -version = "0.3.0" +name = "find-msvc-tools" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" +checksum = "645cbb3a84e60b7531617d5ae4e57f7e27308f6445f5abf653209ea76dec8dff" [[package]] -name = "hermit-abi" -version = "0.1.19" +name = "glob" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] -name = "indoc" -version = "0.3.6" +name = "heck" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47741a8bc60fb26eb8d6e0238bbb26d8575ff623fdc97b1a2c00c050b9684ed8" -dependencies = [ - "indoc-impl", - "proc-macro-hack", -] +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] -name = "indoc-impl" -version = "0.3.6" +name = "hermit-abi" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce046d161f000fffde5f432a0d034d0341dc152643b2598ed5bfce44c4f3a8f0" -dependencies = [ - "proc-macro-hack", - "proc-macro2", - "quote", - "syn", - "unindent", -] +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] -name = "instant" -version = "0.1.12" +name = "indoc" +version = "2.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" dependencies = [ - "cfg-if 1.0.0", + "rustversion", ] [[package]] name = "iterframes" -version = "0.3.0" +version = "0.4.0" dependencies = [ "crossbeam", "ffmpeg-next", @@ -222,72 +207,66 @@ dependencies = [ ] [[package]] -name = "lazy_static" -version = "1.4.0" +name = "itertools" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] [[package]] name = "libc" -version = "0.2.113" +version = "0.2.179" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eef78b64d87775463c549fbd80e19249ef436ea3bf1de2a1eb7e717ec7fab1e9" +checksum = "c5a2d376baa530d1238d133232d15e239abad80d05838b4b59354e5268af431f" [[package]] name = "libloading" -version = "0.5.2" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ - "cc", - "winapi", -] - -[[package]] -name = "lock_api" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" -dependencies = [ - "scopeguard", + "cfg-if", + "windows-link", ] [[package]] name = "memchr" -version = "2.4.1" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "memoffset" -version = "0.6.5" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" dependencies = [ "autocfg", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "nom" -version = "5.1.2" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", - "version_check", + "minimal-lexical", ] [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ "hermit-abi", "libc", @@ -295,112 +274,74 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.9.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" -dependencies = [ - "cfg-if 1.0.0", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi", -] - -[[package]] -name = "paste" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" -dependencies = [ - "paste-impl", - "proc-macro-hack", -] - -[[package]] -name = "paste-impl" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" -dependencies = [ - "proc-macro-hack", -] - -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "pkg-config" -version = "0.3.24" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] -name = "proc-macro-hack" -version = "0.5.19" +name = "portable-atomic" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" +checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" [[package]] name = "proc-macro2" -version = "1.0.36" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] name = "pyo3" -version = "0.15.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cf01dbf1c05af0a14c7779ed6f3aa9deac9c3419606ac9de537a2d649005720" +checksum = "ab53c047fcd1a1d2a8820fe84f05d6be69e9526be40cb03b73f86b6b03e6d87d" dependencies = [ - "cfg-if 1.0.0", "indoc", "libc", - "parking_lot", - "paste", + "memoffset", + "once_cell", + "portable-atomic", "pyo3-build-config", + "pyo3-ffi", "pyo3-macros", "unindent", ] [[package]] name = "pyo3-build-config" -version = "0.15.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf9e4d128bfbddc898ad3409900080d8d5095c379632fbbfbb9c8cfb1fb852b" +checksum = "b455933107de8642b4487ed26d912c2d899dec6114884214a0b3bb3be9261ea6" dependencies = [ - "once_cell", + "target-lexicon", +] + +[[package]] +name = "pyo3-ffi" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c85c9cbfaddf651b1221594209aed57e9e5cff63c4d11d1feead529b872a089" +dependencies = [ + "libc", + "pyo3-build-config", ] [[package]] name = "pyo3-macros" -version = "0.15.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67701eb32b1f9a9722b4bc54b548ff9d7ebfded011c12daece7b9063be1fd755" +checksum = "0a5b10c9bf9888125d917fb4d2ca2d25c8df94c7ab5a52e13313a07e050a3b02" dependencies = [ + "proc-macro2", "pyo3-macros-backend", "quote", "syn", @@ -408,10 +349,11 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.15.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f44f09e825ee49a105f2c7b23ebee50886a9aee0746f4dd5a704138a64b0218a" +checksum = "03b51720d314836e53327f5871d4c0cfb4fb37cc2c4a11cc71907a86342c40f9" dependencies = [ + "heck", "proc-macro2", "pyo3-build-config", "quote", @@ -420,36 +362,41 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.15" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] [[package]] -name = "redox_syscall" -version = "0.2.10" +name = "regex" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ - "bitflags", + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", ] [[package]] -name = "regex" -version = "1.5.4" +name = "regex-automata" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ + "aho-corasick", + "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "rustc-hash" @@ -458,45 +405,45 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] -name = "scopeguard" -version = "1.1.0" +name = "rustversion" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "shlex" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" - -[[package]] -name = "smallvec" -version = "1.8.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "syn" -version = "1.0.86" +version = "2.0.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +checksum = "21f182278bf2d2bcb3c88b1b08a37df029d71ce3d3ae26168e3c653b213b99d4" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] -name = "unicode-xid" -version = "0.2.2" +name = "target-lexicon" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1dd07eb858a2067e2f3c7155d54e929265c264e6f37efe3ee7a8d1b5a1dd0ba" + +[[package]] +name = "unicode-ident" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unindent" -version = "0.1.7" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f14ee04d9415b52b3aeab06258a3f07093182b88ba0f9b8d203f211a7a7d41c7" +checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" [[package]] name = "vcpkg" @@ -505,29 +452,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" diff --git a/Cargo.toml b/Cargo.toml index d310714..02a7999 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,18 +1,13 @@ [package] name = "iterframes" -version = "0.3.0" -authors = ["Alessio Sanfratello"] edition = "2021" -description = "Iterate on video frames quickly" -readme = "README.md" -homepage = "https://github.com/alesanfra/iterframes" -repository = "https://github.com/alesanfra/iterframes" - -[dependencies] -pyo3 = { version = "*", features = ["extension-module", "abi3-py36"] } -ffmpeg = { package = "ffmpeg-next", version = "*" } -crossbeam = "*" +version = "0.4.0" [lib] name = "iterframes" crate-type = ["cdylib"] + +[dependencies] +pyo3 = "*" +ffmpeg = { package = "ffmpeg-next", version = "=7.1.0" } +crossbeam = "*" diff --git a/Dockerfile b/Dockerfile index 335fc49..d72e06e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,72 +1,5 @@ -FROM konstin2/maturin:latest -ARG FFMPEG_VERSION="4.4" +FROM ubuntu:22.04 -# build tools -RUN echo "[1] Install dependencies" -RUN yum install -y autoconf automake bzip2 bzip2-devel clang freetype-devel gcc gcc-c++ git libtool make mercurial pkgconfig zlib-devel - -WORKDIR ~/ffmpeg_sources - -# nasm -RUN echo "[2] Install nasm" && \ - curl -O -L https://www.nasm.us/pub/nasm/releasebuilds/2.14.02/nasm-2.14.02.tar.gz && \ - tar xvfz nasm-2.14.02.tar.gz && \ - cd nasm-2.14.02 && \ - ./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin" && \ - make -j$(nproc) && \ - make install - -# yasm -RUN echo "[3] Install yasm" && \ - curl -O -L https://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz --insecure && \ - tar xzf yasm-1.3.0.tar.gz && \ - cd yasm-1.3.0 && \ - ./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin" && \ - make -j$(nproc) && \ - make install - -# libx264 -RUN echo "[4] Install libx264" && \ - git clone --depth 1 https://code.videolan.org/videolan/x264.git && \ - cd x264 && \ - export PATH="$HOME/bin:$PATH" && \ - PKG_CONFIG_PATH="$HOME/ffmpeg_build/lib/pkgconfig" ./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin" --enable-shared --enable-pic && \ - make -j$(nproc) && \ - make install - -# libvpx -RUN echo "[5] Install libvpx" && \ - git clone --depth 1 https://chromium.googlesource.com/webm/libvpx.git && \ - cd libvpx && \ - export PATH="$HOME/bin:$PATH" && \ - ./configure --prefix="$HOME/ffmpeg_build" --disable-examples --disable-unit-tests --enable-vp9-highbitdepth --as=yasm --enable-shared --enable-pic && \ - make -j$(nproc) && \ - make install - -# ffmpeg -RUN echo "[6] Install ffmpeg" && \ - curl -O -L https://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2 && \ - tar xjf ffmpeg-$FFMPEG_VERSION.tar.bz2 && \ - cd ffmpeg-$FFMPEG_VERSION && \ - export PATH="$HOME/bin:$PATH" && \ - PKG_CONFIG_PATH="$HOME/ffmpeg_build/lib/pkgconfig" ./configure \ - --prefix="$HOME/ffmpeg_build" \ - --extra-cflags="-I$HOME/ffmpeg_build/include" \ - --extra-ldflags="-L$HOME/ffmpeg_build/lib" \ - --extra-libs=-lpthread \ - --extra-libs=-lm \ - --bindir="$HOME/bin" \ - --enable-gpl \ - --enable-libvpx \ - --enable-libx264 \ - --enable-nonfree \ - --disable-static \ - --enable-shared \ - --enable-pic && \ - make -j$(nproc) && \ - make install - -ENV FFMPEG_DIR "/root/ffmpeg_build" -ENV LD_LIBRARY_PATH /root/ffmpeg_build/lib:$LD_LIBRARY_PATH - -WORKDIR /io +RUN \ + && apt update + && apt install -y build-essential python3-dev python3-setuptools make cmake ffmpeg libavcodec-dev libavfilter-dev libavformat-dev libavutil-dev libswresample-dev diff --git a/iterframes/__init__.py b/iterframes/__init__.py index bd7e1c8..d543b3d 100644 --- a/iterframes/__init__.py +++ b/iterframes/__init__.py @@ -2,7 +2,8 @@ import numpy as _np -from .iterframes import FrameReader as _FrameReader, read_batch +from .iterframes import FrameReader as _FrameReader +from .iterframes import read_batch def read( diff --git a/pyproject.toml b/pyproject.toml index 6ab2b2b..0481ad9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,15 @@ [build-system] -requires = ["maturin>=0.12,<1.0"] +requires = ["maturin>=1.9,<2.0"] build-backend = "maturin" [project] name = "iterframes" -requires-python = ">=3.6" +description = "Iterate on video frames quickly" +authors = [ + { name = "Alessio Sanfratello", email = "sanfra90@gmail.com" }, +] +readme = "README.md" +requires-python = ">=3.9" classifiers = [ "Intended Audience :: Science/Research", "Programming Language :: Python :: 3", @@ -12,14 +17,24 @@ classifiers = [ "Programming Language :: Rust", "Topic :: Multimedia :: Video", ] +dynamic = ["version"] dependencies = [ "numpy>=1.16.0", ] -[tool.black] -target_version = ["py36"] +[project.urls] +Homepage = "https://github.com/alesanfra/iterframes" +Source = "https://github.com/alesanfra/iterframes" + +[tool.maturin] +features = ["pyo3/extension-module", "pyo3/abi3-py39"] + +[tool.ruff] line-length = 79 -[tool.isort] -profile = "black" -line_length = 79 +[tool.ruff.lint] +select = ["E", "F", "I"] # Enable pycodestyle errors, pyflakes, and isort +fixable = ["ALL"] + +[tool.ruff.lint.isort] +known-first-party = ["iterframes"] diff --git a/scripts/build_macos.sh b/scripts/build_macos.sh index 2d8a70a..a7f6439 100644 --- a/scripts/build_macos.sh +++ b/scripts/build_macos.sh @@ -6,7 +6,7 @@ echo "Build wheel" maturin build --strip --release echo "Fix shared libs" -delocate-wheel -v target/wheels/iterframes-*-abi3-macosx_10_7_x86_64.whl +delocate-wheel -v target/wheels/iterframes-*-abi3-macosx_*.whl echo "Check wheel" -delocate-listdeps target/wheels/iterframes-*-abi3-macosx_10_7_x86_64.whl +delocate-listdeps target/wheels/iterframes-*-abi3-macosx_*.whl diff --git a/src/decoder.rs b/src/decoder.rs index 1bb411a..808ef22 100644 --- a/src/decoder.rs +++ b/src/decoder.rs @@ -44,7 +44,8 @@ fn decode_video( .ok_or(ffmpeg::Error::StreamNotFound)?; let video_stream_index = input.index(); - let mut decoder = input.codec().decoder().video()?; + let context_decoder = ffmpeg::codec::context::Context::from_parameters(input.parameters())?; + let mut decoder = context_decoder.decoder().video()?; let mut scaler = Context::get( decoder.format(), @@ -98,7 +99,8 @@ pub fn decode_all_video( .unwrap(); let video_stream_index = input.index(); - let mut decoder = input.codec().decoder().video().unwrap(); + let context_decoder = ffmpeg::codec::context::Context::from_parameters(input.parameters())?; + let mut decoder = context_decoder.decoder().video()?; let mut scaler = Context::get( decoder.format(), diff --git a/src/lib.rs b/src/lib.rs index 0f94332..4119d33 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,14 +1,12 @@ use crossbeam::channel::Receiver; use ffmpeg::frame::Video; use pyo3::exceptions::PyRuntimeError; -use pyo3::iter::IterNextOutput; use pyo3::prelude::*; use pyo3::types::PyByteArray; -use pyo3::PyIterProtocol; mod decoder; -#[pyclass(module = "iterframes")] +#[pyclass] pub struct Frame { #[pyo3(get)] buffer: Py, @@ -23,7 +21,7 @@ pub struct Frame { stride: usize, } -#[pyclass(module = "iterframes")] +#[pyclass] pub struct FrameReader { channel: Receiver>, } @@ -41,23 +39,20 @@ impl FrameReader { channel: decoder::start(path, height, width, prefetch_frames), } } -} -#[pyproto] -impl PyIterProtocol for FrameReader { fn __iter__(self_: PyRef) -> PyRef { self_ } - fn __next__(self_: PyRefMut) -> IterNextOutput { + fn __next__(self_: PyRefMut) -> Option { match self_.channel.recv() { - Ok(Some(frame)) => IterNextOutput::Yield(Frame { + Ok(Some(frame)) => Some(Frame { buffer: PyByteArray::new(self_.py(), &frame.data(0)).into(), height: frame.height() as usize, width: frame.width() as usize, stride: frame.stride(0), }), - _ => IterNextOutput::Return(()), + _ => None, } } } @@ -86,7 +81,7 @@ fn read_batch( /// Process quickly all videos in the world, one frame at time. #[pymodule] -fn iterframes(_py: Python, module: &PyModule) -> PyResult<()> { +fn iterframes(_py: Python, module: &Bound<'_, PyModule>) -> PyResult<()> { module.add("__version__", env!("CARGO_PKG_VERSION"))?; module.add_class::()?; module.add_class::()?; diff --git a/tests/benchmark/test_benchmark_decord.py b/tests/benchmark/test_benchmark_decord.py index 7cb017b..5e4bdce 100644 --- a/tests/benchmark/test_benchmark_decord.py +++ b/tests/benchmark/test_benchmark_decord.py @@ -1,3 +1,4 @@ +import platform import timeit import numpy as np @@ -5,6 +6,11 @@ from iterframes import read +# Skip all tests in this module on macOS +pytestmark = pytest.mark.skipif( + platform.system() == "Darwin", reason="Decord tests are skipped on macOS" +) + def test_same_behavior_as_decord(video_path): from decord import VideoReader