diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c14f861..39f0343 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,23 +21,28 @@ permissions: jobs: linux: - runs-on: ubuntu-latest strategy: matrix: include: - docker_file: docker/Dockerfile.manylinux_2_28_ARM64 name: manylinux-arm arch: linux/arm64 + runner: ARM64 - docker_file: docker/Dockerfile.manylinux_2_28_X64 name: manylinux-x86 arch: linux/amd64 - - docker_file: docker/Dockerfile.u2004 + runner: X86 + - docker_file: docker/Dockerfile.u2204 name: native-arm arch: linux/arm64 - - docker_file: docker/Dockerfile.u2004 + runner: ARM64 + - docker_file: docker/Dockerfile.u2204 name: native-x86 arch: linux/amd64 - + runner: X86 + runs-on: + - self-hosted + - ${{ matrix.runner }} steps: - uses: actions/checkout@v3 diff --git a/Cargo.toml b/Cargo.toml index bf86cb2..ec1c262 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ repository = "https://github.com/insight-platform/FFmpeg-Input" readme = "README.md" keywords = ["FFmpeg", "Video"] categories = ["computer-vision"] -version = "0.1.21" +version = "0.1.22" edition = "2021" license="Apache-2.0" rust-version = "1.62" @@ -18,19 +18,20 @@ crate-type = ["cdylib", "lib"] [dependencies] crossbeam = "0.8" log = "0.4" -env_logger = "0.10" +env_logger = "0.11" +parking_lot = "0.12" [dependencies.ffmpeg-next] -git = "https://github.com/insight-platform/rust-ffmpeg.git" -branch = "master" +version = "6" features = ["default"] [dependencies.pyo3] -version = "0.19" +version = "0.20" features = ["extension-module"] +[build-dependencies] +pyo3-build-config = { version = "0.20"} + [profile.release] opt-level = 3 - -[features] -rpi = ["ffmpeg-next/rpi"] +codegen-units = 1 diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..dace4a9 --- /dev/null +++ b/build.rs @@ -0,0 +1,3 @@ +fn main() { + pyo3_build_config::add_extension_module_link_args(); +} diff --git a/docker/Dockerfile.manylinux_2_28_ARM64 b/docker/Dockerfile.manylinux_2_28_ARM64 index f3d6c9a..de73d14 100644 --- a/docker/Dockerfile.manylinux_2_28_ARM64 +++ b/docker/Dockerfile.manylinux_2_28_ARM64 @@ -1,31 +1,6 @@ -FROM quay.io/pypa/manylinux_2_28_aarch64 as base +FROM ghcr.io/insight-platform/manylinux_2_28_arm64:v0.0.3 as builder -RUN dnf install -y epel-release -# RUN dnf config-manager --set-enabled crb -RUN dnf install -y --nogpgcheck https://download1.rpmfusion.org/free/el/rpmfusion-free-release-8.noarch.rpm -RUN dnf install -y --nogpgcheck https://download1.rpmfusion.org/nonfree/el/rpmfusion-nonfree-release-8.noarch.rpm -RUN dnf install -y ffmpeg ffmpeg-devel -RUN dnf install -y clang clang-devel -ENV PATH="/root/.cargo/bin:/opt/python/cp37-cp37m/bin:/opt/python/cp38-cp38/bin:/opt/python/cp39-cp39/bin:/opt/python/cp310-cp310/bin:/opt/python/cp311-cp311/bin:/opt/python/cp312-cp312/bin:$PATH" -RUN pip3 install maturin==0.15 patchelf cffi ziglang sccache>=0.4.0 - -WORKDIR /opt -COPY docker/install-basic-deps-manylinux.sh . -RUN bash /opt/install-basic-deps-manylinux.sh - -FROM base as chef -ENV PATH="/root/.cargo/bin:$PATH" -RUN rustc -V - -FROM chef AS planner -WORKDIR /opt -COPY . . -RUN cargo chef prepare --recipe-path recipe.json - -FROM chef AS builder WORKDIR /opt -COPY --from=planner /opt/recipe.json recipe.json -RUN cargo chef cook --release --recipe-path recipe.json COPY . . ENV LD_LIBRARY_PATH="/usr/lib64/pulseaudio:$LD_LIBRARY_PATH" ARG PYTHON_INTERPRETER diff --git a/docker/Dockerfile.manylinux_2_28_X64 b/docker/Dockerfile.manylinux_2_28_X64 index 11254ea..13121ad 100644 --- a/docker/Dockerfile.manylinux_2_28_X64 +++ b/docker/Dockerfile.manylinux_2_28_X64 @@ -1,31 +1,6 @@ -FROM quay.io/pypa/manylinux_2_28_x86_64 as base +FROM ghcr.io/insight-platform/manylinux_2_28_x64:v0.0.3 as builder -RUN dnf install -y epel-release -# RUN dnf config-manager --set-enabled crb -RUN dnf install -y --nogpgcheck https://download1.rpmfusion.org/free/el/rpmfusion-free-release-8.noarch.rpm -RUN dnf install -y --nogpgcheck https://download1.rpmfusion.org/nonfree/el/rpmfusion-nonfree-release-8.noarch.rpm -RUN dnf install -y ffmpeg ffmpeg-devel -RUN dnf install -y clang clang-devel -ENV PATH="/root/.cargo/bin:/opt/python/cp37-cp37m/bin:/opt/python/cp38-cp38/bin:/opt/python/cp39-cp39/bin:/opt/python/cp310-cp310/bin:/opt/python/cp311-cp311/bin:/opt/python/cp312-cp312/bin:$PATH" -RUN pip3 install maturin==0.15 patchelf cffi ziglang sccache>=0.4.0 - -WORKDIR /opt -COPY docker/install-basic-deps-manylinux.sh . -RUN bash /opt/install-basic-deps-manylinux.sh - -FROM base as chef -ENV PATH="/root/.cargo/bin:$PATH" -RUN rustc -V - -FROM chef AS planner -WORKDIR /opt -COPY . . -RUN cargo chef prepare --recipe-path recipe.json - -FROM chef AS builder WORKDIR /opt -COPY --from=planner /opt/recipe.json recipe.json -RUN cargo chef cook --release --recipe-path recipe.json COPY . . ENV LD_LIBRARY_PATH="/usr/lib64/pulseaudio:$LD_LIBRARY_PATH" ARG PYTHON_INTERPRETER diff --git a/docker/Dockerfile.u2004 b/docker/Dockerfile.u2204 similarity index 83% rename from docker/Dockerfile.u2004 rename to docker/Dockerfile.u2204 index 15e0baf..cbbcd1d 100644 --- a/docker/Dockerfile.u2004 +++ b/docker/Dockerfile.u2204 @@ -1,8 +1,8 @@ -FROM ubuntu:20.04 as base +FROM ubuntu:22.04 as base WORKDIR /opt -COPY docker/install-basic-deps-u2004.sh . -RUN bash /opt/install-basic-deps-u2004.sh +COPY docker/install-basic-deps-u2204.sh . +RUN bash /opt/install-basic-deps-u2204.sh FROM base as chef ENV PATH="/root/.cargo/bin:$PATH" diff --git a/docker/install-basic-deps-manylinux.sh b/docker/install-basic-deps-manylinux.sh deleted file mode 100644 index a5a8993..0000000 --- a/docker/install-basic-deps-manylinux.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash - -set -e - -curl -o rustup.sh --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -sh rustup.sh -y -source $HOME/.cargo/env -rustup update -rustc -V - -cargo install cargo-chef --locked - - diff --git a/docker/install-basic-deps-u2004.sh b/docker/install-basic-deps-u2204.sh similarity index 100% rename from docker/install-basic-deps-u2004.sh rename to docker/install-basic-deps-u2204.sh diff --git a/src/lib.rs b/src/lib.rs index a7e9816..b5045b9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,12 +6,13 @@ use ffmpeg_next::format::{input_with_dictionary, Pixel}; use ffmpeg_next::log::Level; use ffmpeg_next::software::converter; use log::{debug, error, info, warn}; +use parking_lot::Mutex; use pyo3::exceptions::PyBrokenPipeError; use pyo3::prelude::*; use pyo3::types::PyBytes; use std::collections::HashMap; use std::path::Path; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use std::thread::{spawn, JoinHandle}; use std::time::SystemTime; @@ -123,10 +124,7 @@ pub struct FFMpegSource { impl Drop for FFMpegSource { fn drop(&mut self) { { - let mut exit_signal = self - .exit_signal - .lock() - .expect("Exit mutex must be always locked without problems"); + let mut exit_signal = self.exit_signal.lock(); *exit_signal = true; } let t = self.thread.take(); @@ -145,10 +143,7 @@ fn handle( ) { let mut queue_full_skipped_count = 0; ffmpeg::init().expect("FFmpeg initialization must be successful"); - let ll = log_level - .lock() - .expect("Log level mutex must always be available") - .take(); + let ll = log_level.lock().take(); if let Some(l) = ll { info!("Setting log level to {:?}", l); @@ -206,13 +201,10 @@ fn handle( let mut skip_until_first_key_frame = true; for (stream, packet) in ictx.packets() { - if *signal.lock().expect("Mutex is poisoned. Critical error.") { + if *signal.lock() { break; } - let ll = log_level - .lock() - .expect("Log level mutex must always be available") - .take(); + let ll = log_level.lock().take(); if let Some(l) = ll { info!("Setting log level to {:?}", l); @@ -416,11 +408,7 @@ impl FFMpegSource { #[setter] pub fn log_level(&self, ffmpeg_log_level: FFmpegLogLevel) { - let mut ll = self - .log_level - .lock() - .expect("Log Level mutex must be available"); - + let mut ll = self.log_level.lock(); *ll = Some(assign_log_level(ffmpeg_log_level)); } } diff --git a/test_decode.py b/test_decode.py index 2d07dc2..32d59df 100644 --- a/test_decode.py +++ b/test_decode.py @@ -5,9 +5,9 @@ if __name__ == '__main__': s = FFMpegSource("/dev/video0", - params={"video_size": "1280x720", "c:v": "v4l2m2m", "input_format": "mjpeg"}, + params={"video_size": "1920x1080", "c:v": "v4l2m2m", "input_format": "mjpeg"}, queue_len=100, - decode=True, + decode=False, ffmpeg_log_level=FFmpegLogLevel.Info) s.log_level = FFmpegLogLevel.Panic while True: @@ -15,15 +15,15 @@ p = s.video_frame() res = p.payload_as_bytes() # 1944 2592 - print(p.frame_height, p.frame_width) - res = np.frombuffer(res, dtype=np.uint8) - res = np.reshape(res, (p.frame_height, p.frame_width, 3)) + #print(p.frame_height, p.frame_width) + #res = np.frombuffer(res, dtype=np.uint8) + #res = np.reshape(res, (p.frame_height, p.frame_width, 3)) end = time.time() print(p.codec, p.pixel_format, p.queue_len, "all_time={}".format(int(end * 1000 - p.frame_received_ts)), "python_time={}".format(int(end * 1000 - p.frame_processed_ts))) - cv2.imshow('Image', res) - if cv2.waitKey(1) & 0xFF == ord('q'): - break + # cv2.imshow('Image', res) + #if cv2.waitKey(1) & 0xFF == ord('q'): + # break except BrokenPipeError: print("EOS") break