From 92f4203bc2990323621ac9a4a12a9c6030d5544e Mon Sep 17 00:00:00 2001 From: mofeng-git Date: Mon, 12 Oct 2026 22:53:12 +0800 Subject: [PATCH] =?UTF-8?q?build:=20=E5=90=AF=E7=94=A8=E6=98=BE=E5=BC=8F?= =?UTF-8?q?=20RKMPP=20=E6=9E=84=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.toml | 1 + build/build-images.sh | 8 ++++++-- build/package-docker.sh | 8 ++++++-- libs/hwcodec/build.rs | 10 ++++------ libs/hwcodec/src/ffmpeg_ram/mod.rs | 4 ++-- libs/hwcodec/src/lib.rs | 4 ++-- src/video/capture/linux.rs | 22 +++++++++++----------- src/video/capture/status.rs | 4 ++-- src/video/codec/mod.rs | 2 +- src/video/pipeline/encoder_state.rs | 18 +++++++++--------- src/video/pipeline/shared.rs | 16 ++++++++-------- 11 files changed, 52 insertions(+), 45 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6c263e27..27d03a16 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,6 +11,7 @@ categories = ["embedded", "network-programming"] [features] default = ["desktop"] +rkmpp = ["hwcodec/rkmpp"] desktop = [ "dep:tokio", "dep:tokio-util", diff --git a/build/build-images.sh b/build/build-images.sh index 2c1a9d85..933b843f 100755 --- a/build/build-images.sh +++ b/build/build-images.sh @@ -18,6 +18,10 @@ ARCH_MAP=( # Build for specific architecture using cross build_arch() { local rust_target="$1" + local feature_args=() + case "$rust_target" in + aarch64-*|armv7-*) feature_args=(--features rkmpp) ;; + esac case "${CHINAMIRRO:-}" in 1|true|TRUE|yes|YES|on|ON) @@ -40,13 +44,13 @@ build_arch() { CARGO_NET_GIT_FETCH_WITH_CLI=true \ RUSTUP_DIST_SERVER="$rust_dist" \ RUSTUP_UPDATE_ROOT="$rust_root" \ - cross build --release --target "$rust_target" + cross build --release --target "$rust_target" "${feature_args[@]}" return ;; esac echo "=== Building: $rust_target (via cross with custom Dockerfile) ===" - cross build --release --target "$rust_target" + cross build --release --target "$rust_target" "${feature_args[@]}" } # Main diff --git a/build/package-docker.sh b/build/package-docker.sh index ae113245..7d64024f 100755 --- a/build/package-docker.sh +++ b/build/package-docker.sh @@ -268,14 +268,18 @@ build_for_platform() { if [ "$BUILD_BINARY" = true ]; then echo_info "Building binary with cross..." cd "$PROJECT_ROOT" - cross build --release --target "$target" + local feature_args=() + case "$target" in + aarch64-*|armv7-*) feature_args=(--features rkmpp) ;; + esac + cross build --release --target "$target" "${feature_args[@]}" fi # Check binary exists local binary="$PROJECT_ROOT/target/$target/release/one-kvm" if [ ! -f "$binary" ]; then echo_error "Binary not found: $binary" - echo_error "Build it first: cross build --release --target $target" + echo_error "Build it first: ./build/build-images.sh" exit 1 fi diff --git a/libs/hwcodec/build.rs b/libs/hwcodec/build.rs index 08441f97..a95fa5de 100644 --- a/libs/hwcodec/build.rs +++ b/libs/hwcodec/build.rs @@ -154,7 +154,7 @@ mod ffmpeg { let include_dir = Path::new(&custom_lib_path).join("include"); let avcodec_lib = lib_dir.join("libavcodec.a"); - if avcodec_lib.exists() { + if avcodec_lib.exists() && use_static { println!("cargo:info=Using custom FFmpeg from {}", custom_lib_path); println!("cargo:rustc-link-search=native={}", lib_dir.display()); builder.include(&include_dir); @@ -171,7 +171,7 @@ mod ffmpeg { println!("cargo:rustc-link-lib=va-drm"); println!("cargo:rustc-link-lib=va-x11"); // Required for vaGetDisplay println!("cargo:rustc-link-lib=mfx"); - } else { + } else if std::env::var_os("CARGO_FEATURE_RKMPP").is_some() { for lib in ["rockchip_mpp", "rga"] { if !lib_dir.join(format!("lib{lib}.a")).exists() { panic!("missing static library: lib{lib}.a"); @@ -400,8 +400,7 @@ mod ffmpeg { // RKMPP decode only exists on ARM builds where FFmpeg is compiled with RKMPP support. // Avoid compiling this file on x86/x64 where `AV_HWDEVICE_TYPE_RKMPP` doesn't exist. let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default(); - let enable_rkmpp = matches!(target_arch.as_str(), "aarch64" | "arm") - || std::env::var_os("CARGO_FEATURE_RKMPP").is_some(); + let enable_rkmpp = std::env::var_os("CARGO_FEATURE_RKMPP").is_some(); if enable_rkmpp { builder.file(ffmpeg_ram_dir.join("ffmpeg_ram_decode.cpp")); if enable_rkmpp { @@ -459,8 +458,7 @@ mod ffmpeg { .unwrap(); let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default(); - let enable_rkmpp = matches!(target_arch.as_str(), "aarch64" | "arm") - || std::env::var_os("CARGO_FEATURE_RKMPP").is_some(); + let enable_rkmpp = std::env::var_os("CARGO_FEATURE_RKMPP").is_some(); if enable_rkmpp { // Include RGA headers for NV16->NV12 conversion (RGA im2d API) let rga_sys_dirs = [ diff --git a/libs/hwcodec/src/ffmpeg_ram/mod.rs b/libs/hwcodec/src/ffmpeg_ram/mod.rs index f90b0ac6..435f6b4c 100644 --- a/libs/hwcodec/src/ffmpeg_ram/mod.rs +++ b/libs/hwcodec/src/ffmpeg_ram/mod.rs @@ -9,12 +9,12 @@ use std::ffi::c_int; include!(concat!(env!("OUT_DIR"), "/ffmpeg_ram_ffi.rs")); -#[cfg(any(target_arch = "aarch64", target_arch = "arm", feature = "rkmpp"))] +#[cfg(feature = "rkmpp")] pub mod decode; // Provide a small stub on non-ARM builds so dependents can still compile, but decoder // construction will fail (since the C++ RKMPP decoder isn't built/linked). -#[cfg(not(any(target_arch = "aarch64", target_arch = "arm", feature = "rkmpp")))] +#[cfg(not(feature = "rkmpp"))] pub mod decode { use crate::ffmpeg::AVPixelFormat; diff --git a/libs/hwcodec/src/lib.rs b/libs/hwcodec/src/lib.rs index b1e01c37..6c81cc8e 100644 --- a/libs/hwcodec/src/lib.rs +++ b/libs/hwcodec/src/lib.rs @@ -2,12 +2,12 @@ pub mod capture; pub mod common; pub mod ffmpeg; -#[cfg(any(target_arch = "aarch64", target_arch = "arm", feature = "rkmpp"))] +#[cfg(feature = "rkmpp")] pub mod ffmpeg_hw; pub mod ffmpeg_ram; #[cfg(all( target_os = "linux", - any(target_arch = "aarch64", target_arch = "arm", feature = "rkmpp") + feature = "rkmpp" ))] pub mod rkmpp_dmabuf; diff --git a/src/video/capture/linux.rs b/src/video/capture/linux.rs index 4135af44..d00cd5dd 100644 --- a/src/video/capture/linux.rs +++ b/src/video/capture/linux.rs @@ -3,7 +3,7 @@ use std::fs::File; use std::io; use std::os::fd::AsFd; -#[cfg(any(target_arch = "aarch64", target_arch = "arm"))] +#[cfg(feature = "rkmpp")] use std::os::fd::OwnedFd; use std::os::unix::fs::OpenOptionsExt; use std::path::{Path, PathBuf}; @@ -31,7 +31,7 @@ use crate::video::device::VideoControlMode; use crate::video::format::{PixelFormat, Resolution}; use crate::video::signal::SignalStatus; -#[cfg(any(test, target_arch = "aarch64", target_arch = "arm"))] +#[cfg(any(test, feature = "rkmpp"))] #[path = "dmabuf_layout.rs"] mod dmabuf_layout; @@ -79,7 +79,7 @@ pub struct CaptureStream { bridge_kind: Option, native_hdmirx_state: Option, native_hdmirx_next_state_check: Option, - #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] + #[cfg(feature = "rkmpp")] dma_layout_bytes: Option, } @@ -333,7 +333,7 @@ impl CaptureStream { mappings.push(plane_maps); } - #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] + #[cfg(feature = "rkmpp")] let dma_layout_bytes = PixelFormat::from_v4l2r(actual_fmt.pixelformat).and_then(|format| { dmabuf_layout::DmaCaptureLayout { native_hdmi: is_native_hdmirx, @@ -364,7 +364,7 @@ impl CaptureStream { bridge_kind: bridge.kind, native_hdmirx_state, native_hdmirx_next_state_check, - #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] + #[cfg(feature = "rkmpp")] dma_layout_bytes, }; @@ -491,7 +491,7 @@ impl CaptureStream { /// Native HDMI NV12/BGR24 and single-planar USB UVC YUYV/NV12/RGB24/MJPEG. /// Actual EXPBUF/import support is probed separately; failure retains copy. - #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] + #[cfg(feature = "rkmpp")] pub(crate) fn supports_rkmpp_dmabuf(&self) -> bool { self.dma_layout_bytes.is_some_and(|minimum| { (2..=16).contains(&self.mappings.len()) @@ -502,7 +502,7 @@ impl CaptureStream { }) } - #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] + #[cfg(feature = "rkmpp")] pub(crate) fn export_dmabufs(&self) -> io::Result> { if !self.supports_rkmpp_dmabuf() { return Err(io::Error::new( @@ -524,7 +524,7 @@ impl CaptureStream { /// Run a synchronous consumer while a buffer is dequeued. QBUF occurs only /// after the callback returns, including its error path. Consumers must end /// hardware access before returning; see hwcodec::rkmpp_dmabuf::encode. - #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] + #[cfg(feature = "rkmpp")] pub(crate) fn with_next_dmabuf( &mut self, consume: impl FnOnce(usize, usize, Option) -> T, @@ -843,17 +843,17 @@ impl CaptureStream { } } -#[cfg(any(test, target_arch = "aarch64", target_arch = "arm"))] +#[cfg(any(test, feature = "rkmpp"))] struct BufferReturn io::Result<()>>(Option); -#[cfg(any(test, target_arch = "aarch64", target_arch = "arm"))] +#[cfg(any(test, feature = "rkmpp"))] impl io::Result<()>> BufferReturn { fn finish(mut self) -> io::Result<()> { self.0.take().expect("capture lease already returned")() } } -#[cfg(any(test, target_arch = "aarch64", target_arch = "arm"))] +#[cfg(any(test, feature = "rkmpp"))] impl io::Result<()>> Drop for BufferReturn { fn drop(&mut self) { if let Some(return_buffer) = self.0.take() { diff --git a/src/video/capture/status.rs b/src/video/capture/status.rs index 0238a8b2..42074346 100644 --- a/src/video/capture/status.rs +++ b/src/video/capture/status.rs @@ -4,14 +4,14 @@ use std::io; #[cfg(any( test, - all(target_os = "linux", any(target_arch = "aarch64", target_arch = "arm")) + all(target_os = "linux", feature = "rkmpp") ))] use crate::video::device::VideoControlMode; use crate::video::signal::SignalStatus; #[cfg(any( test, - all(target_os = "linux", any(target_arch = "aarch64", target_arch = "arm")) + all(target_os = "linux", feature = "rkmpp") ))] pub(crate) fn capture_recovery_status( control_mode: VideoControlMode, diff --git a/src/video/codec/mod.rs b/src/video/codec/mod.rs index cfa663a3..82f8ab2e 100644 --- a/src/video/codec/mod.rs +++ b/src/video/codec/mod.rs @@ -17,7 +17,7 @@ pub mod video_codec; pub mod vp8; pub mod vp9; -#[cfg(all(feature = "desktop", any(target_arch = "aarch64", target_arch = "arm")))] +#[cfg(all(feature = "desktop", feature = "rkmpp"))] pub mod mjpeg_rkmpp; pub use convert::{MjpegToNv12Decoder, PixelConverter, Yuv420pBuffer}; diff --git a/src/video/pipeline/encoder_state.rs b/src/video/pipeline/encoder_state.rs index 0f8eb075..5f0ad699 100644 --- a/src/video/pipeline/encoder_state.rs +++ b/src/video/pipeline/encoder_state.rs @@ -8,7 +8,7 @@ use crate::video::codec::vp8::{VP8Config, VP8Encoder}; use crate::video::codec::vp9::{VP9Config, VP9Encoder}; use crate::video::format::{PixelFormat, Resolution}; use bytes::Bytes; -#[cfg(any(target_arch = "aarch64", target_arch = "arm"))] +#[cfg(feature = "rkmpp")] use hwcodec::ffmpeg_hw::{ last_error_message as ffmpeg_hw_last_error, HwMjpegH26xConfig, HwMjpegH26xPipeline, }; @@ -22,9 +22,9 @@ pub(super) struct EncoderThreadState { pub(super) nv12_converter: Option, pub(super) yuv420p_converter: Option, pub(super) encoder_needs_yuv420p: bool, - #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] + #[cfg(feature = "rkmpp")] pub(super) ffmpeg_hw_pipeline: Option, - #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] + #[cfg(feature = "rkmpp")] pub(super) ffmpeg_hw_enabled: bool, pub(super) fps: u32, pub(super) codec: VideoEncoderType, @@ -347,9 +347,9 @@ pub(super) fn build_encoder_state( } }; - #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] + #[cfg(feature = "rkmpp")] let is_rkmpp_encoder = selected_codec_name.contains("rkmpp"); - #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] + #[cfg(feature = "rkmpp")] if needs_mjpeg_decode && is_rkmpp_encoder && matches!( @@ -389,9 +389,9 @@ pub(super) fn build_encoder_state( nv12_converter: None, yuv420p_converter: None, encoder_needs_yuv420p: false, - #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] + #[cfg(feature = "rkmpp")] ffmpeg_hw_pipeline: Some(pipeline), - #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] + #[cfg(feature = "rkmpp")] ffmpeg_hw_enabled: true, fps: config.fps, codec: config.output_codec, @@ -573,9 +573,9 @@ pub(super) fn build_encoder_state( nv12_converter, yuv420p_converter, encoder_needs_yuv420p: needs_yuv420p, - #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] + #[cfg(feature = "rkmpp")] ffmpeg_hw_pipeline: None, - #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] + #[cfg(feature = "rkmpp")] ffmpeg_hw_enabled: false, fps: config.fps, codec: config.output_codec, diff --git a/src/video/pipeline/shared.rs b/src/video/pipeline/shared.rs index 31e6c75b..bca9b9df 100644 --- a/src/video/pipeline/shared.rs +++ b/src/video/pipeline/shared.rs @@ -35,13 +35,13 @@ use super::encoder_state::{build_encoder_state, should_parallel_decode_mjpeg, En use super::frame_mailbox::{FrameMailbox, PublishResult}; use super::mjpeg_admission::{MjpegAdmissionPolicy, MjpegAdmissionStage, MjpegDropReason}; -#[cfg(all(target_os = "linux", any(target_arch = "aarch64", target_arch = "arm")))] +#[cfg(all(target_os = "linux", feature = "rkmpp"))] #[path = "dmabuf.rs"] mod dmabuf; #[cfg(any( test, - all(target_os = "linux", any(target_arch = "aarch64", target_arch = "arm")) + all(target_os = "linux", feature = "rkmpp") ))] fn rkmpp_dma_eligible( backend: Option, @@ -269,7 +269,7 @@ fn spawn_mjpeg_decode_workers( senders } -#[cfg(any(target_arch = "aarch64", target_arch = "arm"))] +#[cfg(feature = "rkmpp")] use hwcodec::ffmpeg_hw::last_error_message as ffmpeg_hw_last_error; /// Encoded video frame for distribution @@ -726,7 +726,7 @@ impl SharedVideoPipeline { match cmd { PipelineCmd::SetBitrate { preset } => { let bitrate_kbps = preset.bitrate_kbps(); - #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] + #[cfg(feature = "rkmpp")] if state.ffmpeg_hw_enabled { if let Some(ref mut pipeline) = state.ffmpeg_hw_pipeline { pipeline @@ -1154,7 +1154,7 @@ impl SharedVideoPipeline { Err(e) => return Err(e), }; - #[cfg(all(target_os = "linux", any(target_arch = "aarch64", target_arch = "arm")))] + #[cfg(all(target_os = "linux", feature = "rkmpp"))] if dmabuf::eligible(&config) { if let Some(stream) = preopened.as_ref().filter(|s| s.supports_rkmpp_dmabuf()) { match dmabuf::prepare(stream, &config) { @@ -1817,7 +1817,7 @@ impl SharedVideoPipeline { let pts_ms = self.pts_ms(); - #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] + #[cfg(feature = "rkmpp")] if state.ffmpeg_hw_enabled { if input_format != PixelFormat::Mjpeg { return Err(AppError::VideoError( @@ -2527,9 +2527,9 @@ mod tests { nv12_converter: None, yuv420p_converter: None, encoder_needs_yuv420p: false, - #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] + #[cfg(feature = "rkmpp")] ffmpeg_hw_pipeline: None, - #[cfg(any(target_arch = "aarch64", target_arch = "arm"))] + #[cfg(feature = "rkmpp")] ffmpeg_hw_enabled: false, fps: 30, codec: VideoEncoderType::H264,