Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,266 changes: 746 additions & 520 deletions Cargo.lock

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ members = [
"liveman",
"livetwo",
"livecam",
"livesrc",
]

[workspace.package]
Expand All @@ -71,7 +72,7 @@ webrtc = { git = "https://github.com/webrtc-rs/webrtc", rev = "4da5280" }
sdp = { git = "https://github.com/webrtc-rs/webrtc", rev = "4da5280" }

axum = "0.8"
axum-extra = "0.12"
axum-extra = "0.10"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

downgrade ?

tower-http = "0.6"
rust-embed = "8.7"
mime_guess = "2.0"
Expand Down Expand Up @@ -124,15 +125,15 @@ serde_json = { workspace = true }
anyhow = { workspace = true }
opendal = "0.55.0"

toml = "1.0"
toml = "0.9"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

downgrade ?

tracing-subscriber = { version = "0.3", features = ["env-filter"] }

[features]
webui = ["liveion/webui", "liveman/webui", "livecam/webui"]
net4mqtt = ["liveion/net4mqtt", "liveman/net4mqtt"]
recorder = ["liveion/recorder", "liveman/recorder"]

source = ["liveion/source"]
source-sdp = ["liveion/source-sdp"]
source-rtsp = ["liveion/source-rtsp"]
source-rtp = ["liveion/source-rtp"]
source-libcamera = ["liveion/source-libcamera"]
source-all = ["liveion/source-all"]
27 changes: 27 additions & 0 deletions build_all.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/bash
set -e

echo "======================================="
echo " Live777 Dual-Platform Builder"
echo "======================================="

# 1. 编译 Raspberry Pi 版本
echo ">>> Building for Raspberry Pi (live777_pi)..."
unset CXXFLAGS
cargo clean -p liveion # 确保底层 C++ 构建宏被清理
cargo build --release -j 2 --features source-libcamera,webui
cp target/release/live777 live777_pi
echo "[OK] Pi Output is ready: ./live777_pi"

echo "---------------------------------------"

# 2. 编译 RDK X5 版本
echo ">>> Building for D-Robotics RDK X5 (live777_rdk)..."
export CXXFLAGS="-DPLATFORM_RDK=ON"
cargo clean -p liveion # 确保底层 C++ 构建宏被重新触发
cargo build --release -j 2 --features source-libcamera,webui
cp target/release/live777 live777_rdk
echo "[OK] RDK Output is ready: ./live777_rdk"

echo "======================================="
echo "Done! Please use live777_pi for Raspberry Pi and live777_rdk for RDK X5."
18 changes: 11 additions & 7 deletions conf/live777.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,14 @@ url = "udp://0.0.0.0:8891?host=127.0.0.1&port=8890"
# listen = "[::]:7777"
# Cross-Origin Resource Sharing (CORS)
# reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
# cors = false
cors = true

[[ice_servers]]
urls = [
"stun:stun.22333.fun",
"stun:cn.22333.fun",
"stun:stun.l.google.com:19302",
[[ice_servers]]
urls = [
"stun:stun.22333.fun",
"stun:cn.22333.fun",
"stun:stun.l.google.com:19302",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't change this Indentation style

]

[stream]

# Need enabled `--features=source`
Expand All @@ -39,6 +38,11 @@ urls = [
# - RTSP: rtsp://username:password@host:port/path
# url = "rtsp://username:password@host:port/path"

# 核心测试:使用原生 libcamera-bridge 方案 (普适性标准方案)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

English comment

[[stream.sources]]
stream_id = "pi_cam"
url = "libcamera://0?width=640&height=480&fps=30"

[recorder]
# Stream name patterns for auto-recording, supports wildcards
# auto_streams = ["*"] # Record all streams
Expand Down
19 changes: 19 additions & 0 deletions conf/livesrc-rdk.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[http]
listen = "0.0.0.0:7777"
cors = true

[[ice_servers]]
urls = [
"stun:stun.l.google.com:19302",
]

[stream]
[[stream.sources]]
stream_id = "usbcam"
# RDK X5 专用 V4L2 配置:
# 1. 务必确认 /dev/video0 是出流节点,而非 metadata 节点(可用 v4l2-ctl --list-devices 确认)
# 2. 建议通过 v4l2-ctl 关闭自动曝光,或码率设为 1.5Mbps 防止花屏
url = "v4l2:///dev/video0?width=640&height=480&fps=30&bitrate=1500000"

[log]
level = "info"
25 changes: 25 additions & 0 deletions conf/livesrc-rpicam.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Live777 最终对齐版配置文件 (修正字段名为 stream_id)

[http]
listen = "0.0.0.0:7777"

[log]
level = "debug"

# 严格匹配 liveion/src/config.rs 中的构造
[stream]
[[stream.sources]]
stream_id = "camera"
url = "libcamera://0?width=640&height=480&fps=30"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need unified config in stream


# 同时保留原有的 paths 结构以确保万一
[paths.camera]
source = "libcamera"
source_on_demand = false
rtp_port = 5004

[paths.camera.libcamera]
width = 640
height = 480
fps = 30
camera_id = 0
14 changes: 11 additions & 3 deletions liveion/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,16 @@ reqwest = { workspace = true }
rand = "0.10"
serde = { workspace = true, features = ["serde_derive"] }
serde_json = { workspace = true }
tokio = { workspace = true }
tokio = { workspace = true, features = ["process"] }
tokio-stream = "0.1.15"
async-stream = "0.3.5"
tracing = { workspace = true }
webrtc = { workspace = true }
uuid = { workspace = true }
libc = "0.2"

async-trait = "0.1"
chrono = "0.4"
chrono = { version = "0.4", features = ["serde"] }
lazy_static = "1.4.0"
md-5 = "0.10.6"
prometheus = "0.14"
Expand All @@ -55,6 +56,7 @@ scuffle-h265 = { version = "0.2.2", optional = true }
glob = "0.3"
url = { workspace = true, optional = true }
fs2 = "0.4"
base64 = { workspace = true }

[features]
webui = ["dep:rust-embed", "dep:mime_guess"]
Expand All @@ -72,7 +74,13 @@ recorder = [
source = ["dep:rtsp", "dep:url", "dep:bytes"]
source-sdp = ["source"]
source-rtsp = ["source"]
source-all = ["source-sdp", "source-rtsp"]
source-rtp = ["source"]
source-libcamera = ["source"]
source-all = ["source-sdp", "source-rtsp", "source-rtp", "source-libcamera"]

[dev-dependencies]
tempfile = "3.26"

[build-dependencies]
cmake = "0.1"
pkg-config = "0.3"
85 changes: 85 additions & 0 deletions liveion/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
use std::env;
use std::path::PathBuf;

fn main() {
// Only run if the source-libcamera feature is enabled
if env::var("CARGO_FEATURE_SOURCE_LIBCAMERA").is_err() {
return;
}

let target = env::var("TARGET").unwrap_or_default();
let is_rdk = target.contains("aarch64");

// 1. Rerun-if-changed for all platforms
println!("cargo:rerun-if-changed=../livesrc/libcamera-bridge/bridge_ffi.h");
if is_rdk {
println!("cargo:rerun-if-changed=../livesrc/libcamera-bridge/encoder_rdk.cpp");
println!("cargo:rerun-if-changed=../livesrc/libcamera-bridge/v4l2_capture_rdk.cpp");
println!("cargo:rerun-if-changed=../livesrc/libcamera-bridge/bridge_v4l2_rdk_ffi.cpp");
} else {
println!("cargo:rerun-if-changed=../livesrc/libcamera-bridge/camera.cpp");
println!("cargo:rerun-if-changed=../livesrc/libcamera-bridge/encoder.cpp");
println!("cargo:rerun-if-changed=../livesrc/libcamera-bridge/v4l2_capture.cpp");
println!("cargo:rerun-if-changed=../livesrc/libcamera-bridge/bridge_v4l2_ffi.cpp");
}

// 2. Setup Sysroot handles
if is_rdk {
if let Ok(sysroot) = env::var("RDK_SYSROOT") {
let sysroot = PathBuf::from(sysroot);
println!("cargo:rustc-link-search=native={}", sysroot.join("usr/lib").display());
println!("cargo:rustc-link-search=native={}", sysroot.join("lib").display());
unsafe { env::set_var("PKG_CONFIG_ALLOW_CROSS", "1"); }
}
} else if let Ok(sysroot) = env::var("PI_SYSROOT") {
let sysroot = PathBuf::from(sysroot);
let pkg_config_path = sysroot.join("usr/lib/arm-linux-gnueabihf/pkgconfig");
unsafe {
env::set_var("PKG_CONFIG_SYSROOT_DIR", &sysroot);
env::set_var("PKG_CONFIG_PATH", pkg_config_path);
env::set_var("PKG_CONFIG_ALLOW_CROSS", "1");
}
println!("cargo:rustc-link-search=native={}", sysroot.join("usr/lib/arm-linux-gnueabihf").display());
}

// 3. Find libcamera (RPi Only)
if !is_rdk {
let mut config = pkg_config::Config::new();
config.atleast_version("0.1");
if let Ok(lib) = config.probe("libcamera") {
for path in lib.include_paths { println!("cargo:include={}", path.display()); }
}
}

// 4. Build the C++ bridge library using CMake
let mut cmake_config = cmake::Config::new("../livesrc/libcamera-bridge");
cmake_config.define("CMAKE_POSITION_INDEPENDENT_CODE", "ON");

if is_rdk {
cmake_config.define("PLATFORM_RDK", "ON");
}

let dst = cmake_config.build();

println!("cargo:rustc-link-search=native={}/lib", dst.display());
println!("cargo:rustc-link-lib=static=cambridge");

// 5. Link CORE dependencies
println!("cargo:rustc-link-lib=dylib=stdc++");
if is_rdk {
// Direct path for RDK X5 firmware libraries
println!("cargo:rustc-link-search=native=/usr/hobot/lib");
println!("cargo:rustc-link-search=native=/usr/lib");

println!("cargo:rustc-link-lib=dylib=multimedia");
println!("cargo:rustc-link-lib=dylib=hbmem");
println!("cargo:rustc-link-lib=dylib=vpf");
} else {
println!("cargo:rustc-link-lib=dylib=camera");
println!("cargo:rustc-link-lib=dylib=camera-base");
println!("cargo:rustc-link-lib=dylib=event");
}

println!("cargo:rustc-link-arg=-Wl,--allow-shlib-undefined");
println!("cargo:rustc-link-arg=-Wl,--unresolved-symbols=ignore-in-shared-libs");
}
6 changes: 5 additions & 1 deletion liveion/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -408,9 +408,13 @@ impl SourceConfig {
&& !url_lower.starts_with("rtsps://")
&& !url_lower.starts_with("file://")
&& !url_lower.ends_with(".sdp")
&& !url_lower.starts_with("rtp://")
&& !url_lower.starts_with("exec://")
&& !url_lower.starts_with("libcamera://")
&& !url_lower.starts_with("v4l2://")
{
anyhow::bail!(
"Invalid URL format: {}. Must be rtsp://, rtsps://, file://, or end with .sdp",
"Invalid URL format: {}. Must be rtsp://, rtsps://, file://, rtp://, exec://, libcamera://, v4l2:// or end with .sdp",
self.url
);
}
Expand Down
Loading
Loading